shithub: mc

ref: eeb8989f663c7c2f7ed7e5f92e38bced908cf805
dir: /lib/math/trunc-impl.myr/

View raw version
use std

pkg math =
	pkglocal const trunc32 : (f : flt32 -> flt32)
	pkglocal const floor32 : (f : flt32 -> flt32)
	pkglocal const ceil32  : (f : flt32 -> flt32)
	pkglocal const trunc64 : (f : flt64 -> flt64)
	pkglocal const floor64 : (f : flt64 -> flt64)
	pkglocal const ceil64  : (f : 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 = {f : flt32
	var n, e, s
	(n, e, s) = std.flt32explode(f)

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

	if n
		var fractional_mask = Flt32SigMask >> (e : uint32)
		if s & fractional_mask == 0
			-> f
		else
			/* Turns out the packing of exp and sig is useful */
			var u : uint32 = std.flt32bits(f) & ~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 = {f : flt32
	if std.flt32bits(f) & Flt32NegMask != 0
		-> -floor32(-f)
	else
		-> floor32(f)
	;;
}

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

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

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

	if n
		var fractional_mask = Flt64SigMask >> (e : uint64)
		if s & fractional_mask == 0
			-> f
		else
			/* Turns out the packing of exp and sig is useful */
			var u : uint64 = std.flt64bits(f) & ~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 = {f : flt64
	if std.flt64bits(f) & Flt64NegMask != 0
		-> -floor64(-f)
	else
		-> floor64(f)
	;;
}

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