// Go math-library functions package bifs import ( "math" "github.com/johnkerl/miller/v6/pkg/lib" "github.com/johnkerl/miller/v6/pkg/mlrval" ) // Return error (unary math-library func) func _math_unary_erro1(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.FromTypeErrorUnary(fname, input1) } // Return absent (unary math-library func) func _math_unary_absn1(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.ABSENT } // Return null (unary math-library func) func _math_unary_null1(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.NULL } // Return void (unary math-library func) func _math_unary_void1(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.VOID } func math_unary_f_i(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.FromFloat(f(float64(input1.AcquireIntValue()))) } func math_unary_i_i(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.FromInt(int64(f(float64(input1.AcquireIntValue())))) } func math_unary_f_f(input1 *mlrval.Mlrval, f mathLibUnaryFunc, fname string) *mlrval.Mlrval { return mlrval.FromFloat(f(input1.AcquireFloatValue())) } // Disposition vector for unary mathlib functions var mudispo = [mlrval.MT_DIM]mathLibUnaryFuncWrapper{ /*INT */ math_unary_f_i, /*FLOAT */ math_unary_f_f, /*BOOL */ _math_unary_erro1, /*VOID */ _math_unary_void1, /*STRING */ _math_unary_erro1, /*BYTES */ _math_unary_erro1, /*ARRAY */ _math_unary_absn1, /*MAP */ _math_unary_absn1, /*FUNC */ _math_unary_erro1, /*ERROR */ _math_unary_erro1, /*NULL */ _math_unary_null1, /*ABSENT */ _math_unary_absn1, } func BIF_acos(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Acos, "acos") } func BIF_acosh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Acosh, "acosh") } func BIF_asin(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Asin, "asin") } func BIF_asinh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Asinh, "asinh") } func BIF_atan(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Atan, "atan") } func BIF_atanh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Atanh, "atanh") } func BIF_cbrt(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Cbrt, "atan") } func BIF_cos(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Cos, "cos") } func BIF_cosh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Cosh, "cosh") } func BIF_erf(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Erf, "erf") } func BIF_erfc(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Erfc, "erfc") } func BIF_exp(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Exp, "exp") } func BIF_expm1(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Expm1, "expm1") } func BIF_invqnorm(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, lib.Invqnorm, "invqnorm") } func BIF_log(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Log, "log") } func BIF_log10(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Log10, "log10") } func BIF_log1p(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Log1p, "log1p") } func BIF_qnorm(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, lib.Qnorm, "qnorm") } func BIF_sin(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Sin, "sin") } func BIF_sinh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Sinh, "sinh") } func BIF_sqrt(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Sqrt, "sqrt") } func BIF_tan(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Tan, "tan") } func BIF_tanh(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mudispo[input1.Type()](input1, math.Tanh, "tanh") } // Disposition vector for unary mathlib functions which are int-preserving var imudispo = [mlrval.MT_DIM]mathLibUnaryFuncWrapper{ /*INT */ math_unary_i_i, /*FLOAT */ math_unary_f_f, /*BOOL */ _math_unary_erro1, /*VOID */ _math_unary_void1, /*STRING */ _math_unary_erro1, /*BYTES */ _math_unary_erro1, /*ARRAY */ _math_unary_absn1, /*MAP */ _math_unary_absn1, /*FUNC */ _math_unary_erro1, /*ERROR */ _math_unary_erro1, /*NULL */ _math_unary_null1, /*ABSENT */ _math_unary_absn1, } // Int-preserving func BIF_abs(input1 *mlrval.Mlrval) *mlrval.Mlrval { return imudispo[input1.Type()](input1, math.Abs, "abs") } // xxx func BIF_ceil(input1 *mlrval.Mlrval) *mlrval.Mlrval { return imudispo[input1.Type()](input1, math.Ceil, "ceil") } // xxx func BIF_floor(input1 *mlrval.Mlrval) *mlrval.Mlrval { return imudispo[input1.Type()](input1, math.Floor, "floor") } // xxx func BIF_round(input1 *mlrval.Mlrval) *mlrval.Mlrval { return imudispo[input1.Type()](input1, math.Round, "round") } // xxx func BIF_sgn(input1 *mlrval.Mlrval) *mlrval.Mlrval { return imudispo[input1.Type()](input1, lib.Sgn, "sgn") } // xxx // Exponentiation: DSL operator '**'. See also // https://johnkerl.org/miller6/reference-main-arithmetic.html func pow_f_ii(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { foutput := math.Pow(float64(input1.AcquireIntValue()), float64(input2.AcquireIntValue())) ioutput := int64(foutput) // Int raised to int power should be float if it can be (i.e. unless overflow) if float64(ioutput) == foutput { return mlrval.FromInt(ioutput) } return mlrval.FromFloat(foutput) } func pow_f_if(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Pow(float64(input1.AcquireIntValue()), input2.AcquireFloatValue())) } func pow_f_fi(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Pow(input1.AcquireFloatValue(), float64(input2.AcquireIntValue()))) } func pow_f_ff(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Pow(input1.AcquireFloatValue(), input2.AcquireFloatValue())) } func powte(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromTypeErrorBinary("**", input1, input2) } var pow_dispositions = [mlrval.MT_DIM][mlrval.MT_DIM]BinaryFunc{ // . INT FLOAT BOOL VOID STRING BYTES ARRAY MAP FUNC ERROR NULL ABSENT /*INT */ {pow_f_ii, pow_f_if, powte, _void, powte, powte, powte, powte, powte, powte, powte, _1___}, /*FLOAT */ {pow_f_fi, pow_f_ff, powte, _void, powte, powte, powte, powte, powte, powte, powte, _1___}, /*BOOL */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*VOID */ {_void, _void, powte, _void, powte, powte, powte, powte, powte, powte, powte, _absn}, /*STRING */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*BYTES */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*ARRAY */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*MAP */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*FUNC */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*ERROR */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*NULL */ {powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, powte, _absn}, /*ABSENT */ {_i0__, _f0__, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn}, } func BIF_pow(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return pow_dispositions[input1.Type()][input2.Type()](input1, input2) } func atan2_f_ii(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Atan2(float64(input1.AcquireIntValue()), float64(input2.AcquireIntValue()))) } func atan2_f_if(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Atan2(float64(input1.AcquireIntValue()), input2.AcquireFloatValue())) } func atan2_f_fi(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Atan2(input1.AcquireFloatValue(), float64(input2.AcquireIntValue()))) } func atan2_f_ff(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(math.Atan2(input1.AcquireFloatValue(), input2.AcquireFloatValue())) } func atan2te(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromTypeErrorBinary("atan2", input1, input2) } var atan2_dispositions = [mlrval.MT_DIM][mlrval.MT_DIM]BinaryFunc{ // . INT FLOAT BOOL VOID STRING BYTES ARRAY MAP FUNC ERROR NULL ABSENT /*INT */ {atan2_f_ii, atan2_f_if, atan2te, _void, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _1___}, /*FLOAT */ {atan2_f_fi, atan2_f_ff, atan2te, _void, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _1___}, /*BOOL */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*VOID */ {_void, _void, atan2te, _void, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*STRING */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*BYTES */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*ARRAY */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*MAP */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*FUNC */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*ERROR */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*NULL */ {atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, atan2te, _absn}, /*ABSENT */ {_i0__, _f0__, atan2te, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn}, } func BIF_atan2(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return atan2_dispositions[input1.Type()][input2.Type()](input1, input2) } func mlr_roundm(x, m float64) float64 { return math.Round(x/m) * m } func roundm_f_ii(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromInt(int64(mlr_roundm(float64(input1.AcquireIntValue()), float64(input2.AcquireIntValue())))) } func roundm_f_if(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(mlr_roundm(float64(input1.AcquireIntValue()), input2.AcquireFloatValue())) } func roundm_f_fi(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(mlr_roundm(input1.AcquireFloatValue(), float64(input2.AcquireIntValue()))) } func roundm_f_ff(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromFloat(mlr_roundm(input1.AcquireFloatValue(), input2.AcquireFloatValue())) } func rdmte(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromTypeErrorBinary("roundm", input1, input2) } var roundm_dispositions = [mlrval.MT_DIM][mlrval.MT_DIM]BinaryFunc{ // . INT FLOAT BOOL VOID STRING BYTES ARRAY MAP FUNC ERROR NULL ABSENT /*INT */ {roundm_f_ii, roundm_f_if, rdmte, _void, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _1___}, /*FLOAT */ {roundm_f_fi, roundm_f_ff, rdmte, _void, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _1___}, /*BOOL */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*VOID */ {_void, _void, rdmte, _void, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*STRING */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*BYTES */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*ARRAY */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*MAP */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*FUNC */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*ERROR */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*NULL */ {rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, rdmte, _absn}, /*ABSENT */ {_i0__, _f0__, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn, _absn}, } func BIF_roundm(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return roundm_dispositions[input1.Type()][input2.Type()](input1, input2) } func logifit_te(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromTypeErrorBinary("logifit", input1, input2) } func BIF_logifit(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { if !input1.IsLegit() { return input1 } if !input2.IsLegit() { return input2 } if !input3.IsLegit() { return input3 } // int/float OK; rest not x, xok := input1.GetNumericToFloatValue() if !xok { return logifit_te(input1, input2) } m, mok := input2.GetNumericToFloatValue() if !mok { return logifit_te(input1, input2) } b, bok := input3.GetNumericToFloatValue() if !bok { return logifit_te(input1, input2) } return mlrval.FromFloat(1.0 / (1.0 + math.Exp(-m*x-b))) }