about summary refs log tree commit diff stats
path: root/412print-float-decimal.mu
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-11-29 09:58:41 -0800
committerKartik Agaram <vc@akkartik.com>2020-11-29 12:17:23 -0800
commitb6369d4652b2f8552258f07433af1574ececca71 (patch)
treeae2a415e845ced926486fd21017ce179c09bfb07 /412print-float-decimal.mu
parent6b1cde4761711934211465c3e4ade12d344662ff (diff)
downloadmu-b6369d4652b2f8552258f07433af1574ececca71.tar.gz
7298 - slightly smarter float width
Diffstat (limited to '412print-float-decimal.mu')
-rw-r--r--412print-float-decimal.mu102
1 files changed, 96 insertions, 6 deletions
diff --git a/412print-float-decimal.mu b/412print-float-decimal.mu
index ef966390..06facfa9 100644
--- a/412print-float-decimal.mu
+++ b/412print-float-decimal.mu
@@ -140,9 +140,9 @@ fn test-print-float-decimal-approximate-not-a-number {
 }
 
 # 'precision' controls the maximum width past which we resort to scientific notation
-fn print-float-decimal-approximate screen: (addr screen), n: float, precision: int {
+fn print-float-decimal-approximate screen: (addr screen), in: float, precision: int {
   # - special names
-  var bits/eax: int <- reinterpret n
+  var bits/eax: int <- reinterpret in
   compare bits, 0
   {
     break-if-!=
@@ -490,10 +490,100 @@ fn print-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr
   print-int32-decimal screen, dp
 }
 
-# pretty hacky for now
-fn float-size n: float, precision: int -> _/eax: int {
-  var result/eax: int <- copy precision
-  result <- add 4  # 1 for '.', 3 for exponent
+# follows the structure of print-float-decimal-approximate
+# 'precision' controls the maximum width past which we resort to scientific notation
+fn float-size in: float, precision: int -> _/eax: int {
+  # - special names
+  var bits/eax: int <- reinterpret in
+  compare bits, 0
+  {
+    break-if-!=
+    return 1  # "0"
+  }
+  compare bits, 0x80000000
+  {
+    break-if-!=
+    return 2  # "-0"
+  }
+  compare bits, 0x7f800000
+  {
+    break-if-!=
+    return 3  # "Inf"
+  }
+  compare bits, 0xff800000
+  {
+    break-if-!=
+    return 4  # "-Inf"
+  }
+  var exponent/ecx: int <- copy bits
+  exponent <- shift-right 0x17  # 23 bits of mantissa
+  exponent <- and 0xff
+  exponent <- subtract 0x7f
+  compare exponent, 0x80
+  {
+    break-if-!=
+    return 3  # "NaN"
+  }
+  # - regular numbers
+  # v = 1.mantissa (in base 2) << 0x17
+  var v/ebx: int <- copy bits
+  v <- and 0x7fffff
+  v <- or 0x00800000  # insert implicit 1
+  # e = exponent - 0x17
+  var e/ecx: int <- copy exponent
+  e <- subtract 0x17  # move decimal place from before mantissa to after
+
+  # initialize buffer with decimal representation of v
+  var buf-storage: (array byte 0x7f)
+  var buf/edi: (addr array byte) <- address buf-storage
+  var n/eax: int <- decimal-digits v, buf
+  reverse-digits buf, n
+
+  # loop if e > 0
+  {
+    compare e, 0
+    break-if-<=
+    n <- double-array-of-decimal-digits buf, n
+    e <- decrement
+    loop
+  }
+
+  var dp/edx: int <- copy n
+
+  # loop if e < 0
+  {
+    compare e, 0
+    break-if->=
+    n, dp <- halve-array-of-decimal-digits buf, n, dp
+    e <- increment
+    loop
+  }
+
+  compare dp, 0
+  {
+    break-if->=
+    return 8  # hacky for scientific notation
+  }
+  {
+    var dp2/eax: int <- copy dp
+    compare dp2, precision
+    break-if-<
+    return 8  # hacky for scientific notation
+  }
+
+  var result/eax: int <- copy n
+  {
+    compare result, dp
+    break-if->=
+    result <- copy dp
+  }
+  var sign/edx: int <- reinterpret in
+  sign <- shift-right 0x1f
+  {
+    compare sign, 1
+    break-if-!=
+    result <- increment  # for "-"
+  }
   return result
 }