integer

[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.