shithub: mc

ref: 86aa50f243677df226f5ee02d6b15f85c634a6f1
dir: /lib/math/trunc-impl.myr/

View raw version
use std

pkg math =
	pkglocal const trunc32 : (x : flt32 -> flt32)
	pkglocal const floor32 : (x : flt32 -> flt32)
	pkglocal const ceil32  : (x : flt32 -> flt32)
	pkglocal const trunc64 : (x : flt64 -> flt64)
	pkglocal const floor64 : (x : flt64 -> flt64)
	pkglocal const ceil64  : (x : flt64 -> flt64)
;;

const Flt32NegMask : uint32 = (1 << 31)
const Flt32SigMask : uint32 = (1 << 23) - 1

const Flt64NegMask : uint64 = (1 << 63)
const Flt64SigMask : uint64 = (1 << 52) - 1

pkglocal const floor32 = {x : flt32
	var n, e, s
	(n, e, s) = std.flt32explode(x)

	/* Many special cases */
	if e >= 23 || x == -0.0
		-> x
	elif e < 0
		if n
			-> -1.0
		else
			-> 0.0
		;;
	;;

	if n
		var fractional_mask = Flt32SigMask >> (e : uint32)
		if s & fractional_mask == 0
			-> x
		else
			/* Turns out the packing of exp and sig is useful */
			var u : uint32 = std.flt32bits(x) & ~fractional_mask
			u += ((1 << 23) >> (e : uint32))
			-> std.flt32frombits(u)
		;;
	;;

	var m : uint32 = (Flt32SigMask >> (e : uint32))
	-> std.flt32assem(n, e, s & ~m)
}

pkglocal const trunc32 = {x : flt32
	if std.flt32bits(x) & Flt32NegMask != 0
		-> -floor32(-x)
	else
		-> floor32(x)
	;;
}

pkglocal const ceil32 = {x : flt32
	-> -floor32(-x)
}

pkglocal const floor64 = {x : flt64
	var n, e, s
	(n, e, s) = std.flt64explode(x)

	/* Many special cases */
	if e >= 52 || x == -0.0
		-> x
	elif e < 0
		if n
			-> -1.0
		else
			-> 0.0
		;;
	;;

	if n
		var fractional_mask = Flt64SigMask >> (e : uint64)
		if s & fractional_mask == 0
			-> x
		else
			/* Turns out the packing of exp and sig is useful */
			var u : uint64 = std.flt64bits(x) & ~fractional_mask
			u += ((1 << 52) >> (e : uint64))
			-> std.flt64frombits(u)
		;;
	;;

	var m : uint64 = (Flt64SigMask >> (e : uint64))
	-> std.flt64assem(n, e, s & ~m)
}

pkglocal const trunc64 = {x : flt64
	if std.flt64bits(x) & Flt64NegMask != 0
		-> -floor64(-x)
	else
		-> floor64(x)
	;;
}

pkglocal const ceil64 = {x : flt64
	-> -floor64(-x)
}