package eval
import (
)
func () {
addBuiltinFns(map[string]interface{}{
"float64": toFloat64,
"num": num,
"exact-num": exactNum,
"<": lt,
"<=": le,
"==": eqNum,
"!=": ne,
">": gt,
">=": ge,
"+": add,
"-": sub,
"*": mul,
"/": slash,
"%": rem,
"rand": rand.Float64,
"randint": randint,
})
}
func ( vals.Num) vals.Num {
return
}
func ( vals.Num) (vals.Num, error) {
if , := .(float64); {
:= new(big.Rat).SetFloat64()
if == nil {
return nil, errs.BadValue{What: "argument here",
Valid: "finite float", Actual: vals.ToString()}
}
return , nil
}
return , nil
}
func ( float64) float64 {
return
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return < },
func(, *big.Int) bool { return .Cmp() < 0 },
func(, *big.Rat) bool { return .Cmp() < 0 },
func(, float64) bool { return < })
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return <= },
func(, *big.Int) bool { return .Cmp() <= 0 },
func(, *big.Rat) bool { return .Cmp() <= 0 },
func(, float64) bool { return <= })
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return == },
func(, *big.Int) bool { return .Cmp() == 0 },
func(, *big.Rat) bool { return .Cmp() == 0 },
func(, float64) bool { return == })
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return != },
func(, *big.Int) bool { return .Cmp() != 0 },
func(, *big.Rat) bool { return .Cmp() != 0 },
func(, float64) bool { return != })
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return > },
func(, *big.Int) bool { return .Cmp() > 0 },
func(, *big.Rat) bool { return .Cmp() > 0 },
func(, float64) bool { return > })
}
func ( ...vals.Num) bool {
return chainCompare(,
func(, int) bool { return >= },
func(, *big.Int) bool { return .Cmp() >= 0 },
func(, *big.Rat) bool { return .Cmp() >= 0 },
func(, float64) bool { return >= })
}
func ( []vals.Num,
func(, int) bool, func(, *big.Int) bool,
func(, *big.Rat) bool, func(, float64) bool) bool {
for := 0; < len()-1; ++ {
var bool
switch pair := vals.UnifyNums([:+2], 0).(type) {
case []int:
= ([0], [1])
case []*big.Int:
= ([0], [1])
case []*big.Rat:
= ([0], [1])
case []float64:
= ([0], [1])
}
if ! {
return false
}
}
return true
}
func ( ...vals.Num) vals.Num {
:= vals.UnifyNums(, vals.BigInt)
switch nums := .(type) {
case []*big.Int:
:= big.NewInt(0)
for , := range {
.Add(, )
}
return vals.NormalizeBigInt()
case []*big.Rat:
:= big.NewRat(0, 1)
for , := range {
.Add(, )
}
return vals.NormalizeBigRat()
case []float64:
:= float64(0)
for , := range {
+=
}
return
default:
panic("unreachable")
}
}
func ( ...vals.Num) (vals.Num, error) {
if len() == 0 {
return nil, errs.ArityMismatch{
What: "arguments here",
ValidLow: 1, ValidHigh: -1, Actual: 0,
}
}
:= vals.UnifyNums(, vals.BigInt)
switch nums := .(type) {
case []*big.Int:
:= &big.Int{}
if len() == 1 {
.Neg([0])
return , nil
}
.Set([0])
for , := range [1:] {
.Sub(, )
}
return , nil
case []*big.Rat:
:= &big.Rat{}
if len() == 1 {
.Neg([0])
return , nil
}
.Set([0])
for , := range [1:] {
.Sub(, )
}
return , nil
case []float64:
if len() == 1 {
return -[0], nil
}
:= [0]
for , := range [1:] {
-=
}
return , nil
default:
panic("unreachable")
}
}
func ( ...vals.Num) vals.Num {
:= false
:= false
for , := range {
if == 0 {
= true
}
if , := .(float64); && math.IsInf(, 0) {
= true
break
}
}
if && ! {
return 0
}
:= vals.UnifyNums(, vals.BigInt)
switch nums := .(type) {
case []*big.Int:
:= big.NewInt(1)
for , := range {
.Mul(, )
}
return vals.NormalizeBigInt()
case []*big.Rat:
:= big.NewRat(1, 1)
for , := range {
.Mul(, )
}
return vals.NormalizeBigRat()
case []float64:
:= float64(1)
for , := range {
*=
}
return
default:
panic("unreachable")
}
}
func ( *Frame, ...vals.Num) error {
if len() == 0 {
return .Evaler.Chdir("/")
}
, := div(...)
if == nil {
.OutputChan() <- vals.FromGo()
}
return
}
var ErrDivideByZero = errs.BadValue{
What: "divisor", Valid: "number other than exact 0", Actual: "exact 0"}
func ( ...vals.Num) (vals.Num, error) {
for , := range [1:] {
if == 0 {
return nil, ErrDivideByZero
}
}
if [0] == 0 {
return 0, nil
}
:= vals.UnifyNums(, vals.BigRat)
switch nums := .(type) {
case []*big.Rat:
:= &big.Rat{}
.Set([0])
if len() == 1 {
.Inv()
return , nil
}
for , := range [1:] {
.Quo(, )
}
return , nil
case []float64:
:= [0]
if len() == 1 {
return 1 / , nil
}
for , := range [1:] {
/=
}
return , nil
default:
panic("unreachable")
}
}
func (, int) (int, error) {
if == 0 {
return 0, ErrDivideByZero
}
return % , nil
}
func (, int) (int, error) {
if >= {
return 0, ErrArgs
}
return + rand.Intn(-), nil
}