parse float from text

This commit is contained in:
Kartik K. Agaram 2021-10-12 22:31:57 -07:00
parent 72d104d169
commit d280bd8dac
1 changed files with 170 additions and 0 deletions

170
515parse-float.mu Normal file
View File

@ -0,0 +1,170 @@
# no support for scientific notation yet
fn parse-float-decimal in: (addr stream byte) -> _/xmm1: float {
var zero: float
var result/xmm1: float <- copy zero
var first-iter?/ecx: int <- copy 1/true
rewind-stream in
var negative?/edx: int <- copy 0/false
# first loop: integer part
var ten/eax: int <- copy 0xa
var ten-f/xmm2: float <- convert ten
{
var done?/eax: boolean <- stream-empty? in
compare done?, 0/false
break-if-!=
var key/eax: byte <- read-byte in
compare key, 0x2e/decimal-point
break-if-=
$parse-float-decimal:body: {
compare key, 0x2d/-
{
break-if-!=
compare first-iter?, 0/false
{
break-if-!=
abort "parse-float-decimal: '-' only allowed in first position"
}
negative? <- copy 1/true
break $parse-float-decimal:body
}
compare key, 0x30/0
{
break-if->=
abort "parse-float-decimal: invalid character < '0'"
}
compare key, 0x39/9
{
break-if-<=
abort "parse-float-decimal: invalid character > '9'"
}
# key is now a digit
var digit-value/eax: int <- copy key
digit-value <- subtract 0x30
var digit-value-f/xmm3: float <- convert digit-value
result <- multiply ten-f
result <- add digit-value-f
}
first-iter? <- copy 0/false
loop
}
# second loop: fraction
var current-position/xmm0: float <- rational 1, 0xa
{
var done?/eax: boolean <- stream-empty? in
compare done?, 0/false
break-if-!=
var key/eax: byte <- read-byte in
compare key, 0x30/0
{
break-if->=
abort "parse-float-decimal: invalid fraction character < '0'"
}
compare key, 0x39/9
{
break-if-<=
abort "parse-float-decimal: invalid fraction character > '9'"
}
# key is now a digit
var digit-value/eax: int <- copy key
digit-value <- subtract 0x30
var digit-value-f/xmm3: float <- convert digit-value
digit-value-f <- multiply current-position
result <- add digit-value-f
current-position <- divide ten-f
#
first-iter? <- copy 0/false
loop
}
# finally, the sign
compare negative?, 0/false
{
break-if-=
var minus-one/eax: int <- copy -1
var minus-one-f/xmm2: float <- convert minus-one
result <- multiply minus-one-f
}
return result
}
fn test-parse-float-decimal-zero {
var s-storage: (stream byte 0x10)
var s/esi: (addr stream byte) <- address s-storage
write s, "00"
var x/xmm1: float <- parse-float-decimal s
var expected/eax: int <- copy 0
var expected-f/xmm0: float <- convert expected
compare x, expected-f
{
break-if-=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-zero", 3/fg 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
count-test-failure
}
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}
fn test-parse-float-decimal-integer {
var s-storage: (stream byte 0x10)
var s/esi: (addr stream byte) <- address s-storage
write s, "34"
var x/xmm1: float <- parse-float-decimal s
var expected/eax: int <- copy 0x22/34
var expected-f/xmm0: float <- convert expected
compare x, expected-f
{
break-if-=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-integer", 3/fg 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
count-test-failure
}
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}
fn test-parse-float-decimal-negative-integer {
var s-storage: (stream byte 0x10)
var s/esi: (addr stream byte) <- address s-storage
write s, "-34"
var x/xmm1: float <- parse-float-decimal s
var expected/eax: int <- copy -0x22/-34
var expected-f/xmm0: float <- convert expected
compare x, expected-f
{
break-if-=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-integer", 3/fg 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
count-test-failure
}
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}
fn test-parse-float-decimal-fraction {
var s-storage: (stream byte 0x10)
var s/esi: (addr stream byte) <- address s-storage
write s, "3.4"
var x/xmm1: float <- parse-float-decimal s
var expected-f/xmm0: float <- rational 0x22/34, 0xa/10
compare x, expected-f
{
break-if-=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-fraction", 3/fg 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
count-test-failure
}
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}
fn test-parse-float-decimal-negative-fraction {
var s-storage: (stream byte 0x10)
var s/esi: (addr stream byte) <- address s-storage
write s, "-3.4"
var x/xmm1: float <- parse-float-decimal s
var expected-f/xmm0: float <- rational -0x22/-34, 0xa/10
compare x, expected-f
{
break-if-=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-fraction", 3/fg 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
count-test-failure
}
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}