?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. #ifndef included_f24toa
  2. #define included_f24toa
  3.  
  4. ; Lot's of #define statements
  5. ; This first batch is to make sure char_NEG, TOK_NEG, char_DEC, and TOK_DECIMAL
  6. ; are defined. This is because I accidentally used two different standards early
  7. ; on, and then I decided to share common routines. Let this be a lesson, because
  8. ; now I have to do convoluted trickery for compatibility -__-
  9.  
  10. #ifndef char_NEG
  11. #ifdef TOK_NEG
  12. #define char_NEG TOK_NEG
  13. #else
  14. #define char_NEG '-'
  15. #endif
  16. #endif
  17.  
  18. #ifndef char_DEC
  19. #ifdef TOK_DECIMAL
  20. #define char_DEC TOK_DECIMAL
  21. #else
  22. #define char_DEC '.'
  23. #endif
  24. #endif
  25.  
  26. #ifndef TOK_NEG
  27. #ifdef char_NEG
  28. #define TOK_NEG char_NEG
  29. #else
  30. #define TOK_NEG '-'
  31. #endif
  32. #endif
  33.  
  34. #ifndef TOK_DECIMAL
  35. #ifdef char_DECIMAL
  36. #define TOK_DECIMAL char_DEC
  37. #else
  38. #define TOK_DECIMAL '.'
  39. #endif
  40. #endif
  41.  
  42.  
  43. ; Now we'll set some defaults
  44.  
  45.  
  46. ; Define the absolute maximum number of digits in the result string.
  47. ; If FORMAT_LEN is bigger than this value, then it will be reduced.
  48. #ifndef MAX_FORMAT_LEN
  49. #define MAX_FORMAT_LEN 7
  50. #endif
  51.  
  52. ; Define this to use an external reference to get the number of digits used
  53. ;#define EXTERNAL_FORMAT_LEN <pointer>
  54. ;
  55. ; For example, TI-OS has a byte at fmtDigits:
  56. ;#define EXTERNAL_FORMAT_LEN fmtDigits
  57.  
  58. ; This is the max number of digits in the output.
  59. ; If EXTERNAL_FORMAT_LEN is used and it is 0, then this will be used.
  60. #ifndef FORMAT_LEN
  61. #define FORMAT_LEN 5
  62. #endif
  63.  
  64. ; Define this to use an external reference for the max exponent before switching
  65. ; to enginieering mode.
  66. ;#define EXTERNAL_FORMAT_MAX_ENGINEERING  <pointer>
  67.  
  68. ; Define the max exponent to use before switching to engineering format
  69. ; If none is defined, this uses FORMAT_LEN.
  70. ; If EXTERNAL_FORMAT_MAX_ENGINEERING is used and is 0 or larger than FORMAT_LEN,
  71. ; then this will be used.
  72. ;#define FORMAT_MAX_ENGINEERING
  73.  
  74.  
  75. ; Define this to use an external reference for the min exponent before switching
  76. ; to enginieering mode.
  77. ;#define EXTERNAL_FORMAT_MIN_ENGINEERING  <pointer>
  78.  
  79. ; Define the largest negative exponent to use engineering format
  80. ; If EXTERNAL_FORMAT_MIN_ENGINEERING is used and is 0 or larger than FORMAT_LEN,
  81. ; then this will be used.
  82. #ifndef FORMAT_MIN_ENGINEERING
  83. #define FORMAT_MIN_ENGINEERING  -3  ; causes exponent of -3 to be enginierring
  84. #endif
  85.  
  86.  
  87.  
  88. ; Finally, includes
  89. #include "../f24/f24mul.z80"
  90. #include "../f24/f24pow10_LUT.z80"
  91. #include "formatstr.z80"
  92.  
  93.  
  94. f24toa:
  95. ;converts a 24-bit float to a string
  96. ;Inputs:
  97. ;   AHL is the float to convert
  98. ;   DE points to where to write the string
  99. ;Output:
  100. ;   HL pointing to the string
  101. ;Destroys:
  102. ;   A,DE,BC
  103. ;Notes:
  104. ;   Uses up to 12 bytes to store the string
  105.  
  106.   ld b,a  ; save the exponent
  107.  
  108.   ; check if the input is 0
  109.   add a,a
  110.   jr nz,+_
  111.   ex de,hl
  112.   jr nc,$+5
  113.   ld (hl),char_NEG
  114.   inc hl
  115.   ld (hl),'0'
  116.   inc hl
  117.   ld (hl),0
  118.   dec hl
  119.   ret nc
  120.   dec hl
  121.   ret
  122. _:
  123.  
  124. ;check if the input is inf or NaN
  125.   push de
  126.   cp $FE
  127.   jr nz,f24toa_finite
  128.   ld a,h
  129.   or l
  130.   ld hl,s_NaN
  131.   jr nz,+_
  132.   ld hl,s_NEGinf
  133.   bit 7,b
  134.   jr nz,+_
  135.   inc hl
  136. _:
  137.   ldi
  138.   ldi
  139.   ldi
  140.   ldi
  141.   ld a,(hl)
  142.   ld (de),a
  143.   pop hl
  144.   ret
  145. f24toa_finite:
  146.  
  147. ;BHL is the float and it is not a special number
  148. ;save the exponent
  149.  
  150. ;write a negative sign if needed
  151.   ld a,b
  152.   add a,a
  153.   jr nc,+_
  154.   ex de,hl
  155.   ld (hl),char_NEG
  156.   inc hl
  157.   ex de,hl
  158. _:
  159.  
  160. ;save the string pointer
  161.   push de
  162.  
  163. ;save the significand
  164.   push hl
  165.  
  166. ;Get an estimate of the power of 10
  167. ;multiply A/2 by 77
  168.  
  169.   ld l,a
  170.   ld h,0
  171.   rrca
  172.   ld e,a
  173.   ld d,h
  174.  
  175.   add hl,hl ;4
  176.   add hl,hl ;8
  177.   add hl,de ;9
  178.   add hl,hl ;18
  179.   add hl,de ;19
  180.   add hl,hl ;38
  181.   add hl,hl ;76
  182.   add hl,de ;77
  183.  
  184. ;now HL is approximately (exp+63)*log10(2)*256
  185.  
  186. ;first, save H, the power-of-10 guess
  187. ;also restore the significand
  188.   ld e,h
  189.   ex (sp),hl
  190.  
  191. ;now multiply by the appropriate power-of-10 to get our input in the [1,10]-ish
  192. ;range. Unlike the higher-precision floats, it is actually smaller to store the
  193. ;whole table. This will also be slightly more accurate and also faster.
  194.   push hl
  195.   ld hl,f24pow10_LUT
  196.   add hl,de
  197.   sla e
  198.   add hl,de
  199.   ld e,(hl)
  200.   inc hl
  201.   ld d,(hl)
  202.   inc hl
  203.   ld c,(hl)
  204.   ld a,b
  205.   and $7F
  206.   pop hl
  207.   call f24mul
  208.  
  209.   cp 63
  210.   jr nc,+_
  211.   ;decrement the power of 10 and multiply by 10
  212.   pop de
  213.   dec d
  214.   push de
  215.   ld c,$42
  216.   ld de,$4000
  217.   call f24mul
  218. _:
  219.  
  220. ;now AHL is a float on [1,20]
  221. ;let's convert it to an 8.16 unsigned fixed-point number
  222.   sub 63
  223.   ld b,a
  224.   ld a,1
  225.   jr z,+_
  226.   add hl,hl
  227.   rla
  228.   djnz $-2
  229. _:
  230.  
  231. ;for rounding porpoises, add 3 to A:HL
  232.   ld bc,3
  233.   add hl,bc
  234.   adc a,b
  235.  
  236.   pop bc    ;power-of-10 is in B
  237.   pop de    ;where to write the output
  238.  
  239.  
  240.   cp 10
  241.   jr nc,+_
  242.   add a,'0'
  243.   ld (de),a
  244.   inc de
  245. ;get a second digit
  246.   push bc
  247.   call f24toa_sub
  248.   jr f24toa_write_digits
  249. _:
  250.   inc b
  251. ;save the power-of-10 exponent
  252.   push bc
  253.  
  254. ;for rounding purposes, add another 30 to HL
  255.   ld bc,30
  256.   add hl,bc
  257.   adc a,b
  258.  
  259.   ;the first digit is either a 1 or a 2
  260.   ex de,hl
  261.   ld (hl),'1'
  262.   sub 20
  263.   jr c,$+4
  264.   inc (hl)
  265.   .db $01
  266.   add a,10
  267.   inc hl
  268.   ex de,hl
  269.   add a,'0'
  270.   ld (de),a
  271.   inc de
  272. f24toa_write_digits:
  273. ;get the next three digits
  274.   call f24toa_sub
  275.   call f24toa_sub
  276.   call f24toa_sub
  277.   xor a
  278.   ld (de),a
  279.  
  280. ; need to determine what to do with the power-of-10 exponent
  281.   pop af
  282.  
  283.   pop hl  ; pointer to the string
  284.   push hl
  285.   sub 19
  286.   ld e,a
  287.   add a,a
  288.   sbc a,a
  289.   ld d,a
  290.   call formatstr
  291.   pop hl
  292.   ret
  293. ;
  294. f24toa_sub:
  295. ;now need to multiply 0.HL by 10 and add '0'
  296.   xor a
  297.   ld b,h
  298.   ld c,l
  299.   add hl,hl \ rla
  300.   add hl,hl \ rla
  301.   add hl,bc \ adc a,'0'/2
  302.   add hl,hl \ rla
  303.   ld (de),a
  304.   inc de
  305.   ret
  306. #endif
  307.