| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package math |
| #include "runtime.h" |
| |
| static uint64 uvnan = 0x7FF0000000000001ULL; |
| static uint64 uvinf = 0x7FF0000000000000ULL; |
| static uint64 uvneginf = 0xFFF0000000000000ULL; |
| |
| uint32 |
| float32tobits(float32 f) |
| { |
| // The obvious cast-and-pointer code is technically |
| // not valid, and gcc miscompiles it. Use a union instead. |
| union { |
| float32 f; |
| uint32 i; |
| } u; |
| u.f = f; |
| return u.i; |
| } |
| |
| uint64 |
| float64tobits(float64 f) |
| { |
| // The obvious cast-and-pointer code is technically |
| // not valid, and gcc miscompiles it. Use a union instead. |
| union { |
| float64 f; |
| uint64 i; |
| } u; |
| u.f = f; |
| return u.i; |
| } |
| |
| float64 |
| float64frombits(uint64 i) |
| { |
| // The obvious cast-and-pointer code is technically |
| // not valid, and gcc miscompiles it. Use a union instead. |
| union { |
| float64 f; |
| uint64 i; |
| } u; |
| u.i = i; |
| return u.f; |
| } |
| |
| float32 |
| float32frombits(uint32 i) |
| { |
| // The obvious cast-and-pointer code is technically |
| // not valid, and gcc miscompiles it. Use a union instead. |
| union { |
| float32 f; |
| uint32 i; |
| } u; |
| u.i = i; |
| return u.f; |
| } |
| |
| bool |
| isInf(float64 f, int32 sign) |
| { |
| uint64 x; |
| |
| x = float64tobits(f); |
| if(sign == 0) |
| return x == uvinf || x == uvneginf; |
| if(sign > 0) |
| return x == uvinf; |
| return x == uvneginf; |
| } |
| |
| float64 |
| NaN(void) |
| { |
| return float64frombits(uvnan); |
| } |
| |
| bool |
| isNaN(float64 f) |
| { |
| uint64 x; |
| |
| x = float64tobits(f); |
| return ((uint32)(x>>52) & 0x7FF) == 0x7FF && !isInf(f, 0); |
| } |
| |
| float64 |
| Inf(int32 sign) |
| { |
| if(sign >= 0) |
| return float64frombits(uvinf); |
| else |
| return float64frombits(uvneginf); |
| } |
| |
| enum |
| { |
| MASK = 0x7ffL, |
| SHIFT = 64-11-1, |
| BIAS = 1022L, |
| }; |
| |
| float64 |
| frexp(float64 d, int32 *ep) |
| { |
| uint64 x; |
| |
| if(d == 0) { |
| *ep = 0; |
| return 0; |
| } |
| x = float64tobits(d); |
| *ep = (int32)((x >> SHIFT) & MASK) - BIAS; |
| x &= ~((uint64)MASK << SHIFT); |
| x |= (uint64)BIAS << SHIFT; |
| return float64frombits(x); |
| } |
| |
| float64 |
| ldexp(float64 d, int32 e) |
| { |
| uint64 x; |
| |
| if(d == 0) |
| return 0; |
| x = float64tobits(d); |
| e += (int32)(x >> SHIFT) & MASK; |
| if(e <= 0) |
| return 0; /* underflow */ |
| if(e >= MASK){ /* overflow */ |
| if(d < 0) |
| return Inf(-1); |
| return Inf(1); |
| } |
| x &= ~((uint64)MASK << SHIFT); |
| x |= (uint64)e << SHIFT; |
| return float64frombits(x); |
| } |
| |
| float64 |
| modf(float64 d, float64 *ip) |
| { |
| float64 dd; |
| uint64 x; |
| int32 e; |
| |
| if(d < 1) { |
| if(d < 0) { |
| d = modf(-d, ip); |
| *ip = -*ip; |
| return -d; |
| } |
| *ip = 0; |
| return d; |
| } |
| |
| x = float64tobits(d); |
| e = (int32)((x >> SHIFT) & MASK) - BIAS; |
| |
| /* |
| * Keep the top 11+e bits; clear the rest. |
| */ |
| if(e <= 64-11) |
| x &= ~(((uint64)1 << (64LL-11LL-e))-1); |
| dd = float64frombits(x); |
| *ip = dd; |
| return d - dd; |
| } |
| |
| func Frexp(f float64) (frac float64, exp int32) { |
| frac = frexp(f, &exp); |
| } |
| |
| func Ldexp(frac float64, exp int32) (f float64) { |
| f = ldexp(frac, exp); |
| } |
| |
| func Modf(f float64) (integer float64, frac float64) { |
| frac = modf(f, &integer); |
| } |
| |
| func IsInf(f float64, sign int32) (is bool) { |
| is = isInf(f, sign); |
| } |
| |
| func IsNaN(f float64) (is bool) { |
| is = isNaN(f); |
| } |
| |
| func Inf(sign int32) (f float64) { |
| f = Inf(sign); |
| } |
| |
| func NaN() (f float64) { |
| f = NaN(); |
| } |
| |
| func Float32bits(f float32) (b uint32) { |
| b = float32tobits(f); |
| } |
| |
| func Float64bits(f float64) (b uint64) { |
| b = float64tobits(f); |
| } |
| |
| func Float32frombits(b uint32) (f float32) { |
| f = float32frombits(b); |
| } |
| |
| func Float64frombits(b uint64) (f float64) { |
| f = float64frombits(b); |
| } |
| |