src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/builtin_fn_num_test.elvts (about)

     1  // When testing numbers with different underlying types, the order is usually
     2  //
     3  // 1. int
     4  // 2. *big.Int (100000000000000000000 is often used)
     5  // 3. *big.Rat
     6  // 4. float64
     7  
     8  ///////
     9  # num #
    10  ///////
    11  
    12  ~> num 1
    13  ▶ (num 1)
    14  ~> num 100000000000000000000
    15  ▶ (num 100000000000000000000)
    16  ~> num 1/2
    17  ▶ (num 1/2)
    18  ~> num 0.1
    19  ▶ (num 0.1)
    20  ~> num (num 1)
    21  ▶ (num 1)
    22  
    23  /////////////
    24  # exact-num #
    25  /////////////
    26  
    27  ~> exact-num 1
    28  ▶ (num 1)
    29  ~> exact-num 0.125
    30  ▶ (num 1/8)
    31  ~> exact-num inf
    32  Exception: bad value: argument here must be finite float, but is +Inf
    33    [tty]:1:1-13: exact-num inf
    34  
    35  ///////////////
    36  # inexact-num #
    37  ///////////////
    38  
    39  ~> inexact-num 1
    40  ▶ (num 1.0)
    41  ~> inexact-num 1.0
    42  ▶ (num 1.0)
    43  ~> inexact-num (num 1)
    44  ▶ (num 1.0)
    45  ~> inexact-num (num 1.0)
    46  ▶ (num 1.0)
    47  
    48  //////////////
    49  # Comparison #
    50  //////////////
    51  
    52  ## < ##
    53  
    54  // int
    55  ~> < 1 2 3
    56  ▶ $true
    57  ~> < 1 3 2
    58  ▶ $false
    59  // *big.Int
    60  ~> < 100000000000000000001 100000000000000000002 100000000000000000003
    61  ▶ $true
    62  ~> < 100000000000000000001 100000000000000000003 100000000000000000002
    63  ▶ $false
    64  // *big.Rat
    65  ~> < 1/4 1/3 1/2
    66  ▶ $true
    67  ~> < 1/4 1/2 1/3
    68  ▶ $false
    69  // float64
    70  ~> < 1.0 2.0 3.0
    71  ▶ $true
    72  ~> < 1.0 3.0 2.0
    73  ▶ $false
    74  
    75  ## mixed types ##
    76  // Only test with <; the other commands share the same code path for handling
    77  // mixed types.
    78  
    79  // mixing int and *big.Int
    80  ~> < 1 100000000000000000001
    81  ▶ $true
    82  // mixing int, *big.Int and *big.Rat
    83  ~> < 1/2 1 100000000000000000001
    84  ▶ $true
    85  ~> < 1/2 100000000000000000001 1
    86  ▶ $false
    87  // mixing int, *big.Rat and float64
    88  ~> < 1.0 3/2 2
    89  ▶ $true
    90  ~> < 1.0 2 3/2
    91  ▶ $false
    92  
    93  ## <= ##
    94  
    95  // int
    96  ~> <= 1 1 2
    97  ▶ $true
    98  ~> <= 1 2 1
    99  ▶ $false
   100  // *big.Int
   101  ~> <= 100000000000000000001 100000000000000000001 100000000000000000002
   102  ▶ $true
   103  ~> <= 100000000000000000001 100000000000000000002 100000000000000000001
   104  ▶ $false
   105  // *big.Rat
   106  ~> <= 1/3 1/3 1/2
   107  ▶ $true
   108  ~> <= 1/3 1/2 1/1
   109  ▶ $true
   110  // float64
   111  ~> <= 1.0 1.0 2.0
   112  ▶ $true
   113  ~> <= 1.0 2.0 1.0
   114  ▶ $false
   115  
   116  ## == ##
   117  
   118  // int
   119  ~> == 1 1 1
   120  ▶ $true
   121  ~> == 1 2 1
   122  ▶ $false
   123  // *big.Int
   124  ~> == 100000000000000000001 100000000000000000001 100000000000000000001
   125  ▶ $true
   126  ~> == 100000000000000000001 100000000000000000002 100000000000000000001
   127  ▶ $false
   128  // *big.Rat
   129  ~> == 1/2 1/2 1/2
   130  ▶ $true
   131  ~> == 1/2 1/3 1/2
   132  ▶ $false
   133  // float64
   134  ~> == 1.0 1.0 1.0
   135  ▶ $true
   136  ~> == 1.0 2.0 1.0
   137  ▶ $false
   138  
   139  ## != ##
   140  
   141  // int
   142  ~> != 1 2
   143  ▶ $true
   144  ~> != 1 1
   145  ▶ $false
   146  // *big.Int
   147  ~> != 100000000000000000001 100000000000000000002
   148  ▶ $true
   149  ~> != 100000000000000000001 100000000000000000001
   150  ▶ $false
   151  // *big.Rat
   152  ~> != 1/2 1/3
   153  ▶ $true
   154  ~> != 1/2 1/2
   155  ▶ $false
   156  // float64
   157  ~> != 1.0 2.0
   158  ▶ $true
   159  ~> != 1.0 1.0
   160  ▶ $false
   161  // only accepts two arguments
   162  ~> !=
   163  Exception: arity mismatch: arguments must be 2 values, but is 0 values
   164    [tty]:1:1-2: !=
   165  ~> != 1
   166  Exception: arity mismatch: arguments must be 2 values, but is 1 value
   167    [tty]:1:1-4: != 1
   168  ~> != 1 2 3
   169  Exception: arity mismatch: arguments must be 2 values, but is 3 values
   170    [tty]:1:1-8: != 1 2 3
   171  
   172  ## > ##
   173  
   174  // int
   175  ~> > 3 2 1
   176  ▶ $true
   177  ~> > 3 1 2
   178  ▶ $false
   179  // *big.Int
   180  ~> > 100000000000000000003 100000000000000000002 100000000000000000001
   181  ▶ $true
   182  ~> > 100000000000000000003 100000000000000000001 100000000000000000002
   183  ▶ $false
   184  // *big.Rat
   185  ~> > 1/2 1/3 1/4
   186  ▶ $true
   187  ~> > 1/2 1/4 1/3
   188  ▶ $false
   189  // float64
   190  ~> > 3.0 2.0 1.0
   191  ▶ $true
   192  ~> > 3.0 1.0 2.0
   193  ▶ $false
   194  
   195  ## >= ##
   196  
   197  // int
   198  ~> >= 3 3 2
   199  ▶ $true
   200  ~> >= 3 2 3
   201  ▶ $false
   202  // *big.Int
   203  ~> >= 100000000000000000003 100000000000000000003 100000000000000000002
   204  ▶ $true
   205  ~> >= 100000000000000000003 100000000000000000002 100000000000000000003
   206  ▶ $false
   207  // *big.Rat
   208  ~> >= 1/2 1/2 1/3
   209  ▶ $true
   210  ~> >= 1/2 1/3 1/2
   211  ▶ $false
   212  // float64
   213  ~> >= 3.0 3.0 2.0
   214  ▶ $true
   215  ~> >= 3.0 2.0 3.0
   216  ▶ $false
   217  
   218  ////////////////////
   219  # basic arithmetic #
   220  ////////////////////
   221  
   222  ## + ##
   223  
   224  // no argument
   225  ~> +
   226  ▶ (num 0)
   227  // int
   228  ~> + 233100 233
   229  ▶ (num 233333)
   230  // *big.Int
   231  ~> + 100000000000000000000 100000000000000000001
   232  ▶ (num 200000000000000000001)
   233  // *big.Rat
   234  ~> + 1/2 1/3 1/4
   235  ▶ (num 13/12)
   236  // float64
   237  ~> + 0.5 0.25 1.0
   238  ▶ (num 1.75)
   239  
   240  ## mixing types ##
   241  
   242  // Only test with +; the other commands share the same code path for handling
   243  // mixed types.
   244  
   245  // int and *big.Int
   246  ~> + 1 2 100000000000000000000
   247  ▶ (num 100000000000000000003)
   248  // int, *big,Int and *big.Rat
   249  ~> + 1/2 1/2 1 100000000000000000000
   250  ▶ (num 100000000000000000002)
   251  // int, *big.Rat and float64
   252  ~> + 0.5 1/4 1
   253  ▶ (num 1.75)
   254  
   255  ## - ##
   256  
   257  // no argument is unsupported
   258  ~> -
   259  Exception: arity mismatch: arguments must be 1 or more values, but is 0 values
   260    [tty]:1:1-1: -
   261  // one argument is negation
   262  ~> - 233
   263  ▶ (num -233)
   264  ~> - 100000000000000000000
   265  ▶ (num -100000000000000000000)
   266  ~> - 1/2
   267  ▶ (num -1/2)
   268  ~> - 1.0
   269  ▶ (num -1.0)
   270  // int
   271  ~> - 20 10 2
   272  ▶ (num 8)
   273  // *big.Int
   274  ~> - 200000000000000000003 100000000000000000001
   275  ▶ (num 100000000000000000002)
   276  // *big.Rat
   277  ~> - 1/2 1/3
   278  ▶ (num 1/6)
   279  // float64
   280  ~> - 2.0 1.0 0.5
   281  ▶ (num 0.5)
   282  
   283  ## * ##
   284  
   285  // no argument
   286  ~> *
   287  ▶ (num 1)
   288  // int
   289  ~> * 2 7 4
   290  ▶ (num 56)
   291  // *big.Int
   292  ~> * 2 100000000000000000001
   293  ▶ (num 200000000000000000002)
   294  // *big.Rat
   295  ~> * 1/2 1/3
   296  ▶ (num 1/6)
   297  // float64
   298  ~> * 2.0 0.5 1.75
   299  ▶ (num 1.75)
   300  // 0 * non-infinity
   301  ~> * 0 1/2 1.0
   302  ▶ (num 0)
   303  // 0 * infinity
   304  ~> * 0 +Inf
   305  ▶ (num NaN)
   306  
   307  ## / ##
   308  
   309  // one argument - inversion
   310  ~> / 2
   311  ▶ (num 1/2)
   312  ~> / 100000000000000000000
   313  ▶ (num 1/100000000000000000000)
   314  ~> / 2.0
   315  ▶ (num 0.5)
   316  // int
   317  ~> / 233333 353
   318  ▶ (num 661)
   319  ~> / 3 4 2
   320  ▶ (num 3/8)
   321  // *big.Int
   322  ~> / 200000000000000000000 100000000000000000000
   323  ▶ (num 2)
   324  ~> / 200000000000000000000 2
   325  ▶ (num 100000000000000000000)
   326  ~> / 100000000000000000001 100000000000000000000
   327  ▶ (num 100000000000000000001/100000000000000000000)
   328  // float64
   329  ~> / 1.0 2.0 4.0
   330  ▶ (num 0.125)
   331  ~> / 0 1/2 0.1
   332  ▶ (num 0)
   333  // anything / 0
   334  ~> / 0 0
   335  Exception: bad value: divisor must be number other than exact 0, but is exact 0
   336    [tty]:1:1-5: / 0 0
   337  ~> / 1 0
   338  Exception: bad value: divisor must be number other than exact 0, but is exact 0
   339    [tty]:1:1-5: / 1 0
   340  ~> / 1.0 0
   341  Exception: bad value: divisor must be number other than exact 0, but is exact 0
   342    [tty]:1:1-7: / 1.0 0
   343  
   344  ## implicit cd with / ##
   345  //only-on unix
   346  //in-temp-dir
   347  //with-deprecation-level 21
   348  ~> /
   349  Deprecation: implicit cd is deprecated; use cd or location mode instead
   350    [tty]:1:1-1: /
   351  ~> put $pwd
   352  ▶ /
   353  
   354  ## % ##
   355  ~> % 23 7
   356  ▶ (num 2)
   357  ~> % 1 0
   358  Exception: bad value: divisor must be number other than exact 0, but is exact 0
   359    [tty]:1:1-5: % 1 0
   360  // big int support
   361  ~> % 10000000000000000000 3
   362  ▶ (num 1)
   363  // floating point is not supported, even if integer
   364  ~> % 10.0 3
   365  Exception: bad value: argument must be exact integer, but is (num 10.0)
   366    [tty]:1:1-8: % 10.0 3
   367  ~> % 10 3.0
   368  Exception: bad value: argument must be exact integer, but is (num 3.0)
   369    [tty]:1:1-8: % 10 3.0
   370  
   371  ///////////
   372  # randint #
   373  ///////////
   374  
   375  ~> randint 1 2
   376  ▶ (num 1)
   377  ~> randint 1
   378  ▶ (num 0)
   379  ~> var i = (randint 10 100)
   380     and (<= 10 $i) (< $i 100)
   381  ▶ $true
   382  ~> var i = (randint 10)
   383     and (<= 0 $i) (< $i 10)
   384  ▶ $true
   385  // big int is OK
   386  ~> var z = (num 10000000000000000000)
   387  ~> < (randint $z) $z
   388  ▶ $true
   389  ~> var low = $z
   390     var high = (+ $low 10)
   391     var i = (randint $low $high)
   392     and (<= $low $i) (< $i $high)
   393  ▶ $true
   394  
   395  ## argument checking ##
   396  
   397  ~> randint 2 1
   398  Exception: bad value: high value must be larger than 2, but is 1
   399    [tty]:1:1-11: randint 2 1
   400  ~> var z = (num 10000000000000000000)
   401     randint (+ $z 10) $z
   402  Exception: bad value: high value must be larger than 10000000000000000010, but is 10000000000000000000
   403    [tty]:2:1-20: randint (+ $z 10) $z
   404  ~> randint
   405  Exception: arity mismatch: arguments must be 1 to 2 values, but is 0 values
   406    [tty]:1:1-7: randint
   407  ~> randint 1 2 3
   408  Exception: arity mismatch: arguments must be 1 to 2 values, but is 3 values
   409    [tty]:1:1-13: randint 1 2 3
   410  ~> randint 1.0
   411  Exception: bad value: argument must be exact integer, but is (num 1.0)
   412    [tty]:1:1-11: randint 1.0
   413  
   414  /////////////
   415  # -randseed #
   416  /////////////
   417  
   418  //reseed-afterwards
   419  
   420  // -randseed makes randint deterministic ##
   421  ~> fn f { -randseed 0; randint 10 }
   422     eq (f) (f)
   423  ▶ $true
   424  // big int uses a different code path internally, so verify that generating big
   425  // int is also deterministic.
   426  ~> fn f { -randseed 0; randint 10000000000000000000 }
   427     eq (f) (f)
   428  ▶ $true
   429  // rand is also deterministic
   430  ~> fn f { -randseed 0; rand }
   431     eq (f) (f)
   432  ▶ $true
   433  
   434  /////////
   435  # range #
   436  /////////
   437  
   438  ## argument arity check ##
   439  ~> range
   440  Exception: arity mismatch: arguments must be 1 to 2 values, but is 0 values
   441    [tty]:1:1-5: range
   442  ~> range 0 1 2
   443  Exception: arity mismatch: arguments must be 1 to 2 values, but is 3 values
   444    [tty]:1:1-11: range 0 1 2
   445  
   446  ## int ##
   447  // counting up
   448  ~> range 3
   449  ▶ (num 0)
   450  ▶ (num 1)
   451  ▶ (num 2)
   452  ~> range 1 3
   453  ▶ (num 1)
   454  ▶ (num 2)
   455  // counting down
   456  ~> range -1 10 &step=3
   457  ▶ (num -1)
   458  ▶ (num 2)
   459  ▶ (num 5)
   460  ▶ (num 8)
   461  ~> range 3 -3
   462  ▶ (num 3)
   463  ▶ (num 2)
   464  ▶ (num 1)
   465  ▶ (num 0)
   466  ▶ (num -1)
   467  ▶ (num -2)
   468  // invalid step
   469  ~> range &step=-1 1
   470  Exception: bad value: step must be positive, but is -1
   471    [tty]:1:1-16: range &step=-1 1
   472  ~> range &step=1 1 0
   473  Exception: bad value: step must be negative, but is 1
   474    [tty]:1:1-17: range &step=1 1 0
   475  // bubbling output error
   476  ~> range 2 >&-
   477  Exception: port does not support value output
   478    [tty]:1:1-11: range 2 >&-
   479  
   480  ## near max/min of int ##
   481  // Values near the max/min of int need to be handled carefully to avoid
   482  // overflow. Instead of assuming int is 64-bit or 32-bit, test interesting
   483  // values for both cases.
   484  
   485  // 2^63-3 to 2^63-1
   486  ~> range 9223372036854775805 9223372036854775807
   487  ▶ (num 9223372036854775805)
   488  ▶ (num 9223372036854775806)
   489  ~> range 9223372036854775807 9223372036854775805
   490  ▶ (num 9223372036854775807)
   491  ▶ (num 9223372036854775806)
   492  // -2^63 to -2^63+2
   493  ~> range -9223372036854775808 -9223372036854775806
   494  ▶ (num -9223372036854775808)
   495  ▶ (num -9223372036854775807)
   496  ~> range -9223372036854775806 -9223372036854775808
   497  ▶ (num -9223372036854775806)
   498  ▶ (num -9223372036854775807)
   499  // 2^31-3 to 2^31-1
   500  ~> range 2147483645 2147483647
   501  ▶ (num 2147483645)
   502  ▶ (num 2147483646)
   503  ~> range 2147483647 2147483645
   504  ▶ (num 2147483647)
   505  ▶ (num 2147483646)
   506  // -2^31 to -2^31+2
   507  ~> range -2147483648 -2147483646
   508  ▶ (num -2147483648)
   509  ▶ (num -2147483647)
   510  ~> range -2147483646 -2147483648
   511  ▶ (num -2147483646)
   512  ▶ (num -2147483647)
   513  
   514  ## *big.Int ##
   515  // counting up
   516  ~> range 100000000000000000000 100000000000000000003
   517  ▶ (num 100000000000000000000)
   518  ▶ (num 100000000000000000001)
   519  ▶ (num 100000000000000000002)
   520  ~> range 100000000000000000000 100000000000000000003 &step=2
   521  ▶ (num 100000000000000000000)
   522  ▶ (num 100000000000000000002)
   523  // counting down
   524  ~> range 100000000000000000003 100000000000000000000
   525  ▶ (num 100000000000000000003)
   526  ▶ (num 100000000000000000002)
   527  ▶ (num 100000000000000000001)
   528  ~> range 100000000000000000003 100000000000000000000 &step=-2
   529  ▶ (num 100000000000000000003)
   530  ▶ (num 100000000000000000001)
   531  // invalid step
   532  ~> range &step=-100000000000000000000 10
   533  Exception: bad value: step must be positive, but is -100000000000000000000
   534    [tty]:1:1-37: range &step=-100000000000000000000 10
   535  ~> range &step=100000000000000000000 10 0
   536  Exception: bad value: step must be negative, but is 100000000000000000000
   537    [tty]:1:1-38: range &step=100000000000000000000 10 0
   538  // bubbling output error
   539  ~> range 100000000000000000000 100000000000000000001 >&-
   540  Exception: port does not support value output
   541    [tty]:1:1-53: range 100000000000000000000 100000000000000000001 >&-
   542  
   543  ## *big.Rat ##
   544  // counting up
   545  ~> range 23/10
   546  ▶ (num 0)
   547  ▶ (num 1)
   548  ▶ (num 2)
   549  ~> range 1/10 23/10
   550  ▶ (num 1/10)
   551  ▶ (num 11/10)
   552  ▶ (num 21/10)
   553  ~> range 1/10 9/10 &step=3/10
   554  ▶ (num 1/10)
   555  ▶ (num 2/5)
   556  ▶ (num 7/10)
   557  // counting down
   558  ~> range 23/10 1/10
   559  ▶ (num 23/10)
   560  ▶ (num 13/10)
   561  ▶ (num 3/10)
   562  ~> range 9/10 0/10 &step=-3/10
   563  ▶ (num 9/10)
   564  ▶ (num 3/5)
   565  ▶ (num 3/10)
   566  // invalid step
   567  ~> range &step=-1/2 10
   568  Exception: bad value: step must be positive, but is -1/2
   569    [tty]:1:1-19: range &step=-1/2 10
   570  ~> range &step=1/2 10 0
   571  Exception: bad value: step must be negative, but is 1/2
   572    [tty]:1:1-20: range &step=1/2 10 0
   573  // bubbling output error
   574  ~> range 1/2 3/2 >&-
   575  Exception: port does not support value output
   576    [tty]:1:1-17: range 1/2 3/2 >&-
   577  
   578  ## float64 ##
   579  // counting up
   580  ~> range 1.2
   581  ▶ (num 0.0)
   582  ▶ (num 1.0)
   583  ~> range &step=0.5 1 3
   584  ▶ (num 1.0)
   585  ▶ (num 1.5)
   586  ▶ (num 2.0)
   587  ▶ (num 2.5)
   588  // counting down
   589  ~> range 1.2 -1.2
   590  ▶ (num 1.2)
   591  ▶ (num 0.19999999999999996)
   592  ▶ (num -0.8)
   593  ~> range &step=-0.5 3 1
   594  ▶ (num 3.0)
   595  ▶ (num 2.5)
   596  ▶ (num 2.0)
   597  ▶ (num 1.5)
   598  // Nearing the maximum float64 value where x+1 = x.
   599  ~> range 9007199254740990.0 +inf
   600  ▶ (num 9.00719925474099e+15)
   601  ▶ (num 9007199254740991.0)
   602  ▶ (num 9007199254740992.0)
   603  ~> range 9007199254740992.0 9007199254740990.0
   604  ▶ (num 9007199254740992.0)
   605  ▶ (num 9007199254740991.0)
   606  // invalid step
   607  ~> range &step=-0.5 10
   608  Exception: bad value: step must be positive, but is -0.5
   609    [tty]:1:1-19: range &step=-0.5 10
   610  ~> range &step=0.5 10 0
   611  Exception: bad value: step must be negative, but is 0.5
   612    [tty]:1:1-20: range &step=0.5 10 0
   613  // bubbling output error
   614  ~> range 1.2 >&-
   615  Exception: port does not support value output
   616    [tty]:1:1-13: range 1.2 >&-