github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/mods/math/math_test.go (about)

     1  package math
     2  
     3  import (
     4  	"math"
     5  	"math/big"
     6  	"strconv"
     7  	"testing"
     8  
     9  	"src.elv.sh/pkg/eval"
    10  	"src.elv.sh/pkg/eval/errs"
    11  	. "src.elv.sh/pkg/eval/evaltest"
    12  )
    13  
    14  const (
    15  	zeros = "0000000000000000000"
    16  	// Values that exceed the range of int64, used for testing BigInt.
    17  	z  = "1" + zeros + "0"
    18  	z1 = "1" + zeros + "1" // z+1
    19  	z2 = "1" + zeros + "2" // z+2
    20  )
    21  
    22  var minIntString = strconv.Itoa(minInt)
    23  
    24  func TestMath(t *testing.T) {
    25  	setup := func(ev *eval.Evaler) {
    26  		ev.AddGlobal(eval.NsBuilder{}.AddNs("math", Ns).Ns())
    27  	}
    28  	TestWithSetup(t, setup,
    29  		That("math:abs 2").Puts(2),
    30  		That("math:abs -2").Puts(2),
    31  		That("math:abs "+minIntString).Puts(bigInt(minIntString[1:])),
    32  		That("math:abs "+z).Puts(bigInt(z)),
    33  		That("math:abs -"+z).Puts(bigInt(z)),
    34  		That("math:abs -1/2").Puts(big.NewRat(1, 2)),
    35  		That("math:abs 1/2").Puts(big.NewRat(1, 2)),
    36  		That("math:abs 2.1").Puts(2.1),
    37  		That("math:abs -2.1").Puts(2.1),
    38  
    39  		That("math:is-inf 1.3").Puts(false),
    40  		That("math:is-inf &sign=0 inf").Puts(true),
    41  		That("math:is-inf &sign=1 inf").Puts(true),
    42  		That("math:is-inf &sign=-1 -inf").Puts(true),
    43  		That("math:is-inf &sign=1 -inf").Puts(false),
    44  		That("math:is-inf -inf").Puts(true),
    45  		That("math:is-inf nan").Puts(false),
    46  		That("math:is-inf 1").Puts(false),
    47  		That("math:is-inf "+z).Puts(false),
    48  		That("math:is-inf 1/2").Puts(false),
    49  
    50  		That("math:is-nan 1.3").Puts(false),
    51  		That("math:is-nan inf").Puts(false),
    52  		That("math:is-nan nan").Puts(true),
    53  		That("math:is-nan 1").Puts(false),
    54  		That("math:is-nan "+z).Puts(false),
    55  		That("math:is-nan 1/2").Puts(false),
    56  
    57  		That("math:max").Throws(
    58  			errs.ArityMismatch{What: "arguments here", ValidLow: 1, ValidHigh: -1, Actual: 0},
    59  			"math:max"),
    60  		That("math:max 42").Puts(42),
    61  		That("math:max -3 3 10 -4").Puts(10),
    62  		That("math:max 2 10 "+z).Puts(bigInt(z)),
    63  		That("math:max "+z1+" "+z2+" "+z).Puts(bigInt(z2)),
    64  		That("math:max 1/2 1/3 2/3").Puts(big.NewRat(2, 3)),
    65  		That("math:max 1.0 2.0").Puts(2.0),
    66  		That("math:max 3 NaN 5").Puts(math.NaN()),
    67  
    68  		That("math:min").Throws(
    69  			errs.ArityMismatch{What: "arguments here", ValidLow: 1, ValidHigh: -1, Actual: 0},
    70  			"math:min"),
    71  		That("math:min 42").Puts(42),
    72  		That("math:min -3 3 10 -4").Puts(-4),
    73  		That("math:min 2 10 "+z).Puts(2),
    74  		That("math:min "+z1+" "+z2+" "+z).Puts(bigInt(z)),
    75  		That("math:min 1/2 1/3 2/3").Puts(big.NewRat(1, 3)),
    76  		That("math:min 1.0 2.0").Puts(1.0),
    77  		That("math:min 3 NaN 5").Puts(math.NaN()),
    78  
    79  		// Tests below this line are tests against simple bindings for Go's math package.
    80  
    81  		That("put $math:pi").Puts(math.Pi),
    82  		That("put $math:e").Puts(math.E),
    83  
    84  		That("math:ceil 2.1").Puts(3.0),
    85  		That("math:ceil -2.1").Puts(-2.0),
    86  
    87  		That("math:floor 2.1").Puts(2.0),
    88  		That("math:floor -2.1").Puts(-3.0),
    89  
    90  		That("math:round 2.1").Puts(2.0),
    91  		That("math:round -2.1").Puts(-2.0),
    92  		That("math:round 2.5").Puts(3.0),
    93  		That("math:round -2.5").Puts(-3.0),
    94  		That("math:round (float64 Inf)").Puts(math.Inf(1)),
    95  		That("math:round (float64 NaN)").Puts(math.NaN()),
    96  
    97  		That("math:round-to-even 2.1").Puts(2.0),
    98  		That("math:round-to-even -2.1").Puts(-2.0),
    99  		That("math:round-to-even 2.5").Puts(2.0),
   100  		That("math:round-to-even -2.5").Puts(-2.0),
   101  		That("math:round-to-even (float64 Inf)").Puts(math.Inf(1)),
   102  		That("math:round-to-even (float64 NaN)").Puts(math.NaN()),
   103  
   104  		That("math:trunc 2.1").Puts(2.0),
   105  		That("math:trunc -2.1").Puts(-2.0),
   106  		That("math:trunc 2.5").Puts(2.0),
   107  		That("math:trunc -2.5").Puts(-2.0),
   108  		That("math:trunc (float64 Inf)").Puts(math.Inf(1)),
   109  		That("math:trunc (float64 NaN)").Puts(math.NaN()),
   110  
   111  		That("math:log $math:e").Puts(1.0),
   112  		That("math:log 1").Puts(0.0),
   113  		That("math:log 0").Puts(math.Inf(-1)),
   114  		That("math:log -1").Puts(math.NaN()),
   115  
   116  		That("math:log10 10.0").Puts(1.0),
   117  		That("math:log10 100.0").Puts(2.0),
   118  		That("math:log10 1").Puts(0.0),
   119  		That("math:log10 0").Puts(math.Inf(-1)),
   120  		That("math:log10 -1").Puts(math.NaN()),
   121  
   122  		That("math:log2 8").Puts(3.0),
   123  		That("math:log2 1024.0").Puts(10.0),
   124  		That("math:log2 1").Puts(0.0),
   125  		That("math:log2 0").Puts(math.Inf(-1)),
   126  		That("math:log2 -1").Puts(math.NaN()),
   127  
   128  		That("math:cos 0").Puts(1.0),
   129  		That("math:cos 1").Puts(math.Cos(1.0)),
   130  		That("math:cos $math:pi").Puts(-1.0),
   131  
   132  		That("math:cosh 0").Puts(1.0),
   133  		That("math:cosh inf").Puts(math.Inf(1)),
   134  		That("math:cosh nan").Puts(math.NaN()),
   135  
   136  		That("math:sin 0").Puts(0.0),
   137  		That("math:sin 1").Puts(math.Sin(1.0)),
   138  		That("math:sin $math:pi").Puts(math.Sin(math.Pi)),
   139  
   140  		That("math:sinh 0").Puts(0.0),
   141  		That("math:sinh inf").Puts(math.Inf(1)),
   142  		That("math:sinh nan").Puts(math.NaN()),
   143  
   144  		That("math:tan 0").Puts(0.0),
   145  		That("math:tan 1").Puts(math.Tan(1.0)),
   146  		That("math:tan $math:pi").Puts(math.Tan(math.Pi)),
   147  
   148  		That("math:tanh 0").Puts(0.0),
   149  		That("math:tanh inf").Puts(1.0),
   150  		That("math:tanh nan").Puts(math.NaN()),
   151  
   152  		// This block of tests isn't strictly speaking necessary. But it helps
   153  		// ensure that we're not just confirming Go statements such as
   154  		//    math.Tan(math.Pi) == math.Tan(math.Pi)
   155  		// are true. The ops that should return a zero value do not actually
   156  		// do so. Which illustrates why an approximate match is needed.
   157  		That("math:cos 1").Puts(Approximately{F: 0.5403023058681397174}),
   158  		That("math:sin 1").Puts(Approximately{F: 0.8414709848078965066}),
   159  		That("math:sin $math:pi").Puts(Approximately{F: 0.0}),
   160  		That("math:tan 1").Puts(Approximately{F: 1.5574077246549023}),
   161  		That("math:tan $math:pi").Puts(Approximately{F: 0.0}),
   162  
   163  		That("math:sqrt 0").Puts(0.0),
   164  		That("math:sqrt 4").Puts(2.0),
   165  		That("math:sqrt -4").Puts(math.NaN()),
   166  
   167  		// Test the inverse trigonometric block of functions.
   168  		That("math:acos 0").Puts(math.Acos(0)),
   169  		That("math:acos 1").Puts(math.Acos(1)),
   170  		That("math:acos 1.00001").Puts(math.NaN()),
   171  
   172  		That("math:asin 0").Puts(math.Asin(0)),
   173  		That("math:asin 1").Puts(math.Asin(1)),
   174  		That("math:asin 1.00001").Puts(math.NaN()),
   175  
   176  		That("math:atan 0").Puts(math.Atan(0)),
   177  		That("math:atan 1").Puts(math.Atan(1)),
   178  		That("math:atan inf").Puts(math.Pi/2),
   179  
   180  		// Test the inverse hyperbolic trigonometric block of functions.
   181  		That("math:acosh 0").Puts(math.Acosh(0)),
   182  		That("math:acosh 1").Puts(math.Acosh(1)),
   183  		That("math:acosh nan").Puts(math.NaN()),
   184  
   185  		That("math:asinh 0").Puts(math.Asinh(0)),
   186  		That("math:asinh 1").Puts(math.Asinh(1)),
   187  		That("math:asinh inf").Puts(math.Inf(1)),
   188  
   189  		That("math:atanh 0").Puts(math.Atanh(0)),
   190  		That("math:atanh 1").Puts(math.Inf(1)),
   191  
   192  		That("math:pow nan 2").Puts(math.NaN()),
   193  		That("math:pow inf 2").Puts(math.Inf(1)),
   194  		That("math:pow 1 3").Puts(1.0),
   195  		That("math:pow 2 3").Puts(8.0),
   196  		That("math:pow -2 2").Puts(4.0),
   197  
   198  		That("math:pow10 0").Puts(1.0),
   199  		That("math:pow10 3").Puts(1000.0),
   200  		That("math:pow10 -3").Puts(0.001),
   201  	)
   202  }
   203  
   204  func bigInt(s string) *big.Int {
   205  	z, ok := new(big.Int).SetString(s, 0)
   206  	if !ok {
   207  		panic("cannot parse as big int: " + s)
   208  	}
   209  	return z
   210  }