github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/float.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package grumpy 16 17 import ( 18 "fmt" 19 "math" 20 "math/big" 21 "reflect" 22 "strconv" 23 "strings" 24 "sync/atomic" 25 "unicode" 26 "unsafe" 27 ) 28 29 // FloatType is the object representing the Python 'float' type. 30 var FloatType = newBasisType("float", reflect.TypeOf(Float{}), toFloatUnsafe, ObjectType) 31 32 // Float represents Python 'float' objects. 33 type Float struct { 34 Object 35 value float64 36 hash int 37 } 38 39 // NewFloat returns a new Float holding the given floating point value. 40 func NewFloat(value float64) *Float { 41 return &Float{Object: Object{typ: FloatType}, value: value} 42 } 43 44 func toFloatUnsafe(o *Object) *Float { 45 return (*Float)(o.toPointer()) 46 } 47 48 // ToObject upcasts f to an Object. 49 func (f *Float) ToObject() *Object { 50 return &f.Object 51 } 52 53 // Value returns the underlying floating point value held by f. 54 func (f *Float) Value() float64 { 55 return f.value 56 } 57 58 func floatAbs(f *Frame, o *Object) (*Object, *BaseException) { 59 z := toFloatUnsafe(o).Value() 60 return NewFloat(math.Abs(z)).ToObject(), nil 61 } 62 63 func floatAdd(f *Frame, v, w *Object) (*Object, *BaseException) { 64 return floatArithmeticOp(f, "__add__", v, w, func(v, w float64) float64 { return v + w }) 65 } 66 67 func floatDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 68 return floatDivModOp(f, "__div__", v, w, func(v, w float64) (float64, bool) { 69 if w == 0.0 { 70 return 0, false 71 } 72 return v / w, true 73 }) 74 } 75 76 func floatDivMod(f *Frame, v, w *Object) (*Object, *BaseException) { 77 return floatDivAndModOp(f, "__divmod__", v, w, func(v, w float64) (float64, float64, bool) { 78 m, r := floatModFunc(v, w) 79 if !r { 80 return 0, 0, false 81 } 82 return math.Floor(v / w), m, true 83 }) 84 } 85 86 func floatEq(f *Frame, v, w *Object) (*Object, *BaseException) { 87 return floatCompare(toFloatUnsafe(v), w, False, True, False), nil 88 } 89 90 func floatFloat(f *Frame, o *Object) (*Object, *BaseException) { 91 return o, nil 92 } 93 94 func floatFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 95 return floatDivModOp(f, "__floordiv__", v, w, func(v, w float64) (float64, bool) { 96 if w == 0.0 { 97 return 0, false 98 } 99 return math.Floor(v / w), true 100 }) 101 } 102 103 func floatGE(f *Frame, v, w *Object) (*Object, *BaseException) { 104 return floatCompare(toFloatUnsafe(v), w, False, True, True), nil 105 } 106 107 func floatGetNewArgs(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { 108 if raised := checkMethodArgs(f, "__getnewargs__", args, FloatType); raised != nil { 109 return nil, raised 110 } 111 return NewTuple1(args[0]).ToObject(), nil 112 } 113 114 func floatGT(f *Frame, v, w *Object) (*Object, *BaseException) { 115 return floatCompare(toFloatUnsafe(v), w, False, False, True), nil 116 } 117 118 func floatHash(f *Frame, o *Object) (*Object, *BaseException) { 119 v := toFloatUnsafe(o) 120 p := (*unsafe.Pointer)(unsafe.Pointer(&v.hash)) 121 if lp := atomic.LoadPointer(p); lp != unsafe.Pointer(nil) { 122 return (*Int)(lp).ToObject(), nil 123 } 124 hash := hashFloat(v.Value()) 125 if hash == -1 { 126 hash-- 127 } 128 h := NewInt(hash) 129 atomic.StorePointer(p, unsafe.Pointer(h)) 130 131 return h.ToObject(), nil 132 } 133 134 func floatInt(f *Frame, o *Object) (*Object, *BaseException) { 135 val := toFloatUnsafe(o).Value() 136 if math.IsInf(val, 0) { 137 return nil, f.RaiseType(OverflowErrorType, "cannot convert float infinity to integer") 138 } 139 if math.IsNaN(val) { 140 return nil, f.RaiseType(OverflowErrorType, "cannot convert float NaN to integer") 141 } 142 i := big.Int{} 143 big.NewFloat(val).Int(&i) 144 if !numInIntRange(&i) { 145 return NewLong(&i).ToObject(), nil 146 } 147 return NewInt(int(i.Int64())).ToObject(), nil 148 } 149 150 func floatLong(f *Frame, o *Object) (*Object, *BaseException) { 151 val := toFloatUnsafe(o).Value() 152 if math.IsInf(val, 0) { 153 return nil, f.RaiseType(OverflowErrorType, "cannot convert float infinity to integer") 154 } 155 if math.IsNaN(val) { 156 return nil, f.RaiseType(OverflowErrorType, "cannot convert float NaN to integer") 157 } 158 i, _ := big.NewFloat(val).Int(nil) 159 return NewLong(i).ToObject(), nil 160 } 161 162 func floatLE(f *Frame, v, w *Object) (*Object, *BaseException) { 163 return floatCompare(toFloatUnsafe(v), w, True, True, False), nil 164 } 165 166 func floatLT(f *Frame, v, w *Object) (*Object, *BaseException) { 167 return floatCompare(toFloatUnsafe(v), w, True, False, False), nil 168 } 169 170 func floatMod(f *Frame, v, w *Object) (*Object, *BaseException) { 171 return floatDivModOp(f, "__mod__", v, w, floatModFunc) 172 } 173 174 func floatMul(f *Frame, v, w *Object) (*Object, *BaseException) { 175 return floatArithmeticOp(f, "__mul__", v, w, func(v, w float64) float64 { return v * w }) 176 } 177 178 func floatNative(f *Frame, o *Object) (reflect.Value, *BaseException) { 179 return reflect.ValueOf(toFloatUnsafe(o).Value()), nil 180 } 181 182 func floatNE(f *Frame, v, w *Object) (*Object, *BaseException) { 183 return floatCompare(toFloatUnsafe(v), w, True, False, True), nil 184 } 185 186 func floatNeg(f *Frame, o *Object) (*Object, *BaseException) { 187 z := toFloatUnsafe(o).Value() 188 return NewFloat(-z).ToObject(), nil 189 } 190 191 func floatNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) { 192 argc := len(args) 193 if argc == 0 { 194 return newObject(t), nil 195 } 196 if argc != 1 { 197 return nil, f.RaiseType(TypeErrorType, "'__new__' of 'float' requires 0 or 1 arguments") 198 } 199 if t != FloatType { 200 // Allocate a plain float then copy it's value into an object 201 // of the float subtype. 202 x, raised := floatNew(f, FloatType, args, nil) 203 if raised != nil { 204 return nil, raised 205 } 206 result := toFloatUnsafe(newObject(t)) 207 result.value = toFloatUnsafe(x).Value() 208 return result.ToObject(), nil 209 } 210 o := args[0] 211 if floatSlot := o.typ.slots.Float; floatSlot != nil { 212 fl, raised := floatConvert(floatSlot, f, o) 213 if raised != nil { 214 return nil, raised 215 } 216 return fl.ToObject(), nil 217 } 218 if !o.isInstance(StrType) { 219 return nil, f.RaiseType(TypeErrorType, "float() argument must be a string or a number") 220 } 221 s := toStrUnsafe(o).Value() 222 result, err := strconv.ParseFloat(s, 64) 223 if err != nil { 224 return nil, f.RaiseType(ValueErrorType, fmt.Sprintf("could not convert string to float: %s", s)) 225 } 226 return NewFloat(result).ToObject(), nil 227 } 228 229 func floatNonZero(f *Frame, o *Object) (*Object, *BaseException) { 230 return GetBool(toFloatUnsafe(o).Value() != 0).ToObject(), nil 231 } 232 233 func floatPos(f *Frame, o *Object) (*Object, *BaseException) { 234 return o, nil 235 } 236 237 func floatPow(f *Frame, v, w *Object) (*Object, *BaseException) { 238 return floatArithmeticOp(f, "__pow__", v, w, func(v, w float64) float64 { return math.Pow(v, w) }) 239 } 240 241 func floatRAdd(f *Frame, v, w *Object) (*Object, *BaseException) { 242 return floatArithmeticOp(f, "__radd__", v, w, func(v, w float64) float64 { return w + v }) 243 } 244 245 func floatRDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 246 return floatDivModOp(f, "__rdiv__", v, w, func(v, w float64) (float64, bool) { 247 if v == 0.0 { 248 return 0, false 249 } 250 return w / v, true 251 }) 252 } 253 254 func floatRDivMod(f *Frame, v, w *Object) (*Object, *BaseException) { 255 return floatDivAndModOp(f, "__rdivmod__", v, w, func(v, w float64) (float64, float64, bool) { 256 m, r := floatModFunc(w, v) 257 if !r { 258 return 0, 0, false 259 } 260 return w / v, m, true 261 }) 262 } 263 264 const ( 265 floatReprPrecision = 16 266 floatStrPrecision = 12 267 ) 268 269 func floatRepr(f *Frame, o *Object) (*Object, *BaseException) { 270 return NewStr(floatToString(toFloatUnsafe(o).Value(), floatReprPrecision)).ToObject(), nil 271 } 272 273 func floatRFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 274 return floatDivModOp(f, "__rfloordiv__", v, w, func(v, w float64) (float64, bool) { 275 if v == 0.0 { 276 return 0, false 277 } 278 return math.Floor(w / v), true 279 }) 280 } 281 282 func floatRMod(f *Frame, v, w *Object) (*Object, *BaseException) { 283 return floatDivModOp(f, "__rmod__", v, w, func(v, w float64) (float64, bool) { 284 return floatModFunc(w, v) 285 }) 286 } 287 288 func floatRMul(f *Frame, v, w *Object) (*Object, *BaseException) { 289 return floatArithmeticOp(f, "__rmul__", v, w, func(v, w float64) float64 { return w * v }) 290 } 291 292 func floatRPow(f *Frame, v, w *Object) (*Object, *BaseException) { 293 return floatArithmeticOp(f, "__rpow", v, w, func(v, w float64) float64 { return math.Pow(w, v) }) 294 } 295 296 func floatRSub(f *Frame, v, w *Object) (*Object, *BaseException) { 297 return floatArithmeticOp(f, "__rsub__", v, w, func(v, w float64) float64 { return w - v }) 298 } 299 300 func floatStr(f *Frame, o *Object) (*Object, *BaseException) { 301 return NewStr(floatToString(toFloatUnsafe(o).Value(), floatStrPrecision)).ToObject(), nil 302 } 303 304 func floatSub(f *Frame, v, w *Object) (*Object, *BaseException) { 305 return floatArithmeticOp(f, "__sub__", v, w, func(v, w float64) float64 { return v - w }) 306 } 307 308 func initFloatType(dict map[string]*Object) { 309 dict["__getnewargs__"] = newBuiltinFunction("__getnewargs__", floatGetNewArgs).ToObject() 310 FloatType.slots.Abs = &unaryOpSlot{floatAbs} 311 FloatType.slots.Add = &binaryOpSlot{floatAdd} 312 FloatType.slots.Div = &binaryOpSlot{floatDiv} 313 FloatType.slots.DivMod = &binaryOpSlot{floatDivMod} 314 FloatType.slots.Eq = &binaryOpSlot{floatEq} 315 FloatType.slots.Float = &unaryOpSlot{floatFloat} 316 FloatType.slots.FloorDiv = &binaryOpSlot{floatFloorDiv} 317 FloatType.slots.GE = &binaryOpSlot{floatGE} 318 FloatType.slots.GT = &binaryOpSlot{floatGT} 319 FloatType.slots.Hash = &unaryOpSlot{floatHash} 320 FloatType.slots.Int = &unaryOpSlot{floatInt} 321 FloatType.slots.Long = &unaryOpSlot{floatLong} 322 FloatType.slots.LE = &binaryOpSlot{floatLE} 323 FloatType.slots.LT = &binaryOpSlot{floatLT} 324 FloatType.slots.Mod = &binaryOpSlot{floatMod} 325 FloatType.slots.Mul = &binaryOpSlot{floatMul} 326 FloatType.slots.Native = &nativeSlot{floatNative} 327 FloatType.slots.NE = &binaryOpSlot{floatNE} 328 FloatType.slots.Neg = &unaryOpSlot{floatNeg} 329 FloatType.slots.New = &newSlot{floatNew} 330 FloatType.slots.NonZero = &unaryOpSlot{floatNonZero} 331 FloatType.slots.Pos = &unaryOpSlot{floatPos} 332 FloatType.slots.Pow = &binaryOpSlot{floatPow} 333 FloatType.slots.RAdd = &binaryOpSlot{floatRAdd} 334 FloatType.slots.RDiv = &binaryOpSlot{floatRDiv} 335 FloatType.slots.RDivMod = &binaryOpSlot{floatRDivMod} 336 FloatType.slots.Repr = &unaryOpSlot{floatRepr} 337 FloatType.slots.RFloorDiv = &binaryOpSlot{floatRFloorDiv} 338 FloatType.slots.RMod = &binaryOpSlot{floatRMod} 339 FloatType.slots.RMul = &binaryOpSlot{floatRMul} 340 FloatType.slots.RPow = &binaryOpSlot{floatRPow} 341 FloatType.slots.RSub = &binaryOpSlot{floatRSub} 342 FloatType.slots.Str = &unaryOpSlot{floatStr} 343 FloatType.slots.Sub = &binaryOpSlot{floatSub} 344 } 345 346 func floatArithmeticOp(f *Frame, method string, v, w *Object, fun func(v, w float64) float64) (*Object, *BaseException) { 347 floatW, ok := floatCoerce(w) 348 if !ok { 349 if math.IsInf(floatW, 0) { 350 return nil, f.RaiseType(OverflowErrorType, "long int too large to convert to float") 351 } 352 return NotImplemented, nil 353 } 354 return NewFloat(fun(toFloatUnsafe(v).Value(), floatW)).ToObject(), nil 355 } 356 357 func floatCompare(v *Float, w *Object, ltResult, eqResult, gtResult *Int) *Object { 358 lhs := v.Value() 359 rhs, ok := floatCoerce(w) 360 if !ok { 361 if !math.IsInf(rhs, 0) { 362 return NotImplemented 363 } 364 // When floatCoerce returns (Inf, false) it indicates an 365 // overflow - abs(rhs) is between MaxFloat64 and Inf. 366 // When comparing with infinite floats, rhs might as well be 0. 367 // Otherwise, let the compare proceed normally as |rhs| might 368 // as well be infinite, since it's outside the range of finite 369 // floats. 370 if math.IsInf(lhs, 0) { 371 rhs = 0 372 } 373 } 374 if lhs < rhs { 375 return ltResult.ToObject() 376 } 377 if lhs == rhs { 378 return eqResult.ToObject() 379 } 380 if lhs > rhs { 381 return gtResult.ToObject() 382 } 383 // There must be a NaN involved, which always compares false, even to other NaNs. 384 // This is true both in Go and in Python. 385 return False.ToObject() 386 } 387 388 // floatCoerce will coerce any numeric type to a float. If all is 389 // well, it will return the float64 value, and true (OK). If an overflow 390 // occurs, it will return either (+Inf, false) or (-Inf, false) depending 391 // on whether the source value was too large or too small. Note that if the 392 // source number is an infinite float, the result will be infinite without 393 // overflow, (+-Inf, true). 394 // If the input is not a number, it will return (0, false). 395 func floatCoerce(o *Object) (float64, bool) { 396 switch { 397 case o.isInstance(IntType): 398 return float64(toIntUnsafe(o).Value()), true 399 case o.isInstance(LongType): 400 f, _ := new(big.Float).SetInt(toLongUnsafe(o).Value()).Float64() 401 // If f is infinite, that indicates the big.Int was too large 402 // or too small to be represented as a float64. In that case, 403 // indicate the overflow by returning (f, false). 404 overflow := math.IsInf(f, 0) 405 return f, !overflow 406 case o.isInstance(FloatType): 407 return toFloatUnsafe(o).Value(), true 408 default: 409 return 0, false 410 } 411 } 412 413 func floatConvert(floatSlot *unaryOpSlot, f *Frame, o *Object) (*Float, *BaseException) { 414 result, raised := floatSlot.Fn(f, o) 415 if raised != nil { 416 return nil, raised 417 } 418 if !result.isInstance(FloatType) { 419 exc := fmt.Sprintf("__float__ returned non-float (type %s)", result.typ.Name()) 420 return nil, f.RaiseType(TypeErrorType, exc) 421 } 422 return toFloatUnsafe(result), nil 423 } 424 425 func floatDivModOp(f *Frame, method string, v, w *Object, fun func(v, w float64) (float64, bool)) (*Object, *BaseException) { 426 floatW, ok := floatCoerce(w) 427 if !ok { 428 if math.IsInf(floatW, 0) { 429 return nil, f.RaiseType(OverflowErrorType, "long int too large to convert to float") 430 } 431 return NotImplemented, nil 432 } 433 x, ok := fun(toFloatUnsafe(v).Value(), floatW) 434 if !ok { 435 return nil, f.RaiseType(ZeroDivisionErrorType, "float division or modulo by zero") 436 } 437 return NewFloat(x).ToObject(), nil 438 } 439 440 func floatDivAndModOp(f *Frame, method string, v, w *Object, fun func(v, w float64) (float64, float64, bool)) (*Object, *BaseException) { 441 floatW, ok := floatCoerce(w) 442 if !ok { 443 if math.IsInf(floatW, 0) { 444 return nil, f.RaiseType(OverflowErrorType, "long int too large to convert to float") 445 } 446 return NotImplemented, nil 447 } 448 q, m, ok := fun(toFloatUnsafe(v).Value(), floatW) 449 if !ok { 450 return nil, f.RaiseType(ZeroDivisionErrorType, "float division or modulo by zero") 451 } 452 return NewTuple2(NewFloat(q).ToObject(), NewFloat(m).ToObject()).ToObject(), nil 453 } 454 455 func hashFloat(v float64) int { 456 if math.IsNaN(v) { 457 return 0 458 } 459 460 if math.IsInf(v, 0) { 461 if math.IsInf(v, 1) { 462 return 314159 463 } 464 if math.IsInf(v, -1) { 465 return -271828 466 } 467 return 0 468 } 469 470 _, fracPart := math.Modf(v) 471 if fracPart == 0.0 { 472 i := big.Int{} 473 big.NewFloat(v).Int(&i) 474 if numInIntRange(&i) { 475 return int(i.Int64()) 476 } 477 // TODO: hashBigInt() is not yet matched that of cpython or pypy. 478 return hashBigInt(&i) 479 } 480 481 v, expo := math.Frexp(v) 482 v *= 2147483648.0 483 hiPart := int(v) 484 v = (v - float64(hiPart)) * 2147483648.0 485 x := int(hiPart + int(v) + (expo << 15)) 486 return x 487 } 488 489 func floatModFunc(v, w float64) (float64, bool) { 490 if w == 0.0 { 491 return 0, false 492 } 493 x := math.Mod(v, w) 494 if x != 0 && math.Signbit(x) != math.Signbit(w) { 495 // In Python the result of the modulo operator is 496 // always the same sign as the divisor, whereas in Go, 497 // the result is always the same sign as the dividend. 498 // Therefore we need to do an adjustment when the sign 499 // of the modulo result differs from that of the 500 // divisor. 501 x += w 502 } 503 return x, true 504 } 505 506 func floatToString(f float64, p int) string { 507 s := unsignPositiveInf(strings.ToLower(strconv.FormatFloat(f, 'g', p, 64))) 508 fun := func(r rune) bool { 509 return !unicode.IsDigit(r) 510 } 511 if i := strings.IndexFunc(s, fun); i == -1 { 512 s += ".0" 513 } 514 return s 515 } 516 517 func unsignPositiveInf(s string) string { 518 if s == "+inf" { 519 return "inf" 520 } 521 return s 522 }