2024/08/27(火)kv-0.4.57
今回は、
- 以前にるふぁさんにご指摘頂いた、defint_autostepで使用する級数の次数を1にしたときに正しく計算できていなかったバグの修正。
- ode_maffineに自動微分型を指定し、なおかつcallback関数を指定したとき、 callback関数が初期値に関する微分の情報をも渡してくれるように変更。
大したアップデートではないですが、一応2つ溜まったので。
2024/02/07(水)g++-13と_Float64xとkv-0.4.56
今回は問題発生への対処です。ある人から、g++ version 13でkvがまったくコンパイルできない、clang++では問題ないと連絡が来ました。実際、ubuntu 23.10を入れて試してみると、test-rounding.ccとかtest-interval.ccみたいな基本的なプログラムすらコンパイルエラーになってしまいました。
調べてみると、_Float64x (IntelのFPUが持っている80bit拡張浮動小数点数) の関係する部分がエラーになっています。kvどころか、
#include <iostream> int main() { _Float64x a; std::cin >> a; }みたいな単純なプログラムがコンパイルエラーになってしまいます。また、
#include <iostream> #include <limits> int main() { std::cout << std::numeric_limits<_Float64x>::epsilon() << std::endl; std::cout << std::numeric_limits<_Float64x>::max() << std::endl; std::cout << std::numeric_limits<_Float64x>::min() << std::endl; std::cout << std::numeric_limits<_Float64x>::infinity() << std::endl; std::cout << std::numeric_limits<__float80>::epsilon() << std::endl; std::cout << std::numeric_limits<__float80>::max() << std::endl; std::cout << std::numeric_limits<__float80>::min() << std::endl; std::cout << std::numeric_limits<__float80>::infinity() << std::endl; std::cout << std::numeric_limits<long double>::epsilon() << std::endl; std::cout << std::numeric_limits<long double>::max() << std::endl; std::cout << std::numeric_limits<long double>::min() << std::endl; std::cout << std::numeric_limits<long double>::infinity() << std::endl; }は、
0 0 0 0 1.0842e-19 1.18973e+4932 3.3621e-4932 inf 1.0842e-19 1.18973e+4932 3.3621e-4932 infのように、numeric_limits<_Float64x>はすべて0を返してきます。
調べてみると、「_Float64xをサポートしているのはgccのみで、もともとg++では_Float64xをまったくサポートしていなかった。しかしversion 12までは単なるlong doubleのtypedefだったので、たまたまg++でも動いてしまっていた。最新のg++ version 13では_Float64xを部分的にサポートするようになったがlibstdc++はサポートしていない状態になり、結果的にまったく使えなくなってしまった」ということのようです。やりとりはこの辺。
gccのドキュメントの6.12 Additional Floating Typesでは、「As an extension, GNU C and GNU C++ support additional floating types, (中略) _float80 is available on the i386, x86_64, and IA-64 targets, and supports the 80-bit (XFmode) floating type. It is an alias for the type name _Float64x on these targets. 」とはっきり書いているので、g++でも_Float64xはサポートされているように見えるのですが。
IntelのCPUではlong double、__float80も_Float64xと同じ80bit拡張浮動小数点数です。こっちの2つはg++-13でも生き残っています。どちらかで全部書き換えることも考えたのですが、long doubleは異なるアーキテクチャだと異なる浮動小数点数フォーマットに対応していることが多く、トラブルを招く可能性が高い、__float80はgccのみのオリジナル拡張でclangで使えない、とそれぞれ問題があります。
もっともメジャーで、4月にはみんながubuntu 24.04を使い始めることを考えると、g++-13で動かないなんてのは使い物にならないも同然なので、緊急にkv-0.4.56をリリースしました。とりあえず最低限の変更で、g++-13では_Float64x関連の機能が全部働かないようにしました。g++-12以下ではすべて問題なく、g++-13では_Float64xを使う機能を除いてすべてコンパイルできるようになりました。他の変更は、ついでにoptimize.hppにちょっとした追加機能が入ったくらいです。
g++-14以降でちゃんと戻ることを祈るのみですが、こんなIntel CPUにしかない盲腸のような機能を使おうとするほうが悪い、という話でもあるのかな。