summaryrefslogtreecommitdiff
path: root/lib/math/trunc-impl.myr
blob: cf8fb1de6824f5b3ae53a6aee9580efe8294671f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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)
}