Raymond Toy pushed to branch issue-504-read-denormals-with-rounding at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/code/float.lisp
    ... ... @@ -1152,26 +1152,74 @@
    1152 1152
     			  (assert (= len (the fixnum (1+ digits))))
    
    1153 1153
     			  (multiple-value-bind (f0)
    
    1154 1154
     			      (floatit (ash bits -1))
    
    1155
    -			    #+nil
    
    1156
    -			    (progn
    
    1157
    -                              (format t "x = ~A~%" x)
    
    1158
    -			      (format t "1: f0, f1 = ~A~%" f0)
    
    1159
    -			      (format t "   scale = ~A~%" (1+ scale)))
    
    1160
    -			    
    
    1161 1155
     			    (scale-float f0 (1+ scale))))
    
    1162 1156
     			 (t
    
    1163 1157
     			  (multiple-value-bind (f0)
    
    1164 1158
     			      (floatit bits)
    
    1165
    -			    #+nil
    
    1166
    -			    (progn
    
    1167
    -			      (format t "2: f0, f1 = ~A~%" f0)
    
    1168
    -			      (format t "   scale = ~A~%" scale)
    
    1169
    -			      (format t "scale-float f0 = ~A~%" (scale-float f0 scale)))
    
    1170
    -			    ;; SCALE-FLOAT-MAYBE-UNDERFLOW correctly rounds
    
    1171
    -			    ;; to nearest when constructing a denormal result,
    
    1172
    -			    ;; so just call SCALE-FLOAT here without any
    
    1173
    -			    ;; boundary-case fixup.
    
    1174 1159
     			    (scale-float f0 scale))))))
    
    1160
    +	       (denormal-excess ()
    
    1161
    +		 ;; How many bits of precision the result loses by being
    
    1162
    +		 ;; denormal instead of normal.  A normal-precision return
    
    1163
    +		 ;; would be BITS*2^(SCALE-DIGITS) with BITS having DIGITS
    
    1164
    +		 ;; bits.  Once it's known that this representation will
    
    1165
    +		 ;; produce a denormal -- equivalently, that SCALE-FLOAT-
    
    1166
    +		 ;; MAYBE-UNDERFLOW would take the underflow branch --
    
    1167
    +		 ;; (1 - BIAS) - SCALE bits of the mantissa fall below the
    
    1168
    +		 ;; denormal's narrower storage and must be rounded off.
    
    1169
    +		 ;; Zero in the normal range.
    
    1170
    +		 (let ((bias
    
    1171
    +			(ecase format
    
    1172
    +			  (single-float vm:single-float-bias)
    
    1173
    +			  (double-float vm:double-float-bias))))
    
    1174
    +		   (declare (fixnum bias))
    
    1175
    +		   (max 0 (the fixnum
    
    1176
    +				(- (the fixnum (- 1 bias))
    
    1177
    +				   scale)))))
    
    1178
    +	       (round-denormal (fraction-and-guard rem excess)
    
    1179
    +		 ;; FRACTION-AND-GUARD has (1+ DIGITS) bits with one guard
    
    1180
    +		 ;; bit; round it to (- DIGITS EXCESS) bits using round-to-
    
    1181
    +		 ;; nearest, ties to even, with REM as the sticky tail.
    
    1182
    +		 ;; Drops EXCESS+1 low bits in a single step.  This is the
    
    1183
    +		 ;; one rounding the denormal result undergoes; no
    
    1184
    +		 ;; subsequent SCALE-FLOAT call is needed, so there is no
    
    1185
    +		 ;; double rounding.
    
    1186
    +		 (declare (type unsigned-byte fraction-and-guard rem)
    
    1187
    +			  (fixnum excess))
    
    1188
    +		 (let* ((shift (1+ excess))
    
    1189
    +			(low (ldb (byte shift 0) fraction-and-guard))
    
    1190
    +			(quot (ash fraction-and-guard (- shift)))
    
    1191
    +			(halfway (ash 1 excess)))
    
    1192
    +		   (declare (fixnum shift))
    
    1193
    +		   (cond ((< low halfway) quot)
    
    1194
    +			 ((> low halfway) (1+ quot))
    
    1195
    +			 ((not (zerop rem)) (1+ quot))
    
    1196
    +			 ((oddp quot) (1+ quot))
    
    1197
    +			 (t quot))))
    
    1198
    +	       (denormal-from-bits (mantissa excess)
    
    1199
    +		 ;; MANTISSA has at most (- DIGITS EXCESS) bits and is the
    
    1200
    +		 ;; stored significand of a denormal result.  Denormal
    
    1201
    +		 ;; storage holds (1- DIGITS) bits, so rounding can carry
    
    1202
    +		 ;; into the smallest normal only when EXCESS = 1, in
    
    1203
    +		 ;; which case MANTISSA can be exactly (ASH 1 (1- DIGITS)).
    
    1204
    +		 (declare (fixnum excess))
    
    1205
    +		 (let ((sign (if plusp 0 1)))
    
    1206
    +		   (case format
    
    1207
    +		     (single-float
    
    1208
    +		      (cond ((and (= excess 1)
    
    1209
    +				  (= mantissa
    
    1210
    +				     (ash 1 (1- vm:single-float-digits))))
    
    1211
    +			     (single-from-bits
    
    1212
    +			      sign vm:single-float-normal-exponent-min 0))
    
    1213
    +			    (t
    
    1214
    +			     (single-from-bits sign 0 mantissa))))
    
    1215
    +		     (double-float
    
    1216
    +		      (cond ((and (= excess 1)
    
    1217
    +				  (= mantissa
    
    1218
    +				     (ash 1 (1- vm:double-float-digits))))
    
    1219
    +			     (double-from-bits
    
    1220
    +			      sign vm:double-float-normal-exponent-min 0))
    
    1221
    +			    (t
    
    1222
    +			     (double-from-bits sign 0 mantissa)))))))
    
    1175 1223
     	       (floatit (bits)
    
    1176 1224
     		 (let ((sign (if plusp 0 1)))
    
    1177 1225
     		   (case format
    
    ... ... @@ -1189,16 +1237,36 @@
    1189 1237
     	      (declare (fixnum extra))
    
    1190 1238
     	      (cond ((/= extra 1)
    
    1191 1239
     		     (assert (> extra 1)))
    
    1192
    -		    ((oddp fraction-and-guard)
    
    1193
    -		     (return
    
    1194
    -		      (if (zerop rem)
    
    1195
    -			  (float-and-scale
    
    1196
    -			   (if (zerop (logand fraction-and-guard 2))
    
    1197
    -			       fraction-and-guard
    
    1198
    -			       (1+ fraction-and-guard)))
    
    1199
    -			  (float-and-scale (1+ fraction-and-guard)))))
    
    1200 1240
     		    (t
    
    1201
    -		     (return (float-and-scale fraction-and-guard)))))
    
    1241
    +		     (return
    
    1242
    +		      (let ((excess (denormal-excess)))
    
    1243
    +			(cond
    
    1244
    +			  ((zerop excess)
    
    1245
    +			   ;; Normal result: original odd/even tie-break.
    
    1246
    +			   (cond ((oddp fraction-and-guard)
    
    1247
    +				  (if (zerop rem)
    
    1248
    +				      (float-and-scale
    
    1249
    +				       (if (zerop
    
    1250
    +					    (logand fraction-and-guard 2))
    
    1251
    +					   fraction-and-guard
    
    1252
    +					   (1+ fraction-and-guard)))
    
    1253
    +				      (float-and-scale
    
    1254
    +				       (1+ fraction-and-guard))))
    
    1255
    +				 (t
    
    1256
    +				  (float-and-scale fraction-and-guard))))
    
    1257
    +			  (t
    
    1258
    +			   ;; Denormal result: re-round directly to the
    
    1259
    +			   ;; denormal's narrower precision so the only
    
    1260
    +			   ;; rounding step happens here.  Rounding to
    
    1261
    +			   ;; DIGITS first and re-rounding via
    
    1262
    +			   ;; SCALE-FLOAT-MAYBE-UNDERFLOW would double-
    
    1263
    +			   ;; round (e.g. 7.290983e-39 would land on an
    
    1264
    +			   ;; artifical tie at the 24-bit boundary).
    
    1265
    +			   (let ((mantissa
    
    1266
    +				  (round-denormal fraction-and-guard rem
    
    1267
    +						  excess)))
    
    1268
    +			     (declare (type unsigned-byte mantissa))
    
    1269
    +			     (denormal-from-bits mantissa excess)))))))))
    
    1202 1270
     	    (setq shifted-num (ash shifted-num -1))
    
    1203 1271
     	    (incf scale)))))))
    
    1204 1272