diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-02-27 06:55:41 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-02-27 06:55:41 -0800 |
commit | a9e0cb7cc9da462c6e7886edfb554d7266e84c18 (patch) | |
tree | 80cd66ef67cf32b24603e2081165b1a2f89ea818 | |
parent | c782d38f0b4d263d243415495b8e9d9c84f119db (diff) | |
download | mu-a9e0cb7cc9da462c6e7886edfb554d7266e84c18.tar.gz |
7817
Detour: writing float to stream. In the process I found a bug at the SubX layer X-(
-rw-r--r-- | 115write-byte.subx | 2 | ||||
-rw-r--r-- | 405screen.mu | 16 | ||||
-rw-r--r-- | 412print-float-decimal.mu | 208 | ||||
-rw-r--r-- | baremetal/115write-byte.subx | 2 | ||||
-rw-r--r-- | baremetal/412render-float-decimal.mu | 229 |
5 files changed, 225 insertions, 232 deletions
diff --git a/115write-byte.subx b/115write-byte.subx index 0a4e3c7d..d38db24c 100644 --- a/115write-byte.subx +++ b/115write-byte.subx @@ -210,6 +210,7 @@ append-byte: # f: (addr stream byte), n: int 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers + 50/push-eax 51/push-ecx 57/push-edi # edi = f @@ -231,6 +232,7 @@ $append-byte:end: # . restore registers 5f/pop-to-edi 59/pop-to-ecx + 58/pop-to-eax # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp diff --git a/405screen.mu b/405screen.mu index d009924e..c850df2a 100644 --- a/405screen.mu +++ b/405screen.mu @@ -174,15 +174,19 @@ fn print-string screen: (addr screen), s: (addr array byte) { return } # fake screen - var s2: (stream byte 0x100) - var s2-addr/esi: (addr stream byte) <- address s2 - write s2-addr, s - var screen-addr/edi: (addr screen) <- copy screen + var stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, s + print-stream screen, stream +} + +fn print-stream _screen: (addr screen), s: (addr stream byte) { + var screen/edi: (addr screen) <- copy _screen { - var done?/eax: boolean <- stream-empty? s2-addr + var done?/eax: boolean <- stream-empty? s compare done?, 0 break-if-!= - var g/eax: grapheme <- read-grapheme s2-addr + var g/eax: grapheme <- read-grapheme s print-grapheme screen, g loop } diff --git a/412print-float-decimal.mu b/412print-float-decimal.mu index 67470f1f..a9c7fd0e 100644 --- a/412print-float-decimal.mu +++ b/412print-float-decimal.mu @@ -22,165 +22,165 @@ # This approach turns out to be fast enough for most purposes. # Optimizations, however, get wildly more complex. -fn test-print-float-decimal-approximate-normal { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-normal { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage # 0.5 var half/xmm0: float <- rational 1, 2 - print-float-decimal-approximate screen, half, 3 - check-screen-row screen, 1, "0.5 ", "F - test-print-float-decimal-approximate-normal 0.5" + write-float-decimal-approximate s, half, 3 + check-stream-equal s, "0.5", "F - test-write-float-decimal-approximate-normal 0.5" # 0.25 - clear-screen screen + clear-stream s var quarter/xmm0: float <- rational 1, 4 - print-float-decimal-approximate screen, quarter, 3 - check-screen-row screen, 1, "0.25 ", "F - test-print-float-decimal-approximate-normal 0.25" + write-float-decimal-approximate s, quarter, 3 + check-stream-equal s, "0.25", "F - test-write-float-decimal-approximate-normal 0.25" # 0.75 - clear-screen screen + clear-stream s var three-quarters/xmm0: float <- rational 3, 4 - print-float-decimal-approximate screen, three-quarters, 3 - check-screen-row screen, 1, "0.75 ", "F - test-print-float-decimal-approximate-normal 0.75" + write-float-decimal-approximate s, three-quarters, 3 + check-stream-equal s, "0.75", "F - test-write-float-decimal-approximate-normal 0.75" # 0.125 - clear-screen screen + clear-stream s var eighth/xmm0: float <- rational 1, 8 - print-float-decimal-approximate screen, eighth, 3 - check-screen-row screen, 1, "0.125 ", "F - test-print-float-decimal-approximate-normal 0.125" + write-float-decimal-approximate s, eighth, 3 + check-stream-equal s, "0.125", "F - test-write-float-decimal-approximate-normal 0.125" # 0.0625; start using scientific notation - clear-screen screen + clear-stream s var sixteenth/xmm0: float <- rational 1, 0x10 - print-float-decimal-approximate screen, sixteenth, 3 - check-screen-row screen, 1, "6.25e-2 ", "F - test-print-float-decimal-approximate-normal 0.0625" + write-float-decimal-approximate s, sixteenth, 3 + check-stream-equal s, "6.25e-2", "F - test-write-float-decimal-approximate-normal 0.0625" # sqrt(2); truncate floats with lots of digits after the decimal but not too many before - clear-screen screen + clear-stream s var two-f/xmm0: float <- rational 2, 1 var sqrt-2/xmm0: float <- square-root two-f - print-float-decimal-approximate screen, sqrt-2, 3 - check-screen-row screen, 1, "1.414 ", "F - test-print-float-decimal-approximate-normal √2" + write-float-decimal-approximate s, sqrt-2, 3 + check-stream-equal s, "1.414", "F - test-write-float-decimal-approximate-normal √2" } # print whole integers without decimals -fn test-print-float-decimal-approximate-integer { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-integer { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage # 1 var one-f/xmm0: float <- rational 1, 1 - print-float-decimal-approximate screen, one-f, 3 - check-screen-row screen, 1, "1 ", "F - test-print-float-decimal-approximate-integer 1" + write-float-decimal-approximate s, one-f, 3 + check-stream-equal s, "1", "F - test-write-float-decimal-approximate-integer 1" # 2 - clear-screen screen + clear-stream s var two-f/xmm0: float <- rational 2, 1 - print-float-decimal-approximate screen, two-f, 3 - check-screen-row screen, 1, "2 ", "F - test-print-float-decimal-approximate-integer 2" + write-float-decimal-approximate s, two-f, 3 + check-stream-equal s, "2", "F - test-write-float-decimal-approximate-integer 2" # 10 - clear-screen screen + clear-stream s var ten-f/xmm0: float <- rational 0xa, 1 - print-float-decimal-approximate screen, ten-f, 3 - check-screen-row screen, 1, "10 ", "F - test-print-float-decimal-approximate-integer 10" + write-float-decimal-approximate s, ten-f, 3 + check-stream-equal s, "10", "F - test-write-float-decimal-approximate-integer 10" # -10 - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational -0xa, 1 - print-float-decimal-approximate screen, minus-ten-f, 3 - check-screen-row screen, 1, "-10 ", "F - test-print-float-decimal-approximate-integer -10" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "-10", "F - test-write-float-decimal-approximate-integer -10" # 999 - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational 0x3e7, 1 - print-float-decimal-approximate screen, minus-ten-f, 3 - check-screen-row screen, 1, "999 ", "F - test-print-float-decimal-approximate-integer 1000" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "999", "F - test-write-float-decimal-approximate-integer 1000" # 1000 - start using scientific notation - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational 0x3e8, 1 - print-float-decimal-approximate screen, minus-ten-f, 3 - check-screen-row screen, 1, "1.00e3 ", "F - test-print-float-decimal-approximate-integer 1000" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "1.00e3", "F - test-write-float-decimal-approximate-integer 1000" # 100,000 - clear-screen screen + clear-stream s var hundred-thousand/eax: int <- copy 0x186a0 var hundred-thousand-f/xmm0: float <- convert hundred-thousand - print-float-decimal-approximate screen, hundred-thousand-f, 3 - check-screen-row screen, 1, "1.00e5 ", "F - test-print-float-decimal-approximate-integer 100,000" + write-float-decimal-approximate s, hundred-thousand-f, 3 + check-stream-equal s, "1.00e5", "F - test-write-float-decimal-approximate-integer 100,000" } -fn test-print-float-decimal-approximate-zero { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-zero { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var zero: float - print-float-decimal-approximate screen, zero, 3 - check-screen-row screen, 1, "0 ", "F - test-print-float-decimal-approximate-zero" + write-float-decimal-approximate s, zero, 3 + check-stream-equal s, "0", "F - test-write-float-decimal-approximate-zero" } -fn test-print-float-decimal-approximate-negative-zero { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-negative-zero { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0x80000000 var negative-zero/xmm0: float <- reinterpret n - print-float-decimal-approximate screen, negative-zero, 3 - check-screen-row screen, 1, "-0 ", "F - test-print-float-decimal-approximate-negative-zero" + write-float-decimal-approximate s, negative-zero, 3 + check-stream-equal s, "-0", "F - test-write-float-decimal-approximate-negative-zero" } -fn test-print-float-decimal-approximate-infinity { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-infinity { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int # 0|11111111|00000000000000000000000 # 0111|1111|1000|0000|0000|0000|0000|0000 copy-to n, 0x7f800000 var infinity/xmm0: float <- reinterpret n - print-float-decimal-approximate screen, infinity, 3 - check-screen-row screen, 1, "Inf ", "F - test-print-float-decimal-approximate-infinity" + write-float-decimal-approximate s, infinity, 3 + check-stream-equal s, "Inf", "F - test-write-float-decimal-approximate-infinity" } -fn test-print-float-decimal-approximate-negative-infinity { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-negative-infinity { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0xff800000 var negative-infinity/xmm0: float <- reinterpret n - print-float-decimal-approximate screen, negative-infinity, 3 - check-screen-row screen, 1, "-Inf ", "F - test-print-float-decimal-approximate-negative-infinity" + write-float-decimal-approximate s, negative-infinity, 3 + check-stream-equal s, "-Inf", "F - test-write-float-decimal-approximate-negative-infinity" } -fn test-print-float-decimal-approximate-not-a-number { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 5, 0x20 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-not-a-number { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0xffffffff # exponent must be all 1's, and mantissa must be non-zero var nan/xmm0: float <- reinterpret n - print-float-decimal-approximate screen, nan, 3 - check-screen-row screen, 1, "NaN ", "F - test-print-float-decimal-approximate-not-a-number" + write-float-decimal-approximate s, nan, 3 + check-stream-equal s, "NaN", "F - test-write-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), in: float, precision: int { + var s-storage: (stream byte 0x10) + var s/esi: (addr stream byte) <- address s-storage + write-float-decimal-approximate s, in, precision + print-stream screen, s +} + +# 'precision' controls the maximum width past which we resort to scientific notation +fn write-float-decimal-approximate out: (addr stream byte), in: float, precision: int { # - special names var bits/eax: int <- reinterpret in compare bits, 0 { break-if-!= - print-string screen, "0" + write out, "0" return } compare bits, 0x80000000 { break-if-!= - print-string screen, "-0" + write out, "-0" return } compare bits, 0x7f800000 { break-if-!= - print-string screen, "Inf" + write out, "Inf" return } compare bits, 0xff800000 { break-if-!= - print-string screen, "-Inf" + write out, "-Inf" return } var exponent/ecx: int <- copy bits @@ -190,7 +190,7 @@ fn print-float-decimal-approximate screen: (addr screen), in: float, precision: compare exponent, 0x80 { break-if-!= - print-string screen, "NaN" + write out, "NaN" return } # - regular numbers @@ -199,7 +199,7 @@ fn print-float-decimal-approximate screen: (addr screen), in: float, precision: { compare sign, 1 break-if-!= - print-string screen, "-" + append-byte out, 0x2d/minus } # v = 1.mantissa (in base 2) << 0x17 @@ -239,7 +239,7 @@ fn print-float-decimal-approximate screen: (addr screen), in: float, precision: loop } - print-float-buffer screen, buf, n, dp, precision + _write-float-array-of-decimal-digits out, buf, n, dp, precision } # store the decimal digits of 'n' into 'buf', units first @@ -429,27 +429,25 @@ fn halve-array-of-decimal-digits _buf: (addr array byte), _n: int, _dp: int -> _ return n, dp } -fn print-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { +fn _write-float-array-of-decimal-digits out: (addr stream byte), _buf: (addr array byte), n: int, dp: int, precision: int { var buf/edi: (addr array byte) <- copy _buf -#? print-int32-hex 0, dp -#? print-string 0, "\n" { compare dp, 0 break-if->= - print-float-buffer-in-scientific-notation screen, buf, n, dp, precision + _write-float-array-of-decimal-digits-in-scientific-notation out, buf, n, dp, precision return } { var dp2/eax: int <- copy dp compare dp2, precision break-if-<= - print-float-buffer-in-scientific-notation screen, buf, n, dp, precision + _write-float-array-of-decimal-digits-in-scientific-notation out, buf, n, dp, precision return } { compare dp, 0 break-if-!= - print-string screen, "0" + append-byte out, 0x30/0 } var i/eax: int <- copy 0 # bounds = min(n, dp+3) @@ -467,19 +465,20 @@ fn print-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp compare i, dp { break-if-!= - print-string screen, "." + append-byte out, 0x2e/decimal-point } var curr-a/ecx: (addr byte) <- index buf, i var curr/ecx: byte <- copy-byte *curr-a - curr <- add 0x30/0 - var curr-grapheme/ecx: grapheme <- copy curr - print-grapheme screen, curr-grapheme + var curr-int/ecx: int <- copy curr + curr-int <- add 0x30/0 + append-byte out, curr-int + # i <- increment loop } } -fn print-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { +fn _write-float-array-of-decimal-digits-in-scientific-notation out: (addr stream byte), _buf: (addr array byte), n: int, dp: int, precision: int { var buf/edi: (addr array byte) <- copy _buf var i/eax: int <- copy 0 { @@ -490,23 +489,23 @@ fn print-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr compare i, 1 { break-if-!= - print-string screen, "." + append-byte out, 0x2e/decimal-point } var curr-a/ecx: (addr byte) <- index buf, i var curr/ecx: byte <- copy-byte *curr-a - curr <- add 0x30/0 - var curr-grapheme/ecx: grapheme <- copy curr - print-grapheme screen, curr-grapheme + var curr-int/ecx: int <- copy curr + curr-int <- add 0x30/0 + append-byte out, curr-int # i <- increment loop } - print-string screen, "e" + append-byte out, 0x65/e decrement dp - print-int32-decimal screen, dp + write-int32-decimal out, dp } -# follows the structure of print-float-decimal-approximate +# follows the structure of write-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 @@ -641,10 +640,3 @@ fn test-check-buffer-contains { check-buffer-contains a, "a", "F - test-check-buffer-contains" check-buffer-contains "a", "a", "F - test-check-buffer-contains/null" # no null check when arrays have same length } - -#? fn main -> _/ebx: int { -#? run-tests -#? #? test-print-float-decimal-approximate-integer -#? #? test-print-float-decimal-approximate-normal -#? return 0 -#? } diff --git a/baremetal/115write-byte.subx b/baremetal/115write-byte.subx index 0eeef216..6935d65b 100644 --- a/baremetal/115write-byte.subx +++ b/baremetal/115write-byte.subx @@ -14,6 +14,7 @@ append-byte: # f: (addr stream byte), n: int 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers + 50/push-eax 51/push-ecx 57/push-edi # edi = f @@ -35,6 +36,7 @@ $append-byte:end: # . restore registers 5f/pop-to-edi 59/pop-to-ecx + 58/pop-to-eax # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp diff --git a/baremetal/412render-float-decimal.mu b/baremetal/412render-float-decimal.mu index 498781e9..7aaf8b3a 100644 --- a/baremetal/412render-float-decimal.mu +++ b/baremetal/412render-float-decimal.mu @@ -22,166 +22,170 @@ # This approach turns out to be fast enough for most purposes. # Optimizations, however, get wildly more complex. -fn test-render-float-decimal-normal { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-normal { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage # 0.5 var half/xmm0: float <- rational 1, 2 - var dummy/eax: int <- render-float-decimal screen, half, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "0.5 ", "F - test-render-float-decimal-normal 0.5" + write-float-decimal-approximate s, half, 3 + check-stream-equal s, "0.5", "F - test-write-float-decimal-approximate-normal 0.5" # 0.25 - clear-screen screen + clear-stream s var quarter/xmm0: float <- rational 1, 4 - var dummy/eax: int <- render-float-decimal screen, quarter, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "0.25 ", "F - test-render-float-decimal-normal 0.25" + write-float-decimal-approximate s, quarter, 3 + check-stream-equal s, "0.25", "F - test-write-float-decimal-approximate-normal 0.25" # 0.75 - clear-screen screen + clear-stream s var three-quarters/xmm0: float <- rational 3, 4 - var dummy/eax: int <- render-float-decimal screen, three-quarters, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "0.75 ", "F - test-render-float-decimal-normal 0.75" + write-float-decimal-approximate s, three-quarters, 3 + check-stream-equal s, "0.75", "F - test-write-float-decimal-approximate-normal 0.75" # 0.125 - clear-screen screen + clear-stream s var eighth/xmm0: float <- rational 1, 8 - var dummy/eax: int <- render-float-decimal screen, eighth, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "0.125 ", "F - test-render-float-decimal-normal 0.125" + write-float-decimal-approximate s, eighth, 3 + check-stream-equal s, "0.125", "F - test-write-float-decimal-approximate-normal 0.125" # 0.0625; start using scientific notation - clear-screen screen + clear-stream s var sixteenth/xmm0: float <- rational 1, 0x10 - var dummy/eax: int <- render-float-decimal screen, sixteenth, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "6.25e-2 ", "F - test-render-float-decimal-normal 0.0625" + write-float-decimal-approximate s, sixteenth, 3 + check-stream-equal s, "6.25e-2", "F - test-write-float-decimal-approximate-normal 0.0625" # sqrt(2); truncate floats with lots of digits after the decimal but not too many before - clear-screen screen + clear-stream s var two-f/xmm0: float <- rational 2, 1 var sqrt-2/xmm0: float <- square-root two-f - var dummy/eax: int <- render-float-decimal screen, sqrt-2, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "1.414 ", "F - test-render-float-decimal-normal √2" + write-float-decimal-approximate s, sqrt-2, 3 + check-stream-equal s, "1.414", "F - test-write-float-decimal-approximate-normal √2" } # print whole integers without decimals -fn test-render-float-decimal-integer { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-integer { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage # 1 var one-f/xmm0: float <- rational 1, 1 - var dummy/eax: int <- render-float-decimal screen, one-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "1 ", "F - test-render-float-decimal-integer 1" + write-float-decimal-approximate s, one-f, 3 + check-stream-equal s, "1", "F - test-write-float-decimal-approximate-integer 1" # 2 - clear-screen screen + clear-stream s var two-f/xmm0: float <- rational 2, 1 - var dummy/eax: int <- render-float-decimal screen, two-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "2 ", "F - test-render-float-decimal-integer 2" + write-float-decimal-approximate s, two-f, 3 + check-stream-equal s, "2", "F - test-write-float-decimal-approximate-integer 2" # 10 - clear-screen screen + clear-stream s var ten-f/xmm0: float <- rational 0xa, 1 - var dummy/eax: int <- render-float-decimal screen, ten-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "10 ", "F - test-render-float-decimal-integer 10" + write-float-decimal-approximate s, ten-f, 3 + check-stream-equal s, "10", "F - test-write-float-decimal-approximate-integer 10" # -10 - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational -0xa, 1 - var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "-10 ", "F - test-render-float-decimal-integer -10" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "-10", "F - test-write-float-decimal-approximate-integer -10" # 999 - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational 0x3e7, 1 - var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "999 ", "F - test-render-float-decimal-integer 1000" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "999", "F - test-write-float-decimal-approximate-integer 1000" # 1000 - start using scientific notation - clear-screen screen + clear-stream s var minus-ten-f/xmm0: float <- rational 0x3e8, 1 - var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "1.00e3 ", "F - test-render-float-decimal-integer 1000" + write-float-decimal-approximate s, minus-ten-f, 3 + check-stream-equal s, "1.00e3", "F - test-write-float-decimal-approximate-integer 1000" # 100,000 - clear-screen screen + clear-stream s var hundred-thousand/eax: int <- copy 0x186a0 var hundred-thousand-f/xmm0: float <- convert hundred-thousand - var dummy/eax: int <- render-float-decimal screen, hundred-thousand-f, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "1.00e5 ", "F - test-render-float-decimal-integer 100,000" + write-float-decimal-approximate s, hundred-thousand-f, 3 + check-stream-equal s, "1.00e5", "F - test-write-float-decimal-approximate-integer 100,000" } -fn test-render-float-decimal-zero { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-zero { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var zero: float - var dummy/eax: int <- render-float-decimal screen, zero, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "0 ", "F - test-render-float-decimal-zero" + write-float-decimal-approximate s, zero, 3 + check-stream-equal s, "0", "F - test-write-float-decimal-approximate-zero" } -fn test-render-float-decimal-negative-zero { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-negative-zero { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0x80000000 var negative-zero/xmm0: float <- reinterpret n - var dummy/eax: int <- render-float-decimal screen, negative-zero, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "-0 ", "F - test-render-float-decimal-negative-zero" + write-float-decimal-approximate s, negative-zero, 3 + check-stream-equal s, "-0", "F - test-write-float-decimal-approximate-negative-zero" } -fn test-render-float-decimal-infinity { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-infinity { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int # 0|11111111|00000000000000000000000 # 0111|1111|1000|0000|0000|0000|0000|0000 copy-to n, 0x7f800000 var infinity/xmm0: float <- reinterpret n - var dummy/eax: int <- render-float-decimal screen, infinity, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "Inf ", "F - test-render-float-decimal-infinity" + write-float-decimal-approximate s, infinity, 3 + check-stream-equal s, "Inf", "F - test-write-float-decimal-approximate-infinity" } -fn test-render-float-decimal-negative-infinity { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-negative-infinity { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0xff800000 var negative-infinity/xmm0: float <- reinterpret n - var dummy/eax: int <- render-float-decimal screen, negative-infinity, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "-Inf ", "F - test-render-float-decimal-negative-infinity" + write-float-decimal-approximate s, negative-infinity, 3 + check-stream-equal s, "-Inf", "F - test-write-float-decimal-approximate-negative-infinity" } -fn test-render-float-decimal-not-a-number { - var screen-on-stack: screen - var screen/esi: (addr screen) <- address screen-on-stack - initialize-screen screen, 0x20, 5 # 32 columns should be more than enough +fn test-write-float-decimal-approximate-not-a-number { + var s-storage: (stream byte 0x10) + var s/ecx: (addr stream byte) <- address s-storage var n: int copy-to n, 0xffffffff # exponent must be all 1's, and mantissa must be non-zero var nan/xmm0: float <- reinterpret n - var dummy/eax: int <- render-float-decimal screen, nan, 3/precision, 0, 0, 3/fg, 0/bg - check-screen-row screen, 0/y, "NaN ", "F - test-render-float-decimal-not-a-number" + write-float-decimal-approximate s, nan, 3 + check-stream-equal s, "NaN", "F - test-write-float-decimal-approximate-not-a-number" } -# 'precision' controls the maximum width past which we resort to scientific notation fn render-float-decimal screen: (addr screen), in: float, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int { + var s-storage: (stream byte 0x10) + var s/esi: (addr stream byte) <- address s-storage + write-float-decimal-approximate s, in, precision + var width/eax: int <- copy 0 + var height/ecx: int <- copy 0 + width, height <- screen-size screen + var result/eax: int <- draw-stream-rightward screen, s, x, width, y, color, background-color + return result +} + +# 'precision' controls the maximum width past which we resort to scientific notation +fn write-float-decimal-approximate out: (addr stream byte), in: float, precision: int { # - special names var bits/eax: int <- reinterpret in compare bits, 0 { break-if-!= - var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "0", x, y, color, background-color - return new-x + write out, "0" + return } compare bits, 0x80000000 { break-if-!= - var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "-0", x, y, color, background-color - return new-x + write out, "-0" + return } compare bits, 0x7f800000 { break-if-!= - var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "Inf", x, y, color, background-color - return new-x + write out, "Inf" + return } compare bits, 0xff800000 { break-if-!= - var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "-Inf", x, y, color, background-color - return new-x + write out, "-Inf" + return } var exponent/ecx: int <- copy bits exponent <- shift-right 0x17 # 23 bits of mantissa @@ -190,8 +194,8 @@ fn render-float-decimal screen: (addr screen), in: float, precision: int, x: int compare exponent, 0x80 { break-if-!= - var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "NaN", x, y, color, background-color - return new-x + write out, "NaN" + return } # - regular numbers var sign/edx: int <- copy bits @@ -199,8 +203,7 @@ fn render-float-decimal screen: (addr screen), in: float, precision: int, x: int { compare sign, 1 break-if-!= - draw-code-point screen, 0x2d/minus, x, y, color, background-color - increment x + append-byte out, 0x2d/minus } # v = 1.mantissa (in base 2) << 0x17 @@ -240,8 +243,7 @@ fn render-float-decimal screen: (addr screen), in: float, precision: int, x: int loop } - var new-x/eax: int <- render-float-buffer screen, buf, n, dp, precision, x, y, color, background-color - return new-x + _write-float-array-of-decimal-digits out, buf, n, dp, precision } # store the decimal digits of 'n' into 'buf', units first @@ -410,26 +412,25 @@ fn halve-array-of-decimal-digits _buf: (addr array byte), _n: int, _dp: int -> _ return n, dp } -fn render-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int { +fn _write-float-array-of-decimal-digits out: (addr stream byte), _buf: (addr array byte), n: int, dp: int, precision: int { var buf/edi: (addr array byte) <- copy _buf { compare dp, 0 break-if->= - var new-x/eax: int <- render-float-buffer-in-scientific-notation screen, buf, n, dp, precision, x, y, color, background-color - return new-x + _write-float-array-of-decimal-digits-in-scientific-notation out, buf, n, dp, precision + return } { var dp2/eax: int <- copy dp compare dp2, precision break-if-<= - var new-x/eax: int <- render-float-buffer-in-scientific-notation screen, buf, n, dp, precision, x, y, color, background-color - return new-x + _write-float-array-of-decimal-digits-in-scientific-notation out, buf, n, dp, precision + return } { compare dp, 0 break-if-!= - draw-code-point screen, 0x30/0, x, y, color, background-color - increment x + append-byte out, 0x30/0 } var i/eax: int <- copy 0 # bounds = min(n, dp+3) @@ -447,22 +448,20 @@ fn render-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, d compare i, dp { break-if-!= - draw-code-point screen, 0x2e/decimal-point, x, y, color, background-color - increment x + append-byte out, 0x2e/decimal-point } var curr-a/ecx: (addr byte) <- index buf, i var curr/ecx: byte <- copy-byte *curr-a - curr <- add 0x30/0 - var curr-grapheme/ecx: grapheme <- copy curr - draw-grapheme screen, curr-grapheme, x, y, color, background-color - increment x + var curr-int/ecx: int <- copy curr + curr-int <- add 0x30/0 + append-byte out, curr-int + # i <- increment loop } - return x } -fn render-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int { +fn _write-float-array-of-decimal-digits-in-scientific-notation out: (addr stream byte), _buf: (addr array byte), n: int, dp: int, precision: int { var buf/edi: (addr array byte) <- copy _buf var i/eax: int <- copy 0 { @@ -473,29 +472,23 @@ fn render-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr compare i, 1 { break-if-!= - draw-code-point screen, 0x2e/decimal-point, x, y, color, background-color - increment x + append-byte out, 0x2e/decimal-point } var curr-a/ecx: (addr byte) <- index buf, i var curr/ecx: byte <- copy-byte *curr-a - curr <- add 0x30/0 - var curr-grapheme/ecx: grapheme <- copy curr - draw-grapheme screen, curr-grapheme, x, y, color, background-color - increment x + var curr-int/ecx: int <- copy curr + curr-int <- add 0x30/0 + append-byte out, curr-int # i <- increment loop } - draw-code-point screen, 0x65/e, x, y, color, background-color - increment x + append-byte out, 0x65/e decrement dp - var new-x/eax: int <- copy 0 - var new-y/ecx: int <- copy 0 - new-x, new-y <- draw-int32-decimal-wrapping-right-then-down-over-full-screen screen, dp, x, y, color, background-color - return new-x + write-int32-decimal out, dp } -# follows the structure of render-float-decimal +# follows the structure of write-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 |