github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/object/reflect/float.go (about) 1 package reflect 2 3 import ( 4 "math" 5 "reflect" 6 7 "github.com/hirochachacha/plua/internal/tables" 8 "github.com/hirochachacha/plua/object" 9 "github.com/hirochachacha/plua/object/fnutil" 10 ) 11 12 func buildFloatMT() { 13 mt := tables.NewTableSize(0, 14) 14 15 mt.Set(object.TM_METATABLE, object.True) 16 mt.Set(object.TM_NAME, object.String("FLOAT*")) 17 mt.Set(object.TM_TOSTRING, tostring(toFloat)) 18 mt.Set(object.TM_INDEX, index(toFloat)) 19 20 mt.Set(object.TM_EQ, cmp(func(x, y reflect.Value) bool { return x.Float() == y.Float() }, toFloat)) 21 mt.Set(object.TM_LT, cmp(func(x, y reflect.Value) bool { return x.Float() < y.Float() }, toFloat)) 22 mt.Set(object.TM_LE, cmp(func(x, y reflect.Value) bool { return x.Float() <= y.Float() }, toFloat)) 23 24 mt.Set(object.TM_UNM, unary(func(x reflect.Value) reflect.Value { return reflect.ValueOf(-x.Float()) }, toFloat, mt)) 25 26 mt.Set(object.TM_ADD, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 27 return reflect.ValueOf(x.Float() + y.Float()), nil 28 }, toFloat, mt)) 29 mt.Set(object.TM_SUB, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 30 return reflect.ValueOf(x.Float() - y.Float()), nil 31 }, toFloat, mt)) 32 mt.Set(object.TM_MUL, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 33 return reflect.ValueOf(x.Float() * y.Float()), nil 34 }, toFloat, mt)) 35 mt.Set(object.TM_MOD, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 36 return reflect.ValueOf(fmod(x.Float(), y.Float())), nil 37 }, toFloat, mt)) 38 mt.Set(object.TM_POW, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 39 return reflect.ValueOf(math.Pow(x.Float(), y.Float())), nil 40 }, toFloat, mt)) 41 mt.Set(object.TM_DIV, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 42 return reflect.ValueOf(x.Float() / y.Float()), nil 43 }, toFloat, mt)) 44 mt.Set(object.TM_IDIV, binary(func(x, y reflect.Value) (reflect.Value, *object.RuntimeError) { 45 return reflect.ValueOf(fidiv(x.Float(), y.Float())), nil 46 }, toFloat, mt)) 47 48 floatMT = mt 49 } 50 51 func toFloat(ap *fnutil.ArgParser, n int) (reflect.Value, *object.RuntimeError) { 52 if f, err := ap.ToGoFloat64(n); err == nil { 53 return reflect.ValueOf(f), nil 54 } 55 val, err := toValue(ap, n, "FLOAT*") 56 if err != nil { 57 return reflect.Value{}, err 58 } 59 switch val.Kind() { 60 case reflect.Float32, reflect.Float64: 61 default: 62 return reflect.Value{}, ap.TypeError(n, "FLOAT*") 63 } 64 return val, nil 65 } 66 67 func fmod(x, y float64) float64 { 68 rem := math.Mod(x, y) 69 70 if rem < 0 { 71 rem += y 72 } 73 74 return rem 75 } 76 77 func fidiv(x, y float64) float64 { 78 f, _ := math.Modf(x / y) 79 80 return f 81 }