Является ли long double в C++ реализацией двоичного кода IEEE128?

Из https://en.wikipedia.org/wiki/Long_double:

В C++ long double относится к типу данных с плавающей запятой, который часто является более точным, чем двойная точность. Однако, как и в случае с другими типами с плавающей запятой C++, он может не обязательно отображаться в формате IEEE.

...

В компиляторе GNU C long double представляет собой 80-битную расширенную точность на процессорах x86 независимо от физического хранилища, используемого для типа (которое может быть 96- или 128-битным). На некоторых других архитектурах long double может быть double-double (например, на PowerPC) или 128-битной четверной точностью (например, на SPARC). Начиная с gcc 4.3, четверная точность также поддерживается на x86, но как нестандартный тип __float128, а не long double.

С gcc в Linux по умолчанию используется 80-битная расширенная точность; в некоторых операционных системах BSD (FreeBSD и OpenBSD) по умолчанию используется режим с двойной точностью, и длинные операции с двойной точностью эффективно сокращаются до двойной точности.

С другой стороны, компилятор Intel C++ для x86 по умолчанию включает режим повышенной точности. В OS X long double — это 80-битная расширенная точность.

Кажется, что действительно long double не может быть реализацией двоичного файла IEEE128, но почему бы не сделать это так? Почему в некоторых случаях по умолчанию используется 80-битное представление?


person Eduardo    schedule 11.10.2018    source источник
comment
Это имеет мало общего с c++, это вопрос конкретных платформ.   -  person Zereges    schedule 11.10.2018
comment
Потому что зачем связывать реализации рук? Поскольку стандарт предписывает только sizeof(long double) >= sizeof(double), реализациям разрешено предоставлять любую расширенную поддержку, которую они могут, или не предоставлять, если они не хотят иметь с ней дело.   -  person NathanOliver    schedule 11.10.2018
comment
Также обратите внимание, что нигде даже не говорится, что double нужно отображать в формат IEEE.   -  person NathanOliver    schedule 11.10.2018
comment
Похоже, вы ответили на свой вопрос как нет.   -  person interjay    schedule 11.10.2018
comment
В Windows x64 long double = double = двоичный файл IEEE-75464. Этот ABI решил вообще не иметь типа для x87 80-битной расширенной точности. Другие системы x86-64 отображают его как long double. Так что важен не компилятор, а целевой ABI. GCC для Windows будет следовать этому ABI.   -  person Peter Cordes    schedule 16.04.2019
comment
@PeterCordes Clang и GCC в Windows по умолчанию поддерживают расширенную точность long double. Однако вы можете отключить его с помощью -mlong-double-64. ICC также имеет параметр Qlong-double. для совместимости с MSVC и GCC   -  person phuclv    schedule 18.04.2019
comment
@phuclv: о, странно! Я предполагал, что GCC позаботится о совместимости ABI с MSVC, как и для других типов, но я думаю, что в основном никто не использует long double как часть структуры или в интерфейсах библиотеки функций arg/ret.   -  person Peter Cordes    schedule 19.04.2019
comment
@PeterCordes Я думаю, потому что вам не нужно связывать объекты GCC и MSVC вместе. Однако иногда возникали проблемы, потому что ранее mingw использовал среду выполнения MS, которая не поддерживает 80-битное длинное удвоение, поэтому вы не можете печатать длинные удвоения с помощью printf Спецификатор преобразования long double в C. В настоящее время они реализовали свою собственную среду выполнения, поэтому это больше не проблема.   -  person phuclv    schedule 19.04.2019
comment
@phuclv: вам действительно нужно выйти за границы DLL! Код gcc должен вызывать библиотеки DLL для Win32 API, а MS создает системные библиотеки DLL с помощью собственного компилятора. Или если вы хотите создать DLL, которую вы можете загрузить в Excel или что-то еще. Итак, да, как вы указываете, разница long double ABI ограничивает то, что вы можете делать с GCC в Windows. Если бы было больше различий в ABI для любых более часто используемых типов, это было бы огромной проблемой. (Но, насколько мне известно, их нет; GCC следует соглашению о вызовах Windows и правилам компоновки структур и в противном случае использует ту же ширину типа, например, 32-битный long.)   -  person Peter Cordes    schedule 19.04.2019
comment
@PeterCordes Интересно, какие библиотеки DLL Windows / MSOffice когда-либо передают / получают long double в своих экспортируемых функциях. Я предполагаю, что из-за того, что long double в основном такой же, как double в компиляторах MS, сами MS даже не думают об использовании этого типа где-либо. Ну, среда выполнения C может быть единственным реальным случаем.   -  person Ruslan    schedule 15.12.2019
comment
@Ruslan: Да, наверное, только такие вещи, как sinl(long double), что касается стандартных DLL. (Если это не может быть просто псевдоним символа для sin). Я вообще не знаком с Windows API, но был бы удивлен, если бы они где-нибудь использовали long double. Таким образом, у вас возникнут проблемы только при создании собственных DLL из источников библиотек, которые используют long double в своем API.   -  person Peter Cordes    schedule 15.12.2019


Ответы (2)


Почему в некоторых случаях по умолчанию используется 80-битное представление?

Потому что некоторые платформы могут аппаратно обеспечивать эффективные 80-битные операции с плавающей запятой, но не 128-битные. Это та же самая причина, почему sizeof(int) не указано в стандарте - на некоторых платформах 32-битные целые числа могут быть неэффективными/доступными.

person Max Langhof    schedule 11.10.2018

Почему в некоторых случаях по умолчанию используется 80-битное представление?

Поскольку x87 поддерживает 80-битный формат повышенной точности IEEE-754. Некоторые более поздние платформы, такие как Motorola 6888x, Intel i960 и Itanium, также поддерживают этот тип, поэтому для компиляторов имеет смысл использовать его для long double вместо того, чтобы прибегать к гораздо более медленной программной эмуляции.

По этой же причине PowerPC использует double-double для long double by по умолчанию, потому что вы можете использовать аппаратный блок double, который значительно ускоряет работу. Старые ядра NVIDIA CUDA не имели аппаратной поддержки double, поэтому многие люди использовали float-float для большей точности. См. раздел Эмуляция FP64 с двумя FP32 на графическом процессоре.

Большинство других архитектур не имеют оборудования для типов с плавающей запятой размером более 64 бит, поэтому они выбрали формат четырехкратной точности IEEE-754 для простоты реализации и лучшей прямой совместимости, так как если однажды появится поддержка 128-битных дошел до реального оборудования, скорее всего, это будет IEEE-754 с четырехкратной точностью. В настоящее время Sparc является единственной архитектурой с аппаратной поддержкой четырехкратной точности.

Тем не менее, у большинства компиляторов есть возможность изменить базовый формат для long double. Например, в GCC есть -mlong-double-64/80/128 и -m96/128bit-long-double для x86 и -mabi=ibmlongdouble/ieeelongdouble для PowerPC

person phuclv    schedule 15.04.2019
comment
Почему логика использования PowerPC double-double не распространяется, например, на РУКА? GCC на Raspbian (arm-linux-gnueabihf — аппаратный FPU) имеет DBL_MANT_DIG==LDBL_MANT_DIG, что равно 53, несмотря на то, что ЦП поддерживает родной double. - person Ruslan; 15.12.2019
comment
Двойная арифметика @Ruslan имеет другую семантику, чем обычные типы с плавающей запятой, поэтому, вероятно, авторы компилятора не хотят использовать ее для long double по умолчанию. Кроме того, для большинства практических целей обычно достаточно двойной точности, поэтому более высокая точность long double может и не понадобиться. В настоящее время большинство архитектур, отличных от x86 и PPC, используют стандартный формат IEEE-154 binary128 для более высокой точности вместо нестандартного формата double-double. - person phuclv; 15.12.2019