小林です。

手違いでruby-math宛てが私に来ました。
ごとけんさんの依頼でこちらに流します。

================ 以下ごとけんさんより=============

ごとけんです

In message "[ruby-math:00028] Re: (summary) SingleFloat, DoubleFloat <
Float"
    on 00/01/12, "Shigeo Kobayashi" <shigeo / tinyforest.gr.jp> writes:

>Precision システムとはRubyソースのprec.cあたりの実装を意味するもの
>だと思うのですが、(よんでもよくわからないので)どんなプロトコルなのか
>ヒントを頂けるとありがたいのですが?

えっと Precision は組み込みのモジュールの名前で、mix-in とし
て使います。まだたいしたサービスは提供してないですが、全貌は
次の通りです。

まず、Precisionをincludeするのは精度を持つ具象実数値クラスで
す。ここでは精度とは実数の近似の良さを意味します。小林さんの
BigFloatはPrecisionをインクルードするのにふさわしいクラスで
すが以下を読めばわかるようにこのままでは使えません。

Precisionをインクルードするクラスは induced_from という必ず1
引数のクラスメソッドが実装されていなくてはなりません。このメ
ソッドは、たとえば、ANumberという実数クラスにおいて

  ANumber.induced_from(1)

は、整数1をに相当するANumberを返すモノです。すべての組み込み
の数値クラスに対してANumber.induced_fromはBigFloatオブジェク
トを返すことが期待されます。

一方、Precisionをインクルードしてある場合、precというメソッ
ドを利用できます。これは

  num.prec(Klass)

のように呼び出すと、

  Klass.induced_from(num)

を呼び出すことになります。Precisionの仕様は以上です。


しかし、小林さんのBigFloatはnewが2引数であるためこのままでは
使えないので議論が必要な気がします。案としては、

  * デフォルトの幅を持つ

  * 無限に正しいことを意味する特殊な幅をもつ

  * 幅でパラメトライズされたサブクラスが生成できる

のいずれかが思い付きます。ぼくのお勧めは最後の案です。

当時の議論で合意したことのひとつにNumericはnewを持つべきでな
いという話があります。これは数値は仮にオブジェクトとしては新
しくてもその数自体が新しいわけではないという意味です。たとえ
ば、Integer.newというのは現行では利用可能ですが、新しい整数
というのはよく分からない概念です。そこで数値クラスにはnewの
代わりに [] というクラスメソッドを定義しておくことを提案して
います。たとえばInteger[1.0]でいまのInteger(1.0)の意味になり
ますが、これは Integer というプールから 1.0 に相当するモノを
取り出すという感覚をあらわしています。

精度が異なる数値オブジェクトは異なるオブジェクトであるという
のがPrecisionの方針です。このことを実現する枠組としてパラメー
タ付のクラスというのを考えました。まだドキュメントを書いてな
いのでraaには登録してませんが、[ruby-list:18744]に
paramclass.rbと いうmix-inを投稿してあります。

このパラメーター付クラスとは、Klassという名前のクラスに対し
てKlass(param)という関数が定義されていて、そのこれはパラメー
タparamであるようなクラスKlassをを返すモノです。たとえば、

  BigFloat(30)

は幅が30に固定されたBigFloatをあらわすといった具合です。この
場合、newの代わりに[]が定義されていたらば、

  BigFloat(30)[1]

で整数1を幅30の浮動小数点数であらわしたBigFloatオブジェクト
を返すことになります。また、このBigFloat()が定義されていれば、
これは

  1.prec(BigFloat(30))

と書くこともできます。もちろん、そのためには、各nについて

  BigFloat(n).induced_from

が定義されている必要があります。

長くなりましたが、Precision はこのように以下のことを推奨する
ための mix-in です。

  * 精度はクラスで識別できる。

  * クラスごとに精度が確定している。

  * Klass が精度を持っていることは Klass < Precision で
    調べることができ、オブジェクトが精度を持っていることは、
    obj.kind_of?(Precision) で調べることが出来る。

  * 精度を持っているクラスは1引数のクラスメソッド induced_from
    で他の精度を持ったオブジェクトを型変換できる。

  * 他の精度への変換は num.prec(Klass) で行える。

また、この枠組によりRubyにおける精度を規定してます。

-- gotoken