中川です。

From: matz / netlab.co.jp (Yukihiro Matsumoto)
Subject: [ruby-list:8647] Re: can't build 1.1b9_28 on digital-unix
Date: Wed, 8 Jul 1998 17:38:41 +0900

> まつもと ゆきひろです

> できれば,以下の結果をそれぞれ教えて下さい.
> 
> % ruby -e 'p 1<<1014'
> % ruby -e 'p 2**1014'

直接の回答にはなりませんが、いままで調べた結果を報告します。

o その1 -- FIXNUM_{MAX|MIN} がおかしい?

for i in 0..100
  print ("i=", i, " ", (1<<i).type, " ", (1<<i),"\n")
end
    
を実行すると

(一部略)
i=26 Fixnum 67108864
i=27 Fixnum 134217728
i=28 Fixnum 268435456
i=29 Fixnum 536870912
i=30 Fixnum 1073741824
i=31 Fixnum 
foo.rb:2:in `to_s': integer -2147483648 too big to convert to `int'. 
(ArgumentError)
    from foo.rb:2:in `print'
    from foo.rb:2
    from foo.rb:1:in `each'
    from foo.rb:1

で終了します。/usr/include/limits.h で
#define LONG_MAX         9223372036854775807
が定義されているので、以下のパッチをあてたらそれっぽく動くように
なりました。FIXNUM_MIN の処理は自信ないです。その場しのぎなので
そういう目でみてください :-)

-------- ここから
*** ruby-1.1b9_29/ruby.h	Fri Jun 26 18:44:36 1998
--- ruby-1.1b9_29-alpha/ruby.h	Wed Jul 08 17:59:50 1998
***************
*** 112,119 ****
--- 112,124 ----
  # endif
  #endif
  
+ #if (SIZEOF_LONG == 8) && (SIZEOF_INT == 4)
+ #define FIXNUM_MAX (INT_MAX>>1)
+ #define FIXNUM_MIN RSHIFT((int)INT_MIN,1)
+ #else
  #define FIXNUM_MAX (LONG_MAX>>1)
  #define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
+ #endif
  
  #define FIXNUM_FLAG 0x01
  #define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG)
-------- ここまで

o その2 -- lshift がおかしい?

FIXNUM_MIN の処理が自信ないので確認しようとしました。

for i in 0..100
  print ("i=", i, " ", (-1<<i).type, " ", (-1<<i),"\n")
end

の結果はこんな感じです。

(一部略)
i=28 Fixnum -268435456
i=29 Fixnum -536870912
i=30 Fixnum -1073741824
i=31 Bignum -2147483648
i=32 Fixnum 0
i=33 Fixnum 0
i=34 Fixnum 0
(中略 0が続く)
i=60 Fixnum 0
i=61 Fixnum 0
i=62 Bignum -4611686018427387904
i=63 Bignum -9223372036854775808
(後略)

んー、なんか変。
どうやら sizeof(VALUE)==sizeof(unsigned long) なので
numeric.c の fix_lshift() のうち、

    if (width > (sizeof(VALUE)*CHAR_BIT-1)
        || (unsigned)val>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
        return big_lshift(int2big(val), y);
    }

がうまくいってないみたいです。
パッチありません。面目ないっす。
-1<<30 == -1073741824 が Fixnum というのは x86 な環境と結果が
違うのですが追いきれてません。

o その3 -- pow がおかしい?

for i in 0..100
  print ("i=", i, " ", (2**i).type, " ", (2**i),"\n")
end

の結果はこうなりました。

(一部略)
i=28 Fixnum 268435456
i=29 Fixnum 536870912
i=30 Bignum 1073741824
i=31 Bignum 2147483648
i=32 Fixnum 0
i=33 Fixnum 0
i=34 Fixnum 0
(以下おなじ)

んー、やっぱり変。
原因は追いきれてません。面目ないっす。
--
中川 剛 / nakagawa / shizuokanet.ne.jp