epezent / implot

Immediate Mode Plotting
MIT License
4.65k stars 517 forks source link

Support for long double ? #379

Closed pthom closed 2 years ago

pthom commented 2 years ago

Hello,

I found that the various IMPLOT_TMP template implementations do not support long double.

See extract from implot_items.cpp:

template <typename T>
void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags, int offset, int stride) {
    GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count);
    PlotLineEx(label_id, getter, flags);
}

template IMPLOT_API void PlotLine<ImS8>(const char* label_id, const ImS8* xs, const ImS8* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImU8>(const char* label_id, const ImU8* xs, const ImU8* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImS16>(const char* label_id, const ImS16* xs, const ImS16* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImU16>(const char* label_id, const ImU16* xs, const ImU16* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImS32>(const char* label_id, const ImS32* xs, const ImS32* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImU32>(const char* label_id, const ImU32* xs, const ImU32* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImS64>(const char* label_id, const ImS64* xs, const ImS64* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<ImU64>(const char* label_id, const ImU64* xs, const ImU64* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<float>(const char* label_id, const float* xs, const float* ys, int count, ImPlotLineFlags flags, int offset, int stride);
template IMPLOT_API void PlotLine<double>(const char* label_id, const double* xs, const double* ys, int count, ImPlotLineFlags flags, int offset, int stride);

"long double" is rather unusual, but it might help some people.

On my side, I found a way to work without it, so there is no real need for me. Feel free to close if you think it is not worth the effort.

Thanks!

epezent commented 2 years ago

I was under the impression that long double was just double for many architectures and compilers, and figured very folks would be using it otherwise. If anything, I'd like to remove uncommon supported types rather than add more (each additional type we support adds significantly to compile times).

Have you tried instantiating these functions with a long double template argument? I think it would work fine, and if so then I would recommend you make these changes to implot_items.cpp in your own fork.

pthom commented 2 years ago

Have you tried instantiating these functions with a long double template argument? I think it would work fine, and if so then I would recommend you make these changes to implot_items.cpp in your own fork.

Yes it works.

Note: the fact there is no standard for base type in C/C++ does not make it easy.

I was under the impression that long double was just double for many architectures and compilers, and figured very folks would be using it otherwise.

Actually, I saw that long double is 16 bytes with gcc and clang x86_64. Maybe this is what enables numpy to offer the float128 type (quote from numpy: "np.float128 provide only as much precision as np.longdouble, that is, 80 bits on most x86 machines and 64 bits in standard Windows builds.")

If you want to play, you can experiment with this demo on compiler explorer, which produced this:

x64 msvc2019

sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(unsigned int) = 4
sizeof(long) = 4
sizeof(unsigned long) = 4
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 8

x86 msvc2019

sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(unsigned int) = 4
sizeof(long) = 4
sizeof(unsigned long) = 4
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 8

x86_64 clang 14.0

sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(unsigned int) = 4
sizeof(long) = 8
sizeof(unsigned long) = 8
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 16

x86_64 gcc(trunk)

sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(unsigned int) = 4
sizeof(long) = 8
sizeof(unsigned long) = 8
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 16
ocornut commented 2 years ago

If supported I guess that sort of stuff we be better under a compile-time define ?

pthom commented 2 years ago

@ocornut , @epezent : thanks for your inputs. I propose a fix in this related PR