From 59007fb1dab0fb4dcba803e319e688fd2befe733 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 29 Nov 2020 14:02:27 -0800 Subject: [PATCH] 7307 --- 412print-float-decimal.mu | 12 +- html/412print-float-decimal.mu.html | 874 ++++++++++++++-------------- 2 files changed, 435 insertions(+), 451 deletions(-) diff --git a/412print-float-decimal.mu b/412print-float-decimal.mu index afd73d45..f41cbe37 100644 --- a/412print-float-decimal.mu +++ b/412print-float-decimal.mu @@ -150,8 +150,8 @@ fn test-print-float-decimal-approximate-not-a-number { initialize-screen screen, 5, 0x20 # 32 columns should be more than enough var n: int copy-to n, 0xffffffff # exponent must be all 1's, and mantissa must be non-zero - var negative-infinity/xmm0: float <- reinterpret n - print-float-decimal-approximate screen, negative-infinity, 3 + 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" } @@ -214,21 +214,16 @@ fn print-float-decimal-approximate screen: (addr screen), in: float, precision: # unlike https://research.swtch.com/ftoa, no ascii here var buf-storage: (array byte 0x7f) var buf/edi: (addr array byte) <- address buf-storage -#? print-int32-decimal 0, v -#? print-string 0, "\n" var n/eax: int <- decimal-digits v, buf -#? dump-digits buf, n, "init" # I suspect we can do without reversing, but we'll follow https://research.swtch.com/ftoa # closely for now. reverse-digits buf, n -#? dump-digits buf, n, "reverse" # loop if e > 0 { compare e, 0 break-if-<= n <- double-array-of-decimal-digits buf, n -#? dump-digits buf, n, "double" e <- decrement loop } @@ -240,9 +235,6 @@ fn print-float-decimal-approximate screen: (addr screen), in: float, precision: compare e, 0 break-if->= n, dp <- halve-array-of-decimal-digits buf, n, dp -#? print-int32-decimal 0, dp -#? print-string 0, ", " -#? dump-digits buf, n, "halve" e <- increment loop } diff --git a/html/412print-float-decimal.mu.html b/html/412print-float-decimal.mu.html index 6c6d4f39..bfea44ff 100644 --- a/html/412print-float-decimal.mu.html +++ b/html/412print-float-decimal.mu.html @@ -210,8 +210,8 @@ if ('onhashchange' in window) { 150 initialize-screen screen, 5, 0x20 # 32 columns should be more than enough 151 var n: int 152 copy-to n, 0xffffffff # exponent must be all 1's, and mantissa must be non-zero -153 var negative-infinity/xmm0: float <- reinterpret n -154 print-float-decimal-approximate screen, negative-infinity, 3 +153 var nan/xmm0: float <- reinterpret n +154 print-float-decimal-approximate screen, nan, 3 155 check-screen-row screen, 1, "NaN ", "F - test-print-float-decimal-approximate-not-a-number" 156 } 157 @@ -274,448 +274,440 @@ if ('onhashchange' in window) { 214 # unlike https://research.swtch.com/ftoa, no ascii here 215 var buf-storage: (array byte 0x7f) 216 var buf/edi: (addr array byte) <- address buf-storage -217 #? print-int32-decimal 0, v -218 #? print-string 0, "\n" -219 var n/eax: int <- decimal-digits v, buf -220 #? dump-digits buf, n, "init" -221 # I suspect we can do without reversing, but we'll follow https://research.swtch.com/ftoa -222 # closely for now. -223 reverse-digits buf, n -224 #? dump-digits buf, n, "reverse" -225 -226 # loop if e > 0 -227 { -228 compare e, 0 -229 break-if-<= -230 n <- double-array-of-decimal-digits buf, n -231 #? dump-digits buf, n, "double" -232 e <- decrement -233 loop -234 } -235 -236 var dp/edx: int <- copy n -237 -238 # loop if e < 0 -239 { -240 compare e, 0 -241 break-if->= -242 n, dp <- halve-array-of-decimal-digits buf, n, dp -243 #? print-int32-decimal 0, dp -244 #? print-string 0, ", " -245 #? dump-digits buf, n, "halve" -246 e <- increment -247 loop -248 } -249 -250 print-float-buffer screen, buf, n, dp, precision -251 } -252 -253 # store the decimal digits of 'n' into 'buf', units first -254 # n must be positive -255 fn decimal-digits n: int, _buf: (addr array byte) -> _/eax: int { -256 var buf/edi: (addr array byte) <- copy _buf -257 var i/ecx: int <- copy 0 -258 var curr/eax: int <- copy n -259 var curr-byte/edx: int <- copy 0 -260 { -261 compare curr, 0 -262 break-if-= -263 curr, curr-byte <- integer-divide curr, 0xa -264 var dest/ebx: (addr byte) <- index buf, i -265 copy-byte-to *dest, curr-byte -266 i <- increment -267 loop -268 } -269 return i -270 } -271 -272 fn reverse-digits _buf: (addr array byte), n: int { -273 var buf/esi: (addr array byte) <- copy _buf -274 var left/ecx: int <- copy 0 -275 var right/edx: int <- copy n -276 right <- decrement -277 { -278 compare left, right -279 break-if->= -280 { -281 var l-a/ecx: (addr byte) <- index buf, left -282 var r-a/edx: (addr byte) <- index buf, right -283 var l/ebx: byte <- copy-byte *l-a -284 var r/eax: byte <- copy-byte *r-a -285 copy-byte-to *l-a, r -286 copy-byte-to *r-a, l -287 } -288 left <- increment -289 right <- decrement -290 loop -291 } -292 } -293 -294 # debug helper -295 fn dump-digits _buf: (addr array byte), count: int, msg: (addr array byte) { -296 var buf/edi: (addr array byte) <- copy _buf -297 var i/ecx: int <- copy 0 -298 print-string 0, msg -299 print-string 0, ": " -300 { -301 compare i, count -302 break-if->= -303 var curr/edx: (addr byte) <- index buf, i -304 var curr-byte/eax: byte <- copy-byte *curr -305 var curr-int/eax: int <- copy curr-byte -306 print-int32-decimal 0, curr-int -307 print-string 0, " " -308 break-if-= -309 i <- increment -310 loop -311 } -312 print-string 0, "\n" -313 } -314 -315 fn double-array-of-decimal-digits _buf: (addr array byte), _n: int -> _/eax: int { -316 var buf/edi: (addr array byte) <- copy _buf -317 # initialize delta -318 var delta/edx: int <- copy 0 -319 { -320 var curr/ebx: (addr byte) <- index buf, 0 -321 var tmp/eax: byte <- copy-byte *curr -322 compare tmp, 5 -323 break-if-< -324 delta <- copy 1 -325 } -326 # loop -327 var x/eax: int <- copy 0 -328 var i/ecx: int <- copy _n -329 i <- decrement -330 { -331 compare i, 0 -332 break-if-<= -333 # x += 2*buf[i] -334 { -335 var tmp/ecx: (addr byte) <- index buf, i -336 var tmp2/ecx: byte <- copy-byte *tmp -337 x <- add tmp2 -338 x <- add tmp2 -339 } -340 # x, buf[i+delta] = x/10, x%10 -341 { -342 var dest-index/ecx: int <- copy i -343 dest-index <- add delta -344 var dest/edi: (addr byte) <- index buf, dest-index -345 var next-digit/edx: int <- copy 0 -346 x, next-digit <- integer-divide x, 0xa -347 copy-byte-to *dest, next-digit -348 } -349 # -350 i <- decrement -351 loop -352 } -353 # final patch-up -354 var n/eax: int <- copy _n -355 compare delta, 1 -356 { -357 break-if-!= -358 var curr/ebx: (addr byte) <- index buf, 0 -359 var one/edx: int <- copy 1 -360 copy-byte-to *curr, one -361 n <- increment -362 } -363 return n -364 } -365 -366 fn halve-array-of-decimal-digits _buf: (addr array byte), _n: int, _dp: int -> _/eax: int, _/edx: int { -367 var buf/edi: (addr array byte) <- copy _buf -368 var n/eax: int <- copy _n -369 var dp/edx: int <- copy _dp -370 # initialize one side -371 { -372 # if buf[n-1]%2 == 0, break -373 var right-index/ecx: int <- copy n -374 right-index <- decrement -375 var right-a/ecx: (addr byte) <- index buf, right-index -376 var right/ecx: byte <- copy-byte *right-a -377 var right-int/ecx: int <- copy right -378 var remainder/edx: int <- copy 0 -379 { -380 var dummy/eax: int <- copy 0 -381 dummy, remainder <- integer-divide right-int, 2 -382 } -383 compare remainder, 0 -384 break-if-= -385 # buf[n] = 0 -386 var next-a/ecx: (addr byte) <- index buf, n -387 var zero/edx: byte <- copy 0 -388 copy-byte-to *next-a, zero -389 # n++ -390 n <- increment -391 } -392 # initialize the other -393 var delta/ebx: int <- copy 0 -394 var x/esi: int <- copy 0 -395 { -396 # if buf[0] >= 2, break -397 var left/ecx: (addr byte) <- index buf, 0 -398 var src/ecx: byte <- copy-byte *left -399 compare src, 2 -400 break-if->= -401 # delta, x = 1, buf[0] -402 delta <- copy 1 -403 x <- copy src -404 # n-- -405 n <- decrement -406 # dp-- -407 dp <- decrement -408 } -409 # loop -410 var i/ecx: int <- copy 0 -411 { -412 compare i, n -413 break-if->= -414 # x = x*10 + buf[i+delta] -415 { -416 var ten/edx: int <- copy 0xa -417 x <- multiply ten -418 var src-index/edx: int <- copy i -419 src-index <- add delta -420 var src-a/edx: (addr byte) <- index buf, src-index -421 var src/edx: byte <- copy-byte *src-a -422 x <- add src -423 } -424 # buf[i], x = x/2, x%2 -425 { -426 var quotient/eax: int <- copy 0 -427 var remainder/edx: int <- copy 0 -428 quotient, remainder <- integer-divide x, 2 -429 x <- copy remainder -430 var dest/edx: (addr byte) <- index buf, i -431 copy-byte-to *dest, quotient -432 } -433 # -434 i <- increment -435 loop -436 } -437 return n, dp -438 } -439 -440 fn print-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { -441 var buf/edi: (addr array byte) <- copy _buf -442 #? print-int32-hex 0, dp -443 #? print-string 0, "\n" -444 { -445 compare dp, 0 -446 break-if->= -447 print-float-buffer-in-scientific-notation screen, buf, n, dp, precision -448 return -449 } -450 { -451 var dp2/eax: int <- copy dp -452 compare dp2, precision -453 break-if-<= -454 print-float-buffer-in-scientific-notation screen, buf, n, dp, precision -455 return -456 } -457 { -458 compare dp, 0 -459 break-if-!= -460 print-string screen, "0" -461 } -462 var i/eax: int <- copy 0 -463 # bounds = min(n, dp+3) -464 var limit/edx: int <- copy dp -465 limit <- add 3 -466 { -467 compare limit, n -468 break-if-<= -469 limit <- copy n -470 } -471 { -472 compare i, limit -473 break-if->= -474 # print '.' if necessary -475 compare i, dp -476 { -477 break-if-!= -478 print-string screen, "." -479 } -480 var curr-a/ecx: (addr byte) <- index buf, i -481 var curr/ecx: byte <- copy-byte *curr-a -482 curr <- add 0x30 # '0' -483 var curr-grapheme/ecx: grapheme <- copy curr -484 print-grapheme screen, curr-grapheme -485 i <- increment -486 loop -487 } -488 } -489 -490 fn print-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { -491 var buf/edi: (addr array byte) <- copy _buf -492 var i/eax: int <- copy 0 -493 { -494 compare i, n -495 break-if->= -496 compare i, precision -497 break-if->= -498 compare i, 1 -499 { -500 break-if-!= -501 print-string screen, "." -502 } -503 var curr-a/ecx: (addr byte) <- index buf, i -504 var curr/ecx: byte <- copy-byte *curr-a -505 curr <- add 0x30 # '0' -506 var curr-grapheme/ecx: grapheme <- copy curr -507 print-grapheme screen, curr-grapheme -508 # -509 i <- increment -510 loop -511 } -512 print-string screen, "e" -513 decrement dp -514 print-int32-decimal screen, dp -515 } -516 -517 # follows the structure of print-float-decimal-approximate -518 # 'precision' controls the maximum width past which we resort to scientific notation -519 fn float-size in: float, precision: int -> _/eax: int { -520 # - special names -521 var bits/eax: int <- reinterpret in -522 compare bits, 0 -523 { -524 break-if-!= -525 return 1 # "0" -526 } -527 compare bits, 0x80000000 -528 { -529 break-if-!= -530 return 2 # "-0" -531 } -532 compare bits, 0x7f800000 -533 { -534 break-if-!= -535 return 3 # "Inf" -536 } -537 compare bits, 0xff800000 -538 { -539 break-if-!= -540 return 4 # "-Inf" -541 } -542 var exponent/ecx: int <- copy bits -543 exponent <- shift-right 0x17 # 23 bits of mantissa -544 exponent <- and 0xff -545 exponent <- subtract 0x7f -546 compare exponent, 0x80 -547 { -548 break-if-!= -549 return 3 # "NaN" -550 } -551 # - regular numbers -552 # v = 1.mantissa (in base 2) << 0x17 -553 var v/ebx: int <- copy bits -554 v <- and 0x7fffff -555 v <- or 0x00800000 # insert implicit 1 -556 # e = exponent - 0x17 -557 var e/ecx: int <- copy exponent -558 e <- subtract 0x17 # move decimal place from before mantissa to after -559 -560 # initialize buffer with decimal representation of v -561 var buf-storage: (array byte 0x7f) -562 var buf/edi: (addr array byte) <- address buf-storage -563 var n/eax: int <- decimal-digits v, buf -564 reverse-digits buf, n -565 -566 # loop if e > 0 -567 { -568 compare e, 0 -569 break-if-<= -570 n <- double-array-of-decimal-digits buf, n -571 e <- decrement -572 loop -573 } -574 -575 var dp/edx: int <- copy n -576 -577 # loop if e < 0 -578 { -579 compare e, 0 +217 var n/eax: int <- decimal-digits v, buf +218 # I suspect we can do without reversing, but we'll follow https://research.swtch.com/ftoa +219 # closely for now. +220 reverse-digits buf, n +221 +222 # loop if e > 0 +223 { +224 compare e, 0 +225 break-if-<= +226 n <- double-array-of-decimal-digits buf, n +227 e <- decrement +228 loop +229 } +230 +231 var dp/edx: int <- copy n +232 +233 # loop if e < 0 +234 { +235 compare e, 0 +236 break-if->= +237 n, dp <- halve-array-of-decimal-digits buf, n, dp +238 e <- increment +239 loop +240 } +241 +242 print-float-buffer screen, buf, n, dp, precision +243 } +244 +245 # store the decimal digits of 'n' into 'buf', units first +246 # n must be positive +247 fn decimal-digits n: int, _buf: (addr array byte) -> _/eax: int { +248 var buf/edi: (addr array byte) <- copy _buf +249 var i/ecx: int <- copy 0 +250 var curr/eax: int <- copy n +251 var curr-byte/edx: int <- copy 0 +252 { +253 compare curr, 0 +254 break-if-= +255 curr, curr-byte <- integer-divide curr, 0xa +256 var dest/ebx: (addr byte) <- index buf, i +257 copy-byte-to *dest, curr-byte +258 i <- increment +259 loop +260 } +261 return i +262 } +263 +264 fn reverse-digits _buf: (addr array byte), n: int { +265 var buf/esi: (addr array byte) <- copy _buf +266 var left/ecx: int <- copy 0 +267 var right/edx: int <- copy n +268 right <- decrement +269 { +270 compare left, right +271 break-if->= +272 { +273 var l-a/ecx: (addr byte) <- index buf, left +274 var r-a/edx: (addr byte) <- index buf, right +275 var l/ebx: byte <- copy-byte *l-a +276 var r/eax: byte <- copy-byte *r-a +277 copy-byte-to *l-a, r +278 copy-byte-to *r-a, l +279 } +280 left <- increment +281 right <- decrement +282 loop +283 } +284 } +285 +286 # debug helper +287 fn dump-digits _buf: (addr array byte), count: int, msg: (addr array byte) { +288 var buf/edi: (addr array byte) <- copy _buf +289 var i/ecx: int <- copy 0 +290 print-string 0, msg +291 print-string 0, ": " +292 { +293 compare i, count +294 break-if->= +295 var curr/edx: (addr byte) <- index buf, i +296 var curr-byte/eax: byte <- copy-byte *curr +297 var curr-int/eax: int <- copy curr-byte +298 print-int32-decimal 0, curr-int +299 print-string 0, " " +300 break-if-= +301 i <- increment +302 loop +303 } +304 print-string 0, "\n" +305 } +306 +307 fn double-array-of-decimal-digits _buf: (addr array byte), _n: int -> _/eax: int { +308 var buf/edi: (addr array byte) <- copy _buf +309 # initialize delta +310 var delta/edx: int <- copy 0 +311 { +312 var curr/ebx: (addr byte) <- index buf, 0 +313 var tmp/eax: byte <- copy-byte *curr +314 compare tmp, 5 +315 break-if-< +316 delta <- copy 1 +317 } +318 # loop +319 var x/eax: int <- copy 0 +320 var i/ecx: int <- copy _n +321 i <- decrement +322 { +323 compare i, 0 +324 break-if-<= +325 # x += 2*buf[i] +326 { +327 var tmp/ecx: (addr byte) <- index buf, i +328 var tmp2/ecx: byte <- copy-byte *tmp +329 x <- add tmp2 +330 x <- add tmp2 +331 } +332 # x, buf[i+delta] = x/10, x%10 +333 { +334 var dest-index/ecx: int <- copy i +335 dest-index <- add delta +336 var dest/edi: (addr byte) <- index buf, dest-index +337 var next-digit/edx: int <- copy 0 +338 x, next-digit <- integer-divide x, 0xa +339 copy-byte-to *dest, next-digit +340 } +341 # +342 i <- decrement +343 loop +344 } +345 # final patch-up +346 var n/eax: int <- copy _n +347 compare delta, 1 +348 { +349 break-if-!= +350 var curr/ebx: (addr byte) <- index buf, 0 +351 var one/edx: int <- copy 1 +352 copy-byte-to *curr, one +353 n <- increment +354 } +355 return n +356 } +357 +358 fn halve-array-of-decimal-digits _buf: (addr array byte), _n: int, _dp: int -> _/eax: int, _/edx: int { +359 var buf/edi: (addr array byte) <- copy _buf +360 var n/eax: int <- copy _n +361 var dp/edx: int <- copy _dp +362 # initialize one side +363 { +364 # if buf[n-1]%2 == 0, break +365 var right-index/ecx: int <- copy n +366 right-index <- decrement +367 var right-a/ecx: (addr byte) <- index buf, right-index +368 var right/ecx: byte <- copy-byte *right-a +369 var right-int/ecx: int <- copy right +370 var remainder/edx: int <- copy 0 +371 { +372 var dummy/eax: int <- copy 0 +373 dummy, remainder <- integer-divide right-int, 2 +374 } +375 compare remainder, 0 +376 break-if-= +377 # buf[n] = 0 +378 var next-a/ecx: (addr byte) <- index buf, n +379 var zero/edx: byte <- copy 0 +380 copy-byte-to *next-a, zero +381 # n++ +382 n <- increment +383 } +384 # initialize the other +385 var delta/ebx: int <- copy 0 +386 var x/esi: int <- copy 0 +387 { +388 # if buf[0] >= 2, break +389 var left/ecx: (addr byte) <- index buf, 0 +390 var src/ecx: byte <- copy-byte *left +391 compare src, 2 +392 break-if->= +393 # delta, x = 1, buf[0] +394 delta <- copy 1 +395 x <- copy src +396 # n-- +397 n <- decrement +398 # dp-- +399 dp <- decrement +400 } +401 # loop +402 var i/ecx: int <- copy 0 +403 { +404 compare i, n +405 break-if->= +406 # x = x*10 + buf[i+delta] +407 { +408 var ten/edx: int <- copy 0xa +409 x <- multiply ten +410 var src-index/edx: int <- copy i +411 src-index <- add delta +412 var src-a/edx: (addr byte) <- index buf, src-index +413 var src/edx: byte <- copy-byte *src-a +414 x <- add src +415 } +416 # buf[i], x = x/2, x%2 +417 { +418 var quotient/eax: int <- copy 0 +419 var remainder/edx: int <- copy 0 +420 quotient, remainder <- integer-divide x, 2 +421 x <- copy remainder +422 var dest/edx: (addr byte) <- index buf, i +423 copy-byte-to *dest, quotient +424 } +425 # +426 i <- increment +427 loop +428 } +429 return n, dp +430 } +431 +432 fn print-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { +433 var buf/edi: (addr array byte) <- copy _buf +434 #? print-int32-hex 0, dp +435 #? print-string 0, "\n" +436 { +437 compare dp, 0 +438 break-if->= +439 print-float-buffer-in-scientific-notation screen, buf, n, dp, precision +440 return +441 } +442 { +443 var dp2/eax: int <- copy dp +444 compare dp2, precision +445 break-if-<= +446 print-float-buffer-in-scientific-notation screen, buf, n, dp, precision +447 return +448 } +449 { +450 compare dp, 0 +451 break-if-!= +452 print-string screen, "0" +453 } +454 var i/eax: int <- copy 0 +455 # bounds = min(n, dp+3) +456 var limit/edx: int <- copy dp +457 limit <- add 3 +458 { +459 compare limit, n +460 break-if-<= +461 limit <- copy n +462 } +463 { +464 compare i, limit +465 break-if->= +466 # print '.' if necessary +467 compare i, dp +468 { +469 break-if-!= +470 print-string screen, "." +471 } +472 var curr-a/ecx: (addr byte) <- index buf, i +473 var curr/ecx: byte <- copy-byte *curr-a +474 curr <- add 0x30 # '0' +475 var curr-grapheme/ecx: grapheme <- copy curr +476 print-grapheme screen, curr-grapheme +477 i <- increment +478 loop +479 } +480 } +481 +482 fn print-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int { +483 var buf/edi: (addr array byte) <- copy _buf +484 var i/eax: int <- copy 0 +485 { +486 compare i, n +487 break-if->= +488 compare i, precision +489 break-if->= +490 compare i, 1 +491 { +492 break-if-!= +493 print-string screen, "." +494 } +495 var curr-a/ecx: (addr byte) <- index buf, i +496 var curr/ecx: byte <- copy-byte *curr-a +497 curr <- add 0x30 # '0' +498 var curr-grapheme/ecx: grapheme <- copy curr +499 print-grapheme screen, curr-grapheme +500 # +501 i <- increment +502 loop +503 } +504 print-string screen, "e" +505 decrement dp +506 print-int32-decimal screen, dp +507 } +508 +509 # follows the structure of print-float-decimal-approximate +510 # 'precision' controls the maximum width past which we resort to scientific notation +511 fn float-size in: float, precision: int -> _/eax: int { +512 # - special names +513 var bits/eax: int <- reinterpret in +514 compare bits, 0 +515 { +516 break-if-!= +517 return 1 # "0" +518 } +519 compare bits, 0x80000000 +520 { +521 break-if-!= +522 return 2 # "-0" +523 } +524 compare bits, 0x7f800000 +525 { +526 break-if-!= +527 return 3 # "Inf" +528 } +529 compare bits, 0xff800000 +530 { +531 break-if-!= +532 return 4 # "-Inf" +533 } +534 var exponent/ecx: int <- copy bits +535 exponent <- shift-right 0x17 # 23 bits of mantissa +536 exponent <- and 0xff +537 exponent <- subtract 0x7f +538 compare exponent, 0x80 +539 { +540 break-if-!= +541 return 3 # "NaN" +542 } +543 # - regular numbers +544 # v = 1.mantissa (in base 2) << 0x17 +545 var v/ebx: int <- copy bits +546 v <- and 0x7fffff +547 v <- or 0x00800000 # insert implicit 1 +548 # e = exponent - 0x17 +549 var e/ecx: int <- copy exponent +550 e <- subtract 0x17 # move decimal place from before mantissa to after +551 +552 # initialize buffer with decimal representation of v +553 var buf-storage: (array byte 0x7f) +554 var buf/edi: (addr array byte) <- address buf-storage +555 var n/eax: int <- decimal-digits v, buf +556 reverse-digits buf, n +557 +558 # loop if e > 0 +559 { +560 compare e, 0 +561 break-if-<= +562 n <- double-array-of-decimal-digits buf, n +563 e <- decrement +564 loop +565 } +566 +567 var dp/edx: int <- copy n +568 +569 # loop if e < 0 +570 { +571 compare e, 0 +572 break-if->= +573 n, dp <- halve-array-of-decimal-digits buf, n, dp +574 e <- increment +575 loop +576 } +577 +578 compare dp, 0 +579 { 580 break-if->= -581 n, dp <- halve-array-of-decimal-digits buf, n, dp -582 e <- increment -583 loop -584 } -585 -586 compare dp, 0 -587 { -588 break-if->= -589 return 8 # hacky for scientific notation -590 } -591 { -592 var dp2/eax: int <- copy dp -593 compare dp2, precision -594 break-if-<= -595 return 8 # hacky for scientific notation -596 } -597 -598 # result = min(n, dp+3) -599 var result/ecx: int <- copy dp -600 result <- add 3 +581 return 8 # hacky for scientific notation +582 } +583 { +584 var dp2/eax: int <- copy dp +585 compare dp2, precision +586 break-if-<= +587 return 8 # hacky for scientific notation +588 } +589 +590 # result = min(n, dp+3) +591 var result/ecx: int <- copy dp +592 result <- add 3 +593 { +594 compare result, n +595 break-if-<= +596 result <- copy n +597 } +598 +599 # account for decimal point +600 compare dp, n 601 { -602 compare result, n -603 break-if-<= -604 result <- copy n -605 } -606 -607 # account for decimal point -608 compare dp, n +602 break-if->= +603 result <- increment +604 } +605 +606 # account for sign +607 var sign/edx: int <- reinterpret in +608 sign <- shift-right 0x1f 609 { -610 break-if->= -611 result <- increment -612 } -613 -614 # account for sign -615 var sign/edx: int <- reinterpret in -616 sign <- shift-right 0x1f -617 { -618 compare sign, 1 -619 break-if-!= -620 result <- increment -621 } -622 return result -623 } -624 -625 ## helper -626 -627 # like check-strings-equal, except array sizes don't have to match -628 fn check-buffer-contains _buf: (addr array byte), _contents: (addr array byte), msg: (addr array byte) { -629 var buf/esi: (addr array byte) <- copy _buf -630 var contents/edi: (addr array byte) <- copy _contents -631 var a/eax: boolean <- string-starts-with? buf, contents -632 check-true a, msg -633 var len/ecx: int <- length contents -634 var len2/eax: int <- length buf -635 compare len, len2 -636 break-if-= -637 var c/eax: (addr byte) <- index buf, len -638 var d/eax: byte <- copy-byte *c -639 var e/eax: int <- copy d -640 check-ints-equal e, 0, msg -641 } -642 -643 fn test-check-buffer-contains { -644 var arr: (array byte 4) -645 var a/esi: (addr array byte) <- address arr -646 var b/eax: (addr byte) <- index a, 0 -647 var c/ecx: byte <- copy 0x61 # 'a' -648 copy-byte-to *b, c -649 check-buffer-contains a, "a", "F - test-check-buffer-contains" -650 check-buffer-contains "a", "a", "F - test-check-buffer-contains/null" # no null check when arrays have same length -651 } -652 -653 #? fn main -> _/ebx: int { -654 #? run-tests -655 #? #? test-print-float-decimal-approximate-integer -656 #? #? test-print-float-decimal-approximate-normal -657 #? return 0 -658 #? } +610 compare sign, 1 +611 break-if-!= +612 result <- increment +613 } +614 return result +615 } +616 +617 ## helper +618 +619 # like check-strings-equal, except array sizes don't have to match +620 fn check-buffer-contains _buf: (addr array byte), _contents: (addr array byte), msg: (addr array byte) { +621 var buf/esi: (addr array byte) <- copy _buf +622 var contents/edi: (addr array byte) <- copy _contents +623 var a/eax: boolean <- string-starts-with? buf, contents +624 check-true a, msg +625 var len/ecx: int <- length contents +626 var len2/eax: int <- length buf +627 compare len, len2 +628 break-if-= +629 var c/eax: (addr byte) <- index buf, len +630 var d/eax: byte <- copy-byte *c +631 var e/eax: int <- copy d +632 check-ints-equal e, 0, msg +633 } +634 +635 fn test-check-buffer-contains { +636 var arr: (array byte 4) +637 var a/esi: (addr array byte) <- address arr +638 var b/eax: (addr byte) <- index a, 0 +639 var c/ecx: byte <- copy 0x61 # 'a' +640 copy-byte-to *b, c +641 check-buffer-contains a, "a", "F - test-check-buffer-contains" +642 check-buffer-contains "a", "a", "F - test-check-buffer-contains/null" # no null check when arrays have same length +643 } +644 +645 #? fn main -> _/ebx: int { +646 #? run-tests +647 #? #? test-print-float-decimal-approximate-integer +648 #? #? test-print-float-decimal-approximate-normal +649 #? return 0 +650 #? }