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  }