elvish/pkg/eval/builtin_fn_num_test.elvts
2024-01-30 20:21:39 +00:00

561 lines
11 KiB
Plaintext

// When testing numbers with different underlying types, the order is usually
//
// 1. int
// 2. *big.Int (100000000000000000000 is often used)
// 3. *big.Rat
// 4. float64
///////
# num #
///////
~> num 1
▶ (num 1)
~> num 100000000000000000000
▶ (num 100000000000000000000)
~> num 1/2
▶ (num 1/2)
~> num 0.1
▶ (num 0.1)
~> num (num 1)
▶ (num 1)
/////////////
# exact-num #
/////////////
~> exact-num 1
▶ (num 1)
~> exact-num 0.125
▶ (num 1/8)
~> exact-num inf
Exception: bad value: argument here must be finite float, but is +Inf
[tty]:1:1-13: exact-num inf
///////////////
# inexact-num #
///////////////
~> inexact-num 1
▶ (num 1.0)
~> inexact-num 1.0
▶ (num 1.0)
~> inexact-num (num 1)
▶ (num 1.0)
~> inexact-num (num 1.0)
▶ (num 1.0)
//////////////
# Comparison #
//////////////
## < ##
// int
~> < 1 2 3
▶ $true
~> < 1 3 2
▶ $false
// *big.Int
~> < 100000000000000000001 100000000000000000002 100000000000000000003
▶ $true
~> < 100000000000000000001 100000000000000000003 100000000000000000002
▶ $false
// *big.Rat
~> < 1/4 1/3 1/2
▶ $true
~> < 1/4 1/2 1/3
▶ $false
// float64
~> < 1.0 2.0 3.0
▶ $true
~> < 1.0 3.0 2.0
▶ $false
## mixed types ##
// Only test with <; the other commands share the same code path for handling
// mixed types.
// mixing int and *big.Int
~> < 1 100000000000000000001
▶ $true
// mixing int, *big.Int and *big.Rat
~> < 1/2 1 100000000000000000001
▶ $true
~> < 1/2 100000000000000000001 1
▶ $false
// mixing int, *big.Rat and float64
~> < 1.0 3/2 2
▶ $true
~> < 1.0 2 3/2
▶ $false
## <= ##
// int
~> <= 1 1 2
▶ $true
~> <= 1 2 1
▶ $false
// *big.Int
~> <= 100000000000000000001 100000000000000000001 100000000000000000002
▶ $true
~> <= 100000000000000000001 100000000000000000002 100000000000000000001
▶ $false
// *big.Rat
~> <= 1/3 1/3 1/2
▶ $true
~> <= 1/3 1/2 1/1
▶ $true
// float64
~> <= 1.0 1.0 2.0
▶ $true
~> <= 1.0 2.0 1.0
▶ $false
## == ##
// int
~> == 1 1 1
▶ $true
~> == 1 2 1
▶ $false
// *big.Int
~> == 100000000000000000001 100000000000000000001 100000000000000000001
▶ $true
~> == 100000000000000000001 100000000000000000002 100000000000000000001
▶ $false
// *big.Rat
~> == 1/2 1/2 1/2
▶ $true
~> == 1/2 1/3 1/2
▶ $false
// float64
~> == 1.0 1.0 1.0
▶ $true
~> == 1.0 2.0 1.0
▶ $false
## != ##
// int
~> != 1 2 1
▶ $true
~> != 1 1 2
▶ $false
// *big.Int
~> != 100000000000000000001 100000000000000000002 100000000000000000001
▶ $true
~> != 100000000000000000001 100000000000000000001 100000000000000000002
▶ $false
// *big.Rat
~> != 1/2 1/3 1/2
▶ $true
~> != 1/2 1/2 1/3
▶ $false
// float64
~> != 1.0 2.0 1.0
▶ $true
~> != 1.0 1.0 2.0
▶ $false
## > ##
// int
~> > 3 2 1
▶ $true
~> > 3 1 2
▶ $false
// *big.Int
~> > 100000000000000000003 100000000000000000002 100000000000000000001
▶ $true
~> > 100000000000000000003 100000000000000000001 100000000000000000002
▶ $false
// *big.Rat
~> > 1/2 1/3 1/4
▶ $true
~> > 1/2 1/4 1/3
▶ $false
// float64
~> > 3.0 2.0 1.0
▶ $true
~> > 3.0 1.0 2.0
▶ $false
## >= ##
// int
~> >= 3 3 2
▶ $true
~> >= 3 2 3
▶ $false
// *big.Int
~> >= 100000000000000000003 100000000000000000003 100000000000000000002
▶ $true
~> >= 100000000000000000003 100000000000000000002 100000000000000000003
▶ $false
// *big.Rat
~> >= 1/2 1/2 1/3
▶ $true
~> >= 1/2 1/3 1/2
▶ $false
// float64
~> >= 3.0 3.0 2.0
▶ $true
~> >= 3.0 2.0 3.0
▶ $false
////////////////////
# basic arithmetic #
////////////////////
## + ##
// no argument
~> +
▶ (num 0)
// int
~> + 233100 233
▶ (num 233333)
// *big.Int
~> + 100000000000000000000 100000000000000000001
▶ (num 200000000000000000001)
// *big.Rat
~> + 1/2 1/3 1/4
▶ (num 13/12)
// float64
~> + 0.5 0.25 1.0
▶ (num 1.75)
## mixing types ##
// Only test with +; the other commands share the same code path for handling
// mixed types.
// int and *big.Int
~> + 1 2 100000000000000000000
▶ (num 100000000000000000003)
// int, *big,Int and *big.Rat
~> + 1/2 1/2 1 100000000000000000000
▶ (num 100000000000000000002)
// int, *big.Rat and float64
~> + 0.5 1/4 1
▶ (num 1.75)
## - ##
// no argument is unsupported
~> -
Exception: arity mismatch: arguments must be 1 or more values, but is 0 values
[tty]:1:1-1: -
// one argument is negation
~> - 233
▶ (num -233)
~> - 100000000000000000000
▶ (num -100000000000000000000)
~> - 1/2
▶ (num -1/2)
~> - 1.0
▶ (num -1.0)
// int
~> - 20 10 2
▶ (num 8)
// *big.Int
~> - 200000000000000000003 100000000000000000001
▶ (num 100000000000000000002)
// *big.Rat
~> - 1/2 1/3
▶ (num 1/6)
// float64
~> - 2.0 1.0 0.5
▶ (num 0.5)
## * ##
// no argument
~> *
▶ (num 1)
// int
~> * 2 7 4
▶ (num 56)
// *big.Int
~> * 2 100000000000000000001
▶ (num 200000000000000000002)
// *big.Rat
~> * 1/2 1/3
▶ (num 1/6)
// float64
~> * 2.0 0.5 1.75
▶ (num 1.75)
// 0 * non-infinity
~> * 0 1/2 1.0
▶ (num 0)
// 0 * infinity
~> * 0 +Inf
▶ (num NaN)
## / ##
// one argument - inversion
~> / 2
▶ (num 1/2)
~> / 100000000000000000000
▶ (num 1/100000000000000000000)
~> / 2.0
▶ (num 0.5)
// int
~> / 233333 353
▶ (num 661)
~> / 3 4 2
▶ (num 3/8)
// *big.Int
~> / 200000000000000000000 100000000000000000000
▶ (num 2)
~> / 200000000000000000000 2
▶ (num 100000000000000000000)
~> / 100000000000000000001 100000000000000000000
▶ (num 100000000000000000001/100000000000000000000)
// float64
~> / 1.0 2.0 4.0
▶ (num 0.125)
~> / 0 1/2 0.1
▶ (num 0)
// anything / 0
~> / 0 0
Exception: bad value: divisor must be number other than exact 0, but is exact 0
[tty]:1:1-5: / 0 0
~> / 1 0
Exception: bad value: divisor must be number other than exact 0, but is exact 0
[tty]:1:1-5: / 1 0
~> / 1.0 0
Exception: bad value: divisor must be number other than exact 0, but is exact 0
[tty]:1:1-7: / 1.0 0
## % ##
~> % 23 7
▶ (num 2)
~> % 1 0
Exception: bad value: divisor must be number other than exact 0, but is exact 0
[tty]:1:1-5: % 1 0
///////////
# randint #
///////////
~> randint 1 2
▶ (num 1)
~> randint 1
▶ (num 0)
~> var i = (randint 10 100)
and (<= 10 $i) (< $i 100)
▶ $true
~> var i = (randint 10); and (<= 0 $i) (< $i 10)
▶ $true
## argument checking ##
~> randint 2 1
Exception: bad value: high value must be larger than 2, but is 1
[tty]:1:1-11: randint 2 1
~> randint
Exception: arity mismatch: arguments must be 1 to 2 values, but is 0 values
[tty]:1:1-7: randint
~> randint 1 2 3
Exception: arity mismatch: arguments must be 1 to 2 values, but is 3 values
[tty]:1:1-13: randint 1 2 3
/////////////
# -randseed #
/////////////
//reseed-afterwards
// -randseed makes randint deterministic ##
~> fn f { -randseed 0; randint 10 }
eq (f) (f)
▶ $true
/////////
# range #
/////////
## argument arity check ##
~> range
Exception: arity mismatch: arguments must be 1 to 2 values, but is 0 values
[tty]:1:1-5: range
~> range 0 1 2
Exception: arity mismatch: arguments must be 1 to 2 values, but is 3 values
[tty]:1:1-11: range 0 1 2
## int ##
// counting up
~> range 3
▶ (num 0)
▶ (num 1)
▶ (num 2)
~> range 1 3
▶ (num 1)
▶ (num 2)
// counting down
~> range -1 10 &step=3
▶ (num -1)
▶ (num 2)
▶ (num 5)
▶ (num 8)
~> range 3 -3
▶ (num 3)
▶ (num 2)
▶ (num 1)
▶ (num 0)
▶ (num -1)
▶ (num -2)
// invalid step
~> range &step=-1 1
Exception: bad value: step must be positive, but is -1
[tty]:1:1-16: range &step=-1 1
~> range &step=1 1 0
Exception: bad value: step must be negative, but is 1
[tty]:1:1-17: range &step=1 1 0
// bubbling output error
~> range 2 >&-
Exception: port does not support value output
[tty]:1:1-11: range 2 >&-
## near max/min of int ##
// Values near the max/min of int need to be handled carefully to avoid
// overflow. Instead of assuming int is 64-bit or 32-bit, test interesting
// values for both cases.
// 2^63-3 to 2^63-1
~> range 9223372036854775805 9223372036854775807
▶ (num 9223372036854775805)
▶ (num 9223372036854775806)
~> range 9223372036854775807 9223372036854775805
▶ (num 9223372036854775807)
▶ (num 9223372036854775806)
// -2^63 to -2^63+2
~> range -9223372036854775808 -9223372036854775806
▶ (num -9223372036854775808)
▶ (num -9223372036854775807)
~> range -9223372036854775806 -9223372036854775808
▶ (num -9223372036854775806)
▶ (num -9223372036854775807)
// 2^31-3 to 2^31-1
~> range 2147483645 2147483647
▶ (num 2147483645)
▶ (num 2147483646)
~> range 2147483647 2147483645
▶ (num 2147483647)
▶ (num 2147483646)
// -2^31 to -2^31+2
~> range -2147483648 -2147483646
▶ (num -2147483648)
▶ (num -2147483647)
~> range -2147483646 -2147483648
▶ (num -2147483646)
▶ (num -2147483647)
## *big.Int ##
// counting up
~> range 100000000000000000000 100000000000000000003
▶ (num 100000000000000000000)
▶ (num 100000000000000000001)
▶ (num 100000000000000000002)
~> range 100000000000000000000 100000000000000000003 &step=2
▶ (num 100000000000000000000)
▶ (num 100000000000000000002)
// counting down
~> range 100000000000000000003 100000000000000000000
▶ (num 100000000000000000003)
▶ (num 100000000000000000002)
▶ (num 100000000000000000001)
~> range 100000000000000000003 100000000000000000000 &step=-2
▶ (num 100000000000000000003)
▶ (num 100000000000000000001)
// invalid step
~> range &step=-100000000000000000000 10
Exception: bad value: step must be positive, but is -100000000000000000000
[tty]:1:1-37: range &step=-100000000000000000000 10
~> range &step=100000000000000000000 10 0
Exception: bad value: step must be negative, but is 100000000000000000000
[tty]:1:1-38: range &step=100000000000000000000 10 0
// bubbling output error
~> range 100000000000000000000 100000000000000000001 >&-
Exception: port does not support value output
[tty]:1:1-53: range 100000000000000000000 100000000000000000001 >&-
## *big.Rat ##
// counting up
~> range 23/10
▶ (num 0)
▶ (num 1)
▶ (num 2)
~> range 1/10 23/10
▶ (num 1/10)
▶ (num 11/10)
▶ (num 21/10)
~> range 1/10 9/10 &step=3/10
▶ (num 1/10)
▶ (num 2/5)
▶ (num 7/10)
// counting down
~> range 23/10 1/10
▶ (num 23/10)
▶ (num 13/10)
▶ (num 3/10)
~> range 9/10 0/10 &step=-3/10
▶ (num 9/10)
▶ (num 3/5)
▶ (num 3/10)
// invalid step
~> range &step=-1/2 10
Exception: bad value: step must be positive, but is -1/2
[tty]:1:1-19: range &step=-1/2 10
~> range &step=1/2 10 0
Exception: bad value: step must be negative, but is 1/2
[tty]:1:1-20: range &step=1/2 10 0
// bubbling output error
~> range 1/2 3/2 >&-
Exception: port does not support value output
[tty]:1:1-17: range 1/2 3/2 >&-
## float64 ##
// counting up
~> range 1.2
▶ (num 0.0)
▶ (num 1.0)
~> range &step=0.5 1 3
▶ (num 1.0)
▶ (num 1.5)
▶ (num 2.0)
▶ (num 2.5)
// counting down
~> range 1.2 -1.2
▶ (num 1.2)
▶ (num 0.19999999999999996)
▶ (num -0.8)
~> range &step=-0.5 3 1
▶ (num 3.0)
▶ (num 2.5)
▶ (num 2.0)
▶ (num 1.5)
// Nearing the maximum float64 value where x+1 = x.
~> range 9007199254740990.0 +inf
▶ (num 9.00719925474099e+15)
▶ (num 9007199254740991.0)
▶ (num 9007199254740992.0)
~> range 9007199254740992.0 9007199254740990.0
▶ (num 9007199254740992.0)
▶ (num 9007199254740991.0)
// invalid step
~> range &step=-0.5 10
Exception: bad value: step must be positive, but is -0.5
[tty]:1:1-19: range &step=-0.5 10
~> range &step=0.5 10 0
Exception: bad value: step must be negative, but is 0.5
[tty]:1:1-20: range &step=0.5 10 0
// bubbling output error
~> range 1.2 >&-
Exception: port does not support value output
[tty]:1:1-13: range 1.2 >&-