Raymond Toy pushed to branch rtoy-print-using-ryu at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/code/ryu-print.lisp
    ... ... @@ -38,7 +38,9 @@
    38 38
       "Buffer size for d2fixed.")
    
    39 39
     
    
    40 40
     (defun d2fixed (d precision)
    
    41
    -  "Lisp interface to Ryu d2fixed routine (specically d2fixed_buffered)"
    
    41
    +  "Lisp interface to Ryu d2fixed routine (specically d2fixed_buffered).
    
    42
    +  D is the number to convert and PRECISION is the number of digits
    
    43
    +  after the decimal point.  The total number of digits could be more."
    
    42 44
       (declare (double-float d)
    
    43 45
     	   (type (integer 0 #.+d2fixed-max-precision+) precision))
    
    44 46
       (alien:with-alien ((buf (alien:array c-call:char #.+d2fixed-buffer-size+)))
    
    ... ... @@ -54,7 +56,9 @@
    54 56
         (alien:cast buf c-call:c-string)))
    
    55 57
     
    
    56 58
     (defun d2exp (d precision)
    
    57
    -  "Lisp interface to Ryu d2exp (specifically d2exp-buffered)."
    
    59
    +  "Lisp interface to Ryu d2exp (specifically d2exp-buffered).  D is the
    
    60
    +  number to convert and PRECISION is the number of digits after the
    
    61
    +  decimal point.  The result is of the form \"d.ddddEeee\"."
    
    58 62
       (declare (double-float d)
    
    59 63
     	   (type (integer 0 #.+d2fixed-max-precision+) precision))
    
    60 64
       (alien:with-alien ((buf (alien:array c-call:char #.+d2fixed-buffer-size+)))
    
    ... ... @@ -70,7 +74,9 @@
    70 74
         (alien:cast buf c-call:c-string)))
    
    71 75
     			 
    
    72 76
     (defun d2s (d)
    
    73
    -  "Lisp interface to Ryu d2s (specifically d2s_buffered"
    
    77
    +  "Lisp interface to Ryu d2s (specifically d2s_buffered.  D is the number
    
    78
    +  to convert and the result is the shortest string that reproduces the
    
    79
    +  value when read back in."
    
    74 80
       (declare (double-float d))
    
    75 81
       (alien:with-alien ((buf (alien:array c-call:char #.+d2fixed-buffer-size+)))
    
    76 82
         (alien:alien-funcall
    
    ... ... @@ -83,6 +89,9 @@
    83 89
         (alien:cast buf c-call:c-string)))
    
    84 90
     
    
    85 91
     (defun f2s (s)
    
    92
    +  "Lisp interface to Ryu f2s (specifically f2s_buffered.  D is the number
    
    93
    +  to convert and the result is the shortest string that reproduces the
    
    94
    +  value when read back in."
    
    86 95
       (declare (single-float s))
    
    87 96
       (alien:with-alien ((buf (alien:array c-call:char 16)))
    
    88 97
         (alien:alien-funcall
    
    ... ... @@ -103,17 +112,14 @@
    103 112
         (double-float (d2s (abs f)))
    
    104 113
         (single-float (f2s (abs f)))))
    
    105 114
     
    
    106
    -(defun parsed-d2exp (pos-x digits)
    
    107
    -  (let* ((raw (d2exp pos-x digits))
    
    108
    -	 ;; Parse the result from d2exp.  It has the form "d.dddEeee".
    
    109
    -	 (e-pos (position #\e raw))
    
    110
    -	 (mantissa (subseq raw 0 e-pos))
    
    111
    -	 (exp (parse-integer raw :start (1+ e-pos))))
    
    112
    -    (values mantissa exp)))
    
    113
    -
    
    114 115
     (defun parsed-exp-form (raw-string)
    
    116
    +  "Parse RAW-STRING which is a number in exponential form and return the
    
    117
    +  mantissa part as a string and the exponent part as an integer.
    
    118
    +
    
    119
    +  RAW-STRING is of the form \"d.ddddEeee\" where the exponent marker
    
    120
    +  must exist and must be \"e\" or \"E\"."
    
    115 121
       ;; Parse RAW-STRING, that is in exponential form.  That is, it must
    
    116
    -  ;; the form "d.dddEeee".  There cannot be a leading sign.
    
    122
    +  ;; the form "d.dddEeee".  There cannot be a leading sign.  Returns 
    
    117 123
       (let* ((e-pos (position-if #'(lambda (c)
    
    118 124
     				 (member c '(#\e #\E)))
    
    119 125
     			     raw-string))
    
    ... ... @@ -133,12 +139,20 @@
    133 139
       (- (length mantissa)
    
    134 140
          (if (find #\. mantissa) 1 0)))
    
    135 141
     
    
    142
    +(defun count-decimal-digits (n)
    
    143
    +  "Number of decimal digits in N.  N is the absolute value of a
    
    144
    +   double-float's exponent, so 0 <= n <= 324."
    
    145
    +  (declare (type (integer 0 324) n))
    
    146
    +  (cond ((< n 10)  1)
    
    147
    +        ((< n 100) 2)
    
    148
    +        (t         3)))
    
    149
    +
    
    136 150
     (defun compute-d-for-width (w e k actual-exp is-negative-p at-sign-p)
    
    137
    -  ;; Find the largest d (precision) value that fits in width W given
    
    138
    -  ;; the actual exponent (adjusted by k), and whether signs are
    
    139
    -  ;; printed or not.
    
    140
    -  ;;
    
    141
    -  ;; Returns NIL if no width d can fit in a field of length w.
    
    151
    +  "Find the largest d (precision) value that fits in width W given the
    
    152
    +  actual exponent (adjusted by k), and whether signs are printed or
    
    153
    +  not.
    
    154
    +
    
    155
    +  Returns NIL if no width d can fit in a field of length w."
    
    142 156
       (declare (fixnum k actual-exp))
    
    143 157
       (let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
    
    144 158
     	 (exp-digits (max (or e 1)
    
    ... ... @@ -162,25 +176,16 @@
    162 176
     	  (t
    
    163 177
     	   d-fit))))
    
    164 178
     
    
    165
    -(defun count-decimal-digits (n)
    
    166
    -  "Number of decimal digits in N.  N is the absolute value of a
    
    167
    -   double-float's exponent, so 0 <= n <= 324."
    
    168
    -  (declare (type (integer 0 324) n)
    
    169
    -	   (optimize speed))
    
    170
    -  (cond ((< n 10)  1)
    
    171
    -        ((< n 100) 2)
    
    172
    -        (t         3)))
    
    173
    -
    
    174 179
     (defun compute-exp-output-length (mantissa actual-exp k e is-negative-p at-sign-p
    
    175 180
     				  drop-leading-zero-p)
    
    181
    +  "Compute length of the ~E result with the given parameters, but don't
    
    182
    +  build the string.  MANTISSA is \"d[.dddd]\" from d2exp or
    
    183
    +  d2s. ACTUAL-EXP is the exponent with scaling factor applied.  If
    
    184
    +  DROP-LEADING-ZERO-P is non-NIL, the leading \"0\" before the dot (in
    
    185
    +  the K <= 0 form) is omitted from the length."
    
    176 186
       (declare (type simple-string mantissa)
    
    177 187
     	   (fixnum actual-exp k)
    
    178 188
     	   (type (or null fixnum) e))
    
    179
    -  ;; Compute length of the ~E result with the given parameters, but
    
    180
    -  ;; don't build the string.  MANTISSA is "d[.dddd]" from d2exp or d2s.
    
    181
    -  ;; ACTUAL-EXP is the exponent with scaling factor applied.  If
    
    182
    -  ;; DROP-LEADING-ZERO-P is non-NIL, the leading "0" before the dot
    
    183
    -  ;; (in the K <= 0 form) is omitted from the length.
    
    184 189
       (let* ((sign-len (if (or is-negative-p at-sign-p) 1 0))
    
    185 190
              (exp-digits (max (or e 1)
    
    186 191
                               (count-decimal-digits (abs actual-exp))))
    
    ... ... @@ -309,8 +314,8 @@
    309 314
     	     (abs (float value 1d0))))))
    
    310 315
          
    
    311 316
     (defun d2exp-precision (d k)
    
    312
    -  ;; Compute precision for d2exp when CL requests D digits and the
    
    313
    -  ;; scale factor is K."
    
    317
    +  "Compute precision for d2exp when CL requests D digits and the
    
    318
    +  scale factor is K."
    
    314 319
       (cond ((plusp k)
    
    315 320
     	 ;; k digits before the decimal, d-k+1 after, so D is the
    
    316 321
     	 ;; right precision for d2exp.
    
    ... ... @@ -326,6 +331,14 @@
    326 331
     (defun format-e-string (stream mantissa exponent is-negative-p w e k
    
    327 332
                             overflowchar padchar exponentchar at-sign-p
    
    328 333
                             drop-leading-zero-p)
    
    334
    +  "Write the ~E representation of MANTISSA * 10^EXPONENT to STREAM,
    
    335
    +  right-justified in a field of width W.  If specified, the PADCHAR is
    
    336
    +  inserted.  If OVERFLOWCHAR is given and the result won't fit in the
    
    337
    +  field, OVERFLOWCHAR replaces the result.
    
    338
    +
    
    339
    +  K is the scale factor causing the decimal point to be placed K
    
    340
    +  digits in from the start and the displayed exponent is adjusted
    
    341
    +  appropriately."
    
    329 342
       (declare (type simple-string mantissa)
    
    330 343
                (fixnum exponent k))
    
    331 344
       (let* ((shown-exp (- exponent (1- k)))
    
    ... ... @@ -486,6 +499,8 @@
    486 499
     ;;; Ryu ~F
    
    487 500
     (defun format-f-fixed (stream value w d
    
    488 501
                            overflowchar padchar at-sign-p)
    
    502
    +  "Write the ~F representation of VALUE rounded to D digits after the
    
    503
    +  decimal point, right-justified in a field of width W."
    
    489 504
       (declare (type (or single-float double-float) value))
    
    490 505
       (multiple-value-bind (is-negative-p abs-value)
    
    491 506
           (get-sign-and-absolute-value value)
    
    ... ... @@ -500,13 +515,15 @@
    500 515
     	   ;; that case here and drop the zero if the field would not
    
    501 516
     	   ;; otherwise fit in W.  For exact zero the leading digit is
    
    502 517
     	   ;; required, so PLUSP ABS-VALUE gates the dropping.
    
    503
    -	   (lpoint-droppable
    
    518
    +	   (leading-zero-droppable
    
    504 519
     	     (and (plusp abs-value)
    
    505 520
     		  (>= raw-len 2)
    
    506 521
     		  (char= (char raw-string 0) #\0)
    
    507 522
     		  (char= (char raw-string 1) #\.)))
    
    523
    +	   ;; Drop the leading zero if we it's droppable and W is
    
    524
    +	   ;; given and the number won't fit in width W field.
    
    508 525
     	   (drop-leading-zero-p
    
    509
    -	     (and lpoint-droppable
    
    526
    +	     (and leading-zero-droppable
    
    510 527
     		  w
    
    511 528
     		  (> full-field-len w)))
    
    512 529
                (field-len (if drop-leading-zero-p
    
    ... ... @@ -595,13 +612,13 @@
    595 612
     	 ;; The leading "0." may be shortened to "." when the magnitude
    
    596 613
     	 ;; is < 1 (integer part is the single digit "0") and nonzero,
    
    597 614
     	 ;; and only when the full field would not fit in W.
    
    598
    -	 (lpoint-droppable
    
    615
    +	 (leading-zero-droppable
    
    599 616
     	   (and (= int-end 1)
    
    600 617
     		(char= (char rounded 0) #\0)
    
    601 618
     		(not (zerop value))))
    
    602 619
     	 (full-len   (+ sign-len int-end 1 frac-out-len))
    
    603 620
     	 (drop-leading-zero-p
    
    604
    -	   (and lpoint-droppable w (> full-len w)))
    
    621
    +	   (and leading-zero-droppable w (> full-len w)))
    
    605 622
     	 (field-len  (if drop-leading-zero-p (1- full-len) full-len)))
    
    606 623
         (flet ((write-field ()
    
    607 624
     	     (cond (is-negative-p (write-char #\- stream))