diff options
Diffstat (limited to 'src/pkg/runtime/float.cgo')
| -rw-r--r-- | src/pkg/runtime/float.cgo | 218 | 
1 files changed, 218 insertions, 0 deletions
| diff --git a/src/pkg/runtime/float.cgo b/src/pkg/runtime/float.cgo new file mode 100644 index 000000000..38114aa85 --- /dev/null +++ b/src/pkg/runtime/float.cgo @@ -0,0 +1,218 @@ +// 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); +} + | 
