Не могу подобрать. %lle и %Le не подходят. Другие спецификации перепробовал тоже. Кое-где %Q упоминается, но у меня не работает
Вычисляю машинное эпсилон и не получается для 128-битной плавучки его правильно отобразить.
Вот пример кода, вычисления машинного эпсилон для разных типов (вообще там занятные особенности всплыли работы gcc, особенно если в ассемблерный листинг глянуть)
#include <stdio.h>
int main()
{
float e_float,eps_float=1.0;
double e_double,eps_double=1.0;
long double e_longdouble,eps_longdouble=1.0;
__float80 e__float80,eps__float80=1.0;
__float128 e__float128,eps__float128=1.0;
e_float=1+eps_float;
e_double=1+eps_double;
e_longdouble=1+eps_longdouble;
e__float80=1+eps__float80;
e__float128=1+eps__float128;
while (e_float!=1)
{
eps_float=(float)(eps_float/2);
e_float=(float)(eps_float+1);
}
while (e_double!=1)
{
eps_double=(double)(eps_double/2);
e_double=(double)(eps_double+1);
}
while (e_longdouble!=1)
{
eps_longdouble=(long double)(eps_longdouble/2);
e_longdouble=(long double)(eps_longdouble+1);
}
while (e__float80!=1)
{
eps__float80=(__float80)(eps__float80/2);
e__float80=(__float80)(eps__float80+1);
}
while (e__float128!=1)
{
eps__float128=(__float128)(eps__float128/2);
e__float128=(__float128)(eps__float128+1);
}
printf("size: float = %d double = %d long double = %d __float80= %d __float128= %d\n",sizeof(float),sizeof(double),sizeof(long double),sizeof(__float80),sizeof(__float128));
printf("float eps = %e \ndouble eps = %e \nlong double eps = %lle\n__float80 eps = %lle\n__float128 eps = %Le \n",eps_float,eps_double,eps_longdouble,eps__float80,eps__float128);
return 0;
}
Компилирую
$ gcc -mfpmath=387 gccfloats.c -o gccfloats-387
$ gcc -mfpmath=sse gccfloats.c -o gccfloats-sse
Запускаю. Оба варианта с 387 и sse дают один и тот же результат
size: float = 4 double = 8 long double = 16 __float80= 16 __float128= 16
float eps = 5.960464e-08
double eps = 1.110223e-16
long double eps = 5.421011e-20
__float80 eps = 5.421011e-20
__float128 eps = 0.000000e+00
Понятно, ноль там для __float128 быть не может, это результат какого-то округления при выводе.
Если с sse компилировать, то тоже самое. Пробовал вместо %Le написать %.числоf, так хоть %.50000f то будет 50 тысяч нулей. А это уже какая-то фигня.
Кто виноват и что делать? Как узнать машинное эпсилон для 128 битного типа с плавающей запятой.
Попутно любопытные открытия для себя сделал при просмотре ассемблерного листинга.
1. long double и __float80 - одно и тоже. По крайней мере для gcc 10.2.1 Впрочем, вроде где-то об этом было. Что интереснее, для расчета всегда используется x87-й блок, даже если -mfpmath=sse -msse2
2. Хотя long double - 80-ти битный тип, длинна 16 байт. Видимо из-за выравнивания
3. Для __float128 всегда используется sse2, даже если указано -mfpmath=387
Не понял, как можно заставить использовать avx и avx2