// 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. #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; }