github.com/MontFerret/ferret@v0.18.0/pkg/runtime/values/float.go (about) 1 package values 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "hash/fnv" 7 "math" 8 "strconv" 9 10 "github.com/wI2L/jettison" 11 12 "github.com/MontFerret/ferret/pkg/runtime/core" 13 "github.com/MontFerret/ferret/pkg/runtime/values/types" 14 ) 15 16 type Float float64 17 18 var NaN = Float(math.NaN()) 19 20 const ZeroFloat = Float(0.0) 21 22 func NewFloat(input float64) Float { 23 return Float(input) 24 } 25 26 func ParseFloat(input interface{}) (Float, error) { 27 if core.IsNil(input) { 28 return ZeroFloat, nil 29 } 30 31 i, ok := input.(float64) 32 33 if ok { 34 if i == 0 { 35 return ZeroFloat, nil 36 } 37 38 return Float(i), nil 39 } 40 41 // try to cast 42 str, ok := input.(string) 43 44 if ok { 45 i, err := strconv.Atoi(str) 46 47 if err == nil { 48 if i == 0 { 49 return ZeroFloat, nil 50 } 51 52 return Float(i), nil 53 } 54 } 55 56 return ZeroFloat, core.Error(core.ErrInvalidType, "expected 'float'") 57 } 58 59 func MustParseFloat(input interface{}) Float { 60 res, err := ParseFloat(input) 61 62 if err != nil { 63 panic(err) 64 } 65 66 return res 67 } 68 69 func IsNaN(input Float) Boolean { 70 return NewBoolean(math.IsNaN(float64(input))) 71 } 72 73 func IsInf(input Float, sign Int) Boolean { 74 return NewBoolean(math.IsInf(float64(input), int(sign))) 75 } 76 77 func (t Float) MarshalJSON() ([]byte, error) { 78 return jettison.MarshalOpts(float64(t), jettison.NoHTMLEscaping()) 79 } 80 81 func (t Float) Type() core.Type { 82 return types.Float 83 } 84 85 func (t Float) String() string { 86 return fmt.Sprintf("%v", float64(t)) 87 } 88 89 func (t Float) Compare(other core.Value) int64 { 90 otherType := other.Type() 91 raw := float64(t) 92 93 if otherType == types.Float { 94 f := other.Unwrap().(float64) 95 96 if raw == f { 97 return 0 98 } 99 100 if raw < f { 101 return -1 102 } 103 104 return +1 105 } 106 107 if otherType == types.Int { 108 i := other.Unwrap().(int) 109 f := float64(i) 110 111 if raw == f { 112 return 0 113 } 114 115 if raw < f { 116 return -1 117 } 118 119 return +1 120 } 121 122 return types.Compare(types.Float, otherType) 123 } 124 125 func (t Float) Unwrap() interface{} { 126 return float64(t) 127 } 128 129 func (t Float) Hash() uint64 { 130 h := fnv.New64a() 131 132 h.Write([]byte(t.Type().String())) 133 h.Write([]byte(":")) 134 135 bytes := make([]byte, 8) 136 binary.LittleEndian.PutUint64(bytes, math.Float64bits(float64(t))) 137 h.Write(bytes) 138 139 return h.Sum64() 140 } 141 142 func (t Float) Copy() core.Value { 143 return t 144 }