2014/11/24(月)kv-0.4.13
今回は、やや重大なバグの修正です。ddの表示が正しくなかったというものです。
#include <kv/dd.hpp> int main() { kv::dd x; int i; std::cout.precision(34); for (i=1; i<9; i++) { x = i / (kv::dd)9; std::cout << x << "\n"; } }の実行結果が、
0.1111111111111111111111111111111108 0.2222222222222222222222222222222215 0.3333333333333333333333333333333323 0.4444444444444444444444444444444431 0.5555555555555555833111311711844704 0.6666666666666666666666666666666646 0.7777777777777777916555655855922352 0.8888888888888888888888888888888861となってしまっていました。5/9, 7/9の値がおかしいことが分かります。これは、内部では正しく計算していますが、double-doubleを表示(文字列変換)するときに一つ目と二つ目のdoubleの符号が違うとうまく表示されないというバグのせいです。
文字列変換部 (conv-dd.hpp) は、元々luaという言語で書いていて、それが正しく動くのを確認してC++に移植するという手順を踏んだのですが、負数に対する%(剰余演算子)のluaとC++での違いに起因するものでした。
修正して、ちゃんと
0.1111111111111111111111111111111108 0.2222222222222222222222222222222215 0.3333333333333333333333333333333323 0.4444444444444444444444444444444431 0.5555555555555555555555555555555569 0.6666666666666666666666666666666646 0.7777777777777777777777777777777785 0.8888888888888888888888888888888861と表示されるようになりました。
こういうバグはすぐに修正せねばなりません。ついでに、affineにいくつか関数を追加したり、ソースコードをいくらかクリーンアップしたりしました。
2014/11/12(水)kv-0.4.12
先週の土曜日、kvライブラリを紹介する機会があって、何人かの人に使って頂くことが出来ました。そこで、affine<dd>のようにaffineにdouble以外の型を入れるとうまくコンパイル出来ない事例が見つかったので、修正しました。affineの内部型としては、rdouble.hppやrdd.hppを使って丸め付き演算の方法が与えられているような型を使えるように設計したつもりでしたが、実際に試してはいませんでした。
やはり、ライブラリは使われてこそ鍛えられますね。
ついでに、以前から書きたいと思っていたけど精度保証に直接関係がないので放置していた、ddを区間の端点でなく単体で使ったときのための数学関数(精度保証しない)を作成しました。
更に、そのddの数学関数でpowを実装しているときにふとした疑問を感じ、過去の実装を調べたところ、dd, psa, interval, autodifでpow(x, 2.5)のようにdouble型を指定した非整数乗の動作に問題があり、なんとintに切り捨てられてpow(x, 2)相当の動作をしていたことが判明しました。自分のライブラリ内でpowの第2引数にdoubleを使った例はありませんでしたが、online solverでこの機能を使った方がもしいれば、間違った結果を出していたことになります。
このように結果の信頼性に関わるバグが発見された時は即刻アップデートする方針なので、0.4.12としてアップデートしました。
2014/10/26(日)kv-0.4.11
前の記事に書いたように、rkf45を修正しました。
また、ベキ級数演算のhistory関連にバグがあって、sin等の数学関数のみから成る加減乗除を全く含まない右辺を持つ常微分方程式に対して、内部エラーで計算を行えなかった問題を修正しました。
2014/10/26(日)rkf45
これは、Runge–Kutta–Fehlberg法という有名なもので、6段5次の公式と5段4次の公式が同時に計算できるように工夫されていて、両者の差を観察することによって(大雑把ではあるが)混入した誤差の評価も出来るという優れものです。
この手法を使ったからと言って精度保証出来るわけでは無いのですが、楽しそうだったのでステップ幅調節らしきものも付けて試しに書いてみて、せっかくなのでkvライブラリ内に混ぜておいたものです。
先日、ちょうどオイラー法やルンゲクッタ法など、初期値問題の解法を講義でやったので、このrkf45を講義内で実演してみたら、なぜか精度が出ない! ステップ幅調整もしていない素の4段4次ルンゲクッタに負けてる! 講義中は、「やっぱデモやめた」と誤魔化して先へ進んだのですが、後でチェックしてみたら係数が一箇所間違ってました。精度がでないわけです。
精度保証とは関係ないところですが、ちょっと気分が悪いので、近日中にアップデートしてkv-0.4.11としたいと思います。
2014/10/09(木)kv-0.4.10
webデモ内でlog(対数)が使えなかったバグが見つかったので、修正しました。これはkvライブラリ本体ではなくCGIで書いたpythonからC++へのコンバータのバグなので、本体の問題ではありません。
ライブラリ本体の方はlgammaを追加したり、特異点を持つ関数の数値積分関連を整理したりしてますが、これらはまだ発展途上でドキュメントもありません。更新が落ち着いたらきちんと書きたいと考えています。