https://github.com/akkartik/mu/blob/master/412print-float-decimal.mu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 fn test-print-float-decimal-approximate-normal {
26 var screen-on-stack: screen
27 var screen/esi: (addr screen) <- address screen-on-stack
28 initialize-screen screen, 5, 0x20
29
30 var half/xmm0: float <- rational 1, 2
31 print-float-decimal-approximate screen, half, 3
32 check-screen-row screen, 1, "0.5 ", "F - test-print-float-decimal-approximate-normal 0.5"
33
34 clear-screen screen
35 var quarter/xmm0: float <- rational 1, 4
36 print-float-decimal-approximate screen, quarter, 3
37 check-screen-row screen, 1, "0.25 ", "F - test-print-float-decimal-approximate-normal 0.25"
38
39 clear-screen screen
40 var three-quarters/xmm0: float <- rational 3, 4
41 print-float-decimal-approximate screen, three-quarters, 3
42 check-screen-row screen, 1, "0.75 ", "F - test-print-float-decimal-approximate-normal 0.75"
43
44 clear-screen screen
45 var eighth/xmm0: float <- rational 1, 8
46 print-float-decimal-approximate screen, eighth, 3
47 check-screen-row screen, 1, "0.125 ", "F - test-print-float-decimal-approximate-normal 0.125"
48
49 clear-screen screen
50 var sixteenth/xmm0: float <- rational 1, 0x10
51 print-float-decimal-approximate screen, sixteenth, 3
52 check-screen-row screen, 1, "6.25e-2 ", "F - test-print-float-decimal-approximate-normal 0.0625"
53
54 clear-screen screen
55 var two-f/xmm0: float <- rational 2, 1
56 var sqrt-2/xmm0: float <- square-root two-f
57 print-float-decimal-approximate screen, sqrt-2, 3
58 check-screen-row screen, 1, "1.414 ", "F - test-print-float-decimal-approximate-normal √2"
59 }
60
61
62 fn test-print-float-decimal-approximate-integer {
63 var screen-on-stack: screen
64 var screen/esi: (addr screen) <- address screen-on-stack
65 initialize-screen screen, 5, 0x20
66
67 var one-f/xmm0: float <- rational 1, 1
68 print-float-decimal-approximate screen, one-f, 3
69 check-screen-row screen, 1, "1 ", "F - test-print-float-decimal-approximate-integer 1"
70
71 clear-screen screen
72 var two-f/xmm0: float <- rational 2, 1
73 print-float-decimal-approximate screen, two-f, 3
74 check-screen-row screen, 1, "2 ", "F - test-print-float-decimal-approximate-integer 2"
75
76 clear-screen screen
77 var ten-f/xmm0: float <- rational 0xa, 1
78 print-float-decimal-approximate screen, ten-f, 3
79 check-screen-row screen, 1, "10 ", "F - test-print-float-decimal-approximate-integer 10"
80
81 clear-screen screen
82 var minus-ten-f/xmm0: float <- rational -0xa, 1
83 print-float-decimal-approximate screen, minus-ten-f, 3
84 check-screen-row screen, 1, "-10 ", "F - test-print-float-decimal-approximate-integer -10"
85
86 clear-screen screen
87 var minus-ten-f/xmm0: float <- rational 0x3e7, 1
88 print-float-decimal-approximate screen, minus-ten-f, 3
89 check-screen-row screen, 1, "999 ", "F - test-print-float-decimal-approximate-integer 1000"
90
91 clear-screen screen
92 var minus-ten-f/xmm0: float <- rational 0x3e8, 1
93 print-float-decimal-approximate screen, minus-ten-f, 3
94 check-screen-row screen, 1, "1.00e3 ", "F - test-print-float-decimal-approximate-integer 1000"
95
96 clear-screen screen
97 var hundred-thousand/eax: int <- copy 0x186a0
98 var hundred-thousand-f/xmm0: float <- convert hundred-thousand
99 print-float-decimal-approximate screen, hundred-thousand-f, 3
100 check-screen-row screen, 1, "1.00e5 ", "F - test-print-float-decimal-approximate-integer 100,000"
101 }
102
103 fn test-print-float-decimal-approximate-zero {
104 var screen-on-stack: screen
105 var screen/esi: (addr screen) <- address screen-on-stack
106 initialize-screen screen, 5, 0x20
107 var zero: float
108 print-float-decimal-approximate screen, zero, 3
109 check-screen-row screen, 1, "0 ", "F - test-print-float-decimal-approximate-zero"
110 }
111
112 fn test-print-float-decimal-approximate-negative-zero {
113 var screen-on-stack: screen
114 var screen/esi: (addr screen) <- address screen-on-stack
115 initialize-screen screen, 5, 0x20
116 var n: int
117 copy-to n, 0x80000000
118 var negative-zero/xmm0: float <- reinterpret n
119 print-float-decimal-approximate screen, negative-zero, 3
120 check-screen-row screen, 1, "-0 ", "F - test-print-float-decimal-approximate-negative-zero"
121 }
122
123 fn test-print-float-decimal-approximate-infinity {
124 var screen-on-stack: screen
125 var screen/esi: (addr screen) <- address screen-on-stack
126 initialize-screen screen, 5, 0x20
127 var n: int
128
129
130 copy-to n, 0x7f800000
131 var infinity/xmm0: float <- reinterpret n
132 print-float-decimal-approximate screen, infinity, 3
133 check-screen-row screen, 1, "Inf ", "F - test-print-float-decimal-approximate-infinity"
134 }
135
136 fn test-print-float-decimal-approximate-negative-infinity {
137 var screen-on-stack: screen
138 var screen/esi: (addr screen) <- address screen-on-stack
139 initialize-screen screen, 5, 0x20
140 var n: int
141 copy-to n, 0xff800000
142 var negative-infinity/xmm0: float <- reinterpret n
143 print-float-decimal-approximate screen, negative-infinity, 3
144 check-screen-row screen, 1, "-Inf ", "F - test-print-float-decimal-approximate-negative-infinity"
145 }
146
147 fn test-print-float-decimal-approximate-not-a-number {
148 var screen-on-stack: screen
149 var screen/esi: (addr screen) <- address screen-on-stack
150 initialize-screen screen, 5, 0x20
151 var n: int
152 copy-to n, 0xffffffff
153 var negative-infinity/xmm0: float <- reinterpret n
154 print-float-decimal-approximate screen, negative-infinity, 3
155 check-screen-row screen, 1, "NaN ", "F - test-print-float-decimal-approximate-not-a-number"
156 }
157
158
159 fn print-float-decimal-approximate screen: (addr screen), in: float, precision: int {
160
161 var bits/eax: int <- reinterpret in
162 compare bits, 0
163 {
164 break-if-!=
165 print-string screen, "0"
166 return
167 }
168 compare bits, 0x80000000
169 {
170 break-if-!=
171 print-string screen, "-0"
172 return
173 }
174 compare bits, 0x7f800000
175 {
176 break-if-!=
177 print-string screen, "Inf"
178 return
179 }
180 compare bits, 0xff800000
181 {
182 break-if-!=
183 print-string screen, "-Inf"
184 return
185 }
186 var exponent/ecx: int <- copy bits
187 exponent <- shift-right 0x17
188 exponent <- and 0xff
189 exponent <- subtract 0x7f
190 compare exponent, 0x80
191 {
192 break-if-!=
193 print-string screen, "NaN"
194 return
195 }
196
197 var sign/edx: int <- copy bits
198 sign <- shift-right 0x1f
199 {
200 compare sign, 1
201 break-if-!=
202 print-string screen, "-"
203 }
204
205
206 var v/ebx: int <- copy bits
207 v <- and 0x7fffff
208 v <- or 0x00800000
209
210 var e/ecx: int <- copy exponent
211 e <- subtract 0x17
212
213
214
215 var buf-storage: (array byte 0x7f)
216 var buf/edi: (addr array byte) <- address buf-storage
217
218
219 var n/eax: int <- decimal-digits v, buf
220
221
222
223 reverse-digits buf, n
224
225
226
227 {
228 compare e, 0
229 break-if-<=
230 n <- double-array-of-decimal-digits buf, n
231
232 e <- decrement
233 loop
234 }
235
236 var dp/edx: int <- copy n
237
238
239 {
240 compare e, 0
241 break-if->=
242 n, dp <- halve-array-of-decimal-digits buf, n, dp
243
244
245
246 e <- increment
247 loop
248 }
249
250 print-float-buffer screen, buf, n, dp, precision
251 }
252
253
254
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
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
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
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
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
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
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
371 {
372
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
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
390 n <- increment
391 }
392
393 var delta/ebx: int <- copy 0
394 var x/esi: int <- copy 0
395 {
396
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
402 delta <- copy 1
403 x <- copy src
404
405 n <- decrement
406
407 dp <- decrement
408 }
409
410 var i/ecx: int <- copy 0
411 {
412 compare i, n
413 break-if->=
414
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
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
443
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
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
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
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
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
518
519 fn float-size in: float, precision: int -> _/eax: int {
520
521 var bits/eax: int <- reinterpret in
522 compare bits, 0
523 {
524 break-if-!=
525 return 1
526 }
527 compare bits, 0x80000000
528 {
529 break-if-!=
530 return 2
531 }
532 compare bits, 0x7f800000
533 {
534 break-if-!=
535 return 3
536 }
537 compare bits, 0xff800000
538 {
539 break-if-!=
540 return 4
541 }
542 var exponent/ecx: int <- copy bits
543 exponent <- shift-right 0x17
544 exponent <- and 0xff
545 exponent <- subtract 0x7f
546 compare exponent, 0x80
547 {
548 break-if-!=
549 return 3
550 }
551
552
553 var v/ebx: int <- copy bits
554 v <- and 0x7fffff
555 v <- or 0x00800000
556
557 var e/ecx: int <- copy exponent
558 e <- subtract 0x17
559
560
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
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
578 {
579 compare e, 0
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
590 }
591 {
592 var dp2/eax: int <- copy dp
593 compare dp2, precision
594 break-if-<=
595 return 8
596 }
597
598
599 var result/ecx: int <- copy dp
600 result <- add 3
601 {
602 compare result, n
603 break-if-<=
604 result <- copy n
605 }
606
607
608 compare dp, n
609 {
610 break-if->=
611 result <- increment
612 }
613
614
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
626
627
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
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"
651 }
652
653
654
655
656
657
658