[fill in information about tcl's handling of integers - particular the new Tcl 8.5 longer integer support]
Starting from Tcl 8.5, the expr command is based on LibTomMath arbitrary precision integers:
AMG: Not sure "precision" is the right word here. I think "magnitude" is more apt. Also this applies not only to [expr] but all math operations, e.g. those done by [if] and [while].
MB Note that in Tcl releases prior to 8.5, integer calculations were performed with one of the C types long int or Tcl_WideInt. Since a "long int" is based on 32 bits, with one bit for the sign, the maximum positive integer is 2^31. The following is a little algorithm which computes the maximum integer which can be processed without truncation.
# # searchintmax -- # Compute the maximum integer on Tcl platform. # proc searchintmax {imax {fine 0}} { # # Search the maximum available power of 2 which keeps multiplication # set a 1 for {set i 1} {$i<$imax} {incr i} { set n [expr {$a*2}] set p [expr {$n/2}] puts "a=$a, n=$n, p=$p" if {$p!=$a} then { break } set a $n } # # Refine process with positivity property of addition # if {$fine==1} then { set shift [expr {int(pow(2,30))}] for {set i 1} {$i<$imax} {incr i} { set n [expr {$a+$shift}] puts "a=$a, shift=$shift, n=$n" if {$n<=0} then { set shift [expr {$shift/2}] if {$shift==0} then { break } } set a [expr {$a + $shift}] } } return $a }
If one uses this algorithm with Tcl 8.4, one gets the 2^30=1073741824 value, which is the greatest a such (a * 2)/2 = a.
set intmax [searchintmax 100]
With the fine=1 option, one can get the finer value 2^31=2147483647, which is the greatest a such that (a + 1) - 1 = a.
set intmax [searchintmax 100 1]
This is what the algorithm prints out :
a=1, n=2, p=1 a=2, n=4, p=2 a=4, n=8, p=4 a=8, n=16, p=8 a=16, n=32, p=16 a=32, n=64, p=32 a=64, n=128, p=64 a=128, n=256, p=128 a=256, n=512, p=256 a=512, n=1024, p=512 a=1024, n=2048, p=1024 a=2048, n=4096, p=2048 a=4096, n=8192, p=4096 a=8192, n=16384, p=8192 a=16384, n=32768, p=16384 a=32768, n=65536, p=32768 a=65536, n=131072, p=65536 a=131072, n=262144, p=131072 a=262144, n=524288, p=262144 a=524288, n=1048576, p=524288 a=1048576, n=2097152, p=1048576 a=2097152, n=4194304, p=2097152 a=4194304, n=8388608, p=4194304 a=8388608, n=16777216, p=8388608 a=16777216, n=33554432, p=16777216 a=33554432, n=67108864, p=33554432 a=67108864, n=134217728, p=67108864 a=134217728, n=268435456, p=134217728 a=268435456, n=536870912, p=268435456 a=536870912, n=1073741824, p=536870912 a=1073741824, n=-2147483648, p=-1073741824 a=1073741824, shift=1073741824, n=-2147483648 a=1610612736, shift=536870912, n=-2147483648 a=1879048192, shift=268435456, n=-2147483648 a=2013265920, shift=134217728, n=-2147483648 a=2080374784, shift=67108864, n=-2147483648 a=2113929216, shift=33554432, n=-2147483648 a=2130706432, shift=16777216, n=-2147483648 a=2139095040, shift=8388608, n=-2147483648 a=2143289344, shift=4194304, n=-2147483648 a=2145386496, shift=2097152, n=-2147483648 a=2146435072, shift=1048576, n=-2147483648 a=2146959360, shift=524288, n=-2147483648 a=2147221504, shift=262144, n=-2147483648 a=2147352576, shift=131072, n=-2147483648 a=2147418112, shift=65536, n=-2147483648 a=2147450880, shift=32768, n=-2147483648 a=2147467264, shift=16384, n=-2147483648 a=2147475456, shift=8192, n=-2147483648 a=2147479552, shift=4096, n=-2147483648 a=2147481600, shift=2048, n=-2147483648 a=2147482624, shift=1024, n=-2147483648 a=2147483136, shift=512, n=-2147483648 a=2147483392, shift=256, n=-2147483648 a=2147483520, shift=128, n=-2147483648 a=2147483584, shift=64, n=-2147483648 a=2147483616, shift=32, n=-2147483648 a=2147483632, shift=16, n=-2147483648 a=2147483640, shift=8, n=-2147483648 a=2147483644, shift=4, n=-2147483648 a=2147483646, shift=2, n=-2147483648 a=2147483647, shift=1, n=-2147483648
With Tcl 8.5, the loop reaches the maximum number of iterations, which is the expected result.
See also wide.