shithub: mc

Download patch

ref: 7f941fe7689b6085a18d67389eb7cd7f8b3fae48
parent: 62227e61e476af5fb0b9d601117b371fefb7e1cc
author: Ori Bernstein <[email protected]>
date: Tue Sep 16 21:45:16 EDT 2014

Add missing file.

--- /dev/null
+++ b/libstd/floatfmt.myr
@@ -1,0 +1,195 @@
+use "bigint.use"
+use "types.use"
+use "floatbits.use"
+use "extremum.use"
+use "utf.use"
+use "alloc.use"
+use "slpush.use"
+use "die.use"
+
+pkg std =
+	const float64bfmt	: (buf : byte[:], val : float64, mode : int, precision : int -> size)
+	const float32bfmt	: (buf : byte[:], val : float32, mode : int, precision : int -> size)
+;;
+
+const Dblbias = 1023
+const Fltbias = 127
+
+const float64bfmt = {buf, val, mode, precision
+	var isneg, exp, mant
+
+	(isneg, mant, exp) = float64explode(val)
+	-> dragon4(buf, isneg, mant, (exp - 52) castto(int64), Dblbias, mode, precision)
+}
+
+const float32bfmt = {buf, val, mode, precision
+	var isneg, exp, mant
+
+	(isneg, mant, exp) = float32explode(val)
+	-> dragon4(buf, isneg, mant castto(int64), (exp - 52) castto(int64), Fltbias, mode, precision)
+}
+
+/*
+buf: output buffer
+e: exponent
+p: precision
+f: mantissa
+
+floating value: x = f^(e - p)
+*/
+const dragon4 = {buf, isneg, f, e, p, mode, cutoff
+	var r, s, t, u, v
+	var udig
+	var mm, mp	/* margins above and below */
+	var roundup
+	var low, high
+	var k : int, n : size
+
+	/* if we have zero for the mantissa, we can return early */
+	n = 0
+	if isneg
+		n += encode(buf, '-')
+	;;
+	if f == 0
+		n += encode(buf[n:], '0')
+		n += encode(buf[n:], '.')
+		n += encode(buf[n:], '0')
+		-> n
+	;;
+
+	/* initialize */
+	roundup = false
+	r = mkbigint(f)
+	r = bigshli(r, max(e - p, 0))
+	s = bigshli(mkbigint(1), max(0, -(e - p)))
+	mm = bigshli(mkbigint(1), max((e - p), 0))
+	mp = bigdup(mm)
+
+	/* fixup: unequal gaps */
+	t = mkbigint(1)
+	bigshli(t, p - 1)
+	if bigeqi(t, f)
+		bigshli(mp, 1)
+		bigshli(r, 1)
+		bigshli(s, 1)
+	;;
+	bigfree(t)
+
+	k = 0
+	while true
+		/* r < ceil(s/b) */
+		t = bigdup(s)
+		bigaddi(t, 9)
+		bigdivi(t, 10)
+		match bigcmp(r, t)
+		| `Before:
+			k--
+			bigmuli(r, 10)
+			bigmuli(mm, 10)
+			bigmuli(mp, 10)
+		| _:
+			bigfree(t)
+			break
+		;;
+		bigfree(t)
+	;;
+
+	t = bigdup(r)
+	bigshli(t, 1)
+	bigadd(t, mp)
+	while true
+		u = bigdup(s)
+		bigshli(u, 1)
+		match bigcmp(t, u)
+		| `Before:
+			bigfree(u)
+			break
+		| _:
+			k++
+			bigmuli(s, 10)
+			bigfree(u)
+		;;
+	;;
+	cutoff = k - buf.len - 1
+	bigfree(t)
+
+	if k <= 0
+		n += encode(buf[n:], '0')
+		n += encode(buf[n:], '.')
+	;;
+	while true
+		k--
+		bigmuli(r, 10)
+		u = bigdup(r);
+		bigdiv(u, s)
+
+		bigmod(r, s)
+		bigmuli(mm, 10)
+		bigmuli(mp, 10)
+
+		low = false
+		t = bigdup(r)
+		bigshli(t, 1)
+		match bigcmp(t, mm)
+		| `Before:	low = true
+		;;
+		bigfree(t)
+		
+		v = bigdup(r)
+		bigshli(v, 1)
+		t = bigdup(s)
+		bigshli(t, 1)
+		bigsub(t, mp)
+		match bigcmp(v, t)
+		| `After: high = true
+		| `Equal: high = roundup
+		| `Before: high = false
+		;;
+		bigfree(v)
+		bigfree(t)
+		if low || high || k == cutoff
+			break
+		;;
+		n += format(buf[n:], lowdig(u), k)
+		bigfree(u)
+	;;
+
+	/* format the last digit */
+	udig = lowdig(u)
+	if low && !high
+		n += format(buf[n:], udig, k)
+	elif high && !low
+		n += format(buf[n:], udig + 1, k)
+	else
+		bigmuli(r, 2)
+		match bigcmp(r, s)
+		| `Before:	n += format(buf[n:], udig, k)
+		| `Equal:	n += format(buf[n:], udig, k)
+		| `After:	n += format(buf[n:], udig + 1, k)
+		;;
+	;;
+	-> n
+}
+
+const lowdig = {u
+	if u.dig.len > 0
+		-> u.dig[0]
+	;;
+	-> 0
+}
+
+const format = {buf, d, k
+	const dig = "0123456789"
+	var n, i
+
+	n = 0
+	if k == 0
+		n += encode(buf[n:], '.')
+	elif k < 0
+		for i = 0; i < -k; i++
+			n += encode(buf[n:], '0')
+		;;
+	;;
+	buf[n++] = dig[d]
+	-> n
+}