Raymond Toy pushed to branch issue-276-xoroshiro128starstar at cmucl / cmucl

Commits:

6 changed files:

Changes:

  • src/code/float.lisp
    ... ... @@ -1137,7 +1137,8 @@
    1137 1137
     			      (floatit (ash bits -1))
    
    1138 1138
     			    #+nil
    
    1139 1139
     			    (progn
    
    1140
    -			      (format t "1: f0, f1 = ~A ~A~%" f0 f1)
    
    1140
    +                              (format t "x = ~A~%" x)
    
    1141
    +			      (format t "1: f0, f1 = ~A~%" f0)
    
    1141 1142
     			      (format t "   scale = ~A~%" (1+ scale)))
    
    1142 1143
     			    
    
    1143 1144
     			    (scale-float f0 (1+ scale))))
    
    ... ... @@ -1146,14 +1147,30 @@
    1146 1147
     			      (floatit bits)
    
    1147 1148
     			    #+nil
    
    1148 1149
     			    (progn
    
    1149
    -			      (format t "2: f0, f1 = ~A ~A~%" f0 f1)
    
    1150
    +			      (format t "2: f0, f1 = ~A~%" f0)
    
    1150 1151
     			      (format t "   scale = ~A~%" scale)
    
    1151
    -			      (format t "scale-float f0 = ~A~%" (scale-float f0 scale))
    
    1152
    -			      (when f1
    
    1153
    -				(format t "scale-float f1 = ~A~%"
    
    1154
    -					(scale-float f1 (- scale 53)))))
    
    1155
    -			    
    
    1156
    -				(scale-float f0 scale))))))
    
    1152
    +			      (format t "scale-float f0 = ~A~%" (scale-float f0 scale)))
    
    1153
    +                            (let ((min-exponent
    
    1154
    +                                    ;; Compute the min (unbiased) exponent
    
    1155
    +                                    (ecase format
    
    1156
    +                                      (single-float
    
    1157
    +                                       (- vm:single-float-normal-exponent-min
    
    1158
    +                                          vm:single-float-bias
    
    1159
    +                                          vm:single-float-digits))
    
    1160
    +                                      (double-float
    
    1161
    +                                       (- vm:double-float-normal-exponent-min
    
    1162
    +                                          vm:double-float-bias
    
    1163
    +                                          vm:double-float-digits)))))
    
    1164
    +                              ;; F0 is always between 0.5 and 1.  If
    
    1165
    +                              ;; SCALE is the min exponent, we have a
    
    1166
    +                              ;; denormal number just less than the
    
    1167
    +                              ;; least-positive float.  We want to
    
    1168
    +                              ;; return the least-positive-float so
    
    1169
    +                              ;; multiply F0 by 2 (without adjusting
    
    1170
    +                              ;; SCALE) to get the nearest float.
    
    1171
    +                              (if (= scale min-exponent)
    
    1172
    +                                  (scale-float (* 2 f0) scale)
    
    1173
    +			          (scale-float f0 scale))))))))
    
    1157 1174
     	       (floatit (bits)
    
    1158 1175
     		 (let ((sign (if plusp 0 1)))
    
    1159 1176
     		   (case format
    

  • src/code/reader.lisp
    ... ... @@ -1785,7 +1785,7 @@ the end of the stream."
    1785 1785
         ;; Is there an exponent letter?
    
    1786 1786
         (cond ((eofp char)
    
    1787 1787
                ;; If not, we've read the whole number.
    
    1788
    -           (let ((num (make-float-aux number divisor
    
    1788
    +           (let ((num (make-float-aux 0 number divisor
    
    1789 1789
                                           *read-default-float-format*
    
    1790 1790
     				      stream)))
    
    1791 1791
                  (return-from make-float (if negative-fraction (- num) num))))
    
    ... ... @@ -1815,7 +1815,7 @@ the end of the stream."
    1815 1815
     				  #+double-double
    
    1816 1816
     				  (#\W 'kernel:double-double-float)))
    
    1817 1817
                       num)
    
    1818
    -	     (setq num (make-float-aux (* (expt 10 exponent) number) divisor
    
    1818
    +	     (setq num (make-float-aux exponent number divisor
    
    1819 1819
     				       float-format stream))
    
    1820 1820
     
    
    1821 1821
     	     (return-from make-float (if negative-fraction
    
    ... ... @@ -1823,10 +1823,55 @@ the end of the stream."
    1823 1823
                                                  num))))
    
    1824 1824
     	  (t (error _"Internal error in floating point reader.")))))
    
    1825 1825
     
    
    1826
    -(defun make-float-aux (number divisor float-format stream)
    
    1826
    +(defun make-float-aux (exponent number divisor float-format stream)
    
    1827
    +  ;; Computes x = number*10^exponent/divisor.
    
    1828
    +  ;;
    
    1829
    +  ;; First check to see if x can possibly fit into a float of the
    
    1830
    +  ;; given format.  So compute log2(x) to get an approximate value of
    
    1831
    +  ;; the base 2 exponent of x.  If it's too large or too small, we can
    
    1832
    +  ;; throw an error immediately.  We don't need to be super accurate
    
    1833
    +  ;; with the limits.  The rest of the code will handle it correctly,
    
    1834
    +  ;; even if we're too small or too large.
    
    1835
    +  (unless (zerop number)
    
    1836
    +    (flet ((fast-log2 (n)
    
    1837
    +             ;;  For an integer, the integer-length is close enough to
    
    1838
    +             ;;  the log2 of the number.
    
    1839
    +             (integer-length n)))
    
    1840
    +      ;; log2(x) = log(number*10^exponent/divisor)
    
    1841
    +      ;;         = exponent*log2(10) + log2(number)-log2(divisor)
    
    1842
    +      (let ((log2-num (+ (* exponent #.(kernel::log2 10d0))
    
    1843
    +                         (fast-log2 number)
    
    1844
    +                         (- (fast-log2 divisor)))))
    
    1845
    +        (multiple-value-bind (log2-low log2-high)
    
    1846
    +            (ecase float-format
    
    1847
    +              ((short-float single-float)
    
    1848
    +               ;; Single-float exponents range is -149 to 127, but we
    
    1849
    +               ;; don't need to be super-accurate since we're
    
    1850
    +               ;; multiplying the values by 2.
    
    1851
    +               (values (* 2 (- vm:single-float-normal-exponent-min
    
    1852
    +                               vm:single-float-bias
    
    1853
    +                               vm:single-float-digits))
    
    1854
    +                       (* 2 (- vm:single-float-normal-exponent-max
    
    1855
    +                               vm:single-float-bias))))
    
    1856
    +              ((double-float long-float
    
    1857
    +                             #+double-double kernel:double-double-float)
    
    1858
    +               (values (* 2 (- vm:double-float-normal-exponent-min
    
    1859
    +                               vm:double-float-bias
    
    1860
    +                               vm:double-float-digits))
    
    1861
    +                       (* 2 (- vm:double-float-normal-exponent-max
    
    1862
    +                               vm:double-float-bias)))))
    
    1863
    +          ;; Double-float exponent range is -1074 to -1023
    
    1864
    +          (unless (< log2-low log2-num log2-high)
    
    1865
    +            ;; The number is definitely too large or too small to fit.
    
    1866
    +            ;; Signal an error.
    
    1867
    +            (%reader-error stream _"Number not representable as a ~S: ~S"
    
    1868
    +			   float-format (read-buffer-to-string)))))))
    
    1869
    +
    
    1870
    +  ;; Otherwise the number might fit, so we carefully compute the result
    
    1827 1871
       (handler-case
    
    1828 1872
           (with-float-traps-masked (:underflow)
    
    1829
    -	(let* ((ratio (/ number divisor))
    
    1873
    +	(let* ((ratio (/ (* (expt 10 exponent) number)
    
    1874
    +                         divisor))
    
    1830 1875
     	       (result (coerce ratio float-format)))
    
    1831 1876
     	  (when (and (zerop result) (not (zerop number)))
    
    1832 1877
     	    ;; The number we've read is so small that it gets
    
    ... ... @@ -1850,7 +1895,7 @@ the end of the stream."
    1850 1895
     	  result))
    
    1851 1896
         (error ()
    
    1852 1897
     	   (%reader-error stream _"Number not representable as a ~S: ~S"
    
    1853
    -			  float-format (/ number divisor)))))
    
    1898
    +			  float-format (read-buffer-to-string)))))
    
    1854 1899
     
    
    1855 1900
     
    
    1856 1901
     (defun make-ratio (stream)
    

  • src/i18n/locale/cmucl.pot
    ... ... @@ -8728,11 +8728,11 @@ msgid "Internal error in floating point reader."
    8728 8728
     msgstr ""
    
    8729 8729
     
    
    8730 8730
     #: src/code/reader.lisp
    
    8731
    -msgid "Underflow"
    
    8731
    +msgid "Number not representable as a ~S: ~S"
    
    8732 8732
     msgstr ""
    
    8733 8733
     
    
    8734 8734
     #: src/code/reader.lisp
    
    8735
    -msgid "Number not representable as a ~S: ~S"
    
    8735
    +msgid "Underflow"
    
    8736 8736
     msgstr ""
    
    8737 8737
     
    
    8738 8738
     #: src/code/reader.lisp
    

  • src/lisp/gencgc.c
    ... ... @@ -6756,10 +6756,9 @@ scavenge_newspace_generation_one_scan(int generation)
    6756 6756
     {
    
    6757 6757
         int i;
    
    6758 6758
     
    
    6759
    -#if 0
    
    6760
    -    fprintf(stderr, "Starting one full scan of newspace generation %d\n",
    
    6761
    -	    generation);
    
    6762
    -#endif
    
    6759
    +    DPRINTF(gencgc_verbose,
    
    6760
    +            (stderr, "Starting one full scan of newspace generation %d\n",
    
    6761
    +             generation));
    
    6763 6762
     
    
    6764 6763
         for (i = 0; i < last_free_page; i++) {
    
    6765 6764
     	if (PAGE_ALLOCATED(i) && !PAGE_UNBOXED(i)
    
    ... ... @@ -6864,10 +6863,10 @@ scavenge_newspace_generation_one_scan(int generation)
    6864 6863
     	    i = last_page;
    
    6865 6864
     	}
    
    6866 6865
         }
    
    6867
    -#if 0
    
    6868
    -    fprintf(stderr, "Finished one full scan of newspace generation %d\n",
    
    6869
    -	    generation);
    
    6870
    -#endif
    
    6866
    +
    
    6867
    +    DPRINTF(gencgc_verbose,
    
    6868
    +            (stderr, "Finished one full scan of newspace generation %d\n",
    
    6869
    +             generation));
    
    6871 6870
     }
    
    6872 6871
     
    
    6873 6872
     /* Scan all weak objects and reset weak object lists */
    
    ... ... @@ -6896,9 +6895,8 @@ scavenge_newspace_generation(int generation)
    6896 6895
         struct new_area (*previous_new_areas)[] = NULL;
    
    6897 6896
         int previous_new_areas_index;
    
    6898 6897
     
    
    6899
    -#if 0
    
    6900
    -    fprintf(stderr, "Start scavenge_newspace_generation %d\n", generation);
    
    6901
    -#endif
    
    6898
    +    DPRINTF(gencgc_verbose,
    
    6899
    +            (stderr, "Start scavenge_newspace_generation %d\n", generation));
    
    6902 6900
     
    
    6903 6901
     #define SC_NS_GEN_CK 0
    
    6904 6902
     #if SC_NS_GEN_CK
    
    ... ... @@ -7078,9 +7076,9 @@ scavenge_newspace_generation(int generation)
    7078 7076
     		    "*** scav.new.gen. %d: write protected page %d written to? dont_move=%d\n",
    
    7079 7077
     		    generation, i, PAGE_DONT_MOVE(i));
    
    7080 7078
     #endif
    
    7081
    -#if 0
    
    7082
    -    fprintf(stderr, "Finished scavenge_newspace_generation %d\n", generation);
    
    7083
    -#endif
    
    7079
    +
    
    7080
    +    DPRINTF(gencgc_verbose,
    
    7081
    +            (stderr, "Finished scavenge_newspace_generation %d\n", generation));
    
    7084 7082
     }
    
    7085 7083
     
    
    7086 7084
     
    
    ... ... @@ -7839,20 +7837,26 @@ garbage_collect_generation(int generation, int raise)
    7839 7837
         scavenge_control_stack();
    
    7840 7838
     #endif
    
    7841 7839
     
    
    7840
    +    DPRINTF(gencgc_verbose,
    
    7841
    +            (stderr, "Scavenging interrupt handlers ...\n"));
    
    7842
    +
    
    7842 7843
         scavenge_interrupt_handlers();
    
    7843 7844
     
    
    7844
    -#ifdef PRINTNOISE
    
    7845
    -    printf("Scavenging the binding stack (%d bytes) ...\n",
    
    7846
    -	   ((lispobj *) get_binding_stack_pointer() -
    
    7847
    -	    binding_stack) * sizeof(lispobj));
    
    7848
    -#endif
    
    7845
    +    DPRINTF(gencgc_verbose,
    
    7846
    +            (stderr, "Done scavenging interrupt handlers\n"));
    
    7847
    +
    
    7848
    +    DPRINTF(gencgc_verbose,
    
    7849
    +            (stderr, "Scavenging the binding stack (%d bytes) ...\n",
    
    7850
    +             ((lispobj *) get_binding_stack_pointer() -
    
    7851
    +              binding_stack) * sizeof(lispobj)));
    
    7852
    +
    
    7849 7853
         /* Scavenge the binding stack. */
    
    7850 7854
         scavenge(binding_stack,
    
    7851 7855
     	     (lispobj *) get_binding_stack_pointer() - binding_stack);
    
    7852 7856
     
    
    7853
    -#ifdef PRINTNOISE
    
    7854
    -    printf("Done scavenging the binding stack.\n");
    
    7855
    -#endif
    
    7857
    +    DPRINTF(gencgc_verbose,
    
    7858
    +            (stderr, "Done scavenging the binding stack.\n"));
    
    7859
    +
    
    7856 7860
         /*
    
    7857 7861
          * Scavenge the scavenge_hooks in case this refers to a hook added
    
    7858 7862
          * in a prior generation GC. From here on the scavenger_hook will
    
    ... ... @@ -7860,30 +7864,44 @@ garbage_collect_generation(int generation, int raise)
    7860 7864
          * doing here.
    
    7861 7865
          */
    
    7862 7866
     
    
    7863
    -#ifdef PRINTNOISE
    
    7864
    -    printf("Scavenging the scavenger hooks ...\n");
    
    7865
    -#endif
    
    7867
    +    DPRINTF(gencgc_verbose,
    
    7868
    +            (stderr, "Scavenging the scavenger hooks ...\n"));
    
    7869
    +
    
    7866 7870
         scavenge(&scavenger_hooks, 1);
    
    7867
    -#ifdef PRINTNOISE
    
    7868
    -    printf("Done scavenging the scavenger hooks.\n");
    
    7869
    -#endif
    
    7871
    +
    
    7872
    +    DPRINTF(gencgc_verbose,
    
    7873
    +            (stderr, "Done scavenging the scavenger hooks.\n"));
    
    7870 7874
     
    
    7871 7875
         static_space_size = (lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER)
    
    7872 7876
     	- static_space;
    
    7873
    -    if (gencgc_verbose > 1)
    
    7874
    -	fprintf(stderr, "Scavenge static space: %ld bytes\n",
    
    7875
    -		static_space_size * sizeof(lispobj));
    
    7877
    +
    
    7878
    +    DPRINTF(gencgc_verbose,
    
    7879
    +            (stderr, "Scavenge static space: %ld bytes\n",
    
    7880
    +             static_space_size * sizeof(lispobj)));
    
    7881
    +
    
    7876 7882
         scavenge(static_space, static_space_size);
    
    7877 7883
     
    
    7884
    +    DPRINTF(gencgc_verbose,
    
    7885
    +            (stderr, "Done scavenging static space\n"));
    
    7886
    +
    
    7878 7887
         /*
    
    7879 7888
          * All generations but the generation being GCed need to be
    
    7880 7889
          * scavenged. The new_space generation needs special handling as
    
    7881 7890
          * objects may be moved in - it is handle separately below.
    
    7882 7891
          */
    
    7883
    -    for (i = 0; i < NUM_GENERATIONS; i++)
    
    7884
    -	if (i != generation && i != new_space)
    
    7892
    +    for (i = 0; i < NUM_GENERATIONS; i++) {
    
    7893
    +	if (i != generation && i != new_space) {
    
    7894
    +            DPRINTF(gencgc_verbose,
    
    7895
    +                    (stderr, "Scavenge generation %lu (gen = %d, new space = %d)\n",
    
    7896
    +                     i, generation, new_space));
    
    7897
    +
    
    7885 7898
     	    scavenge_generation(i);
    
    7886 7899
     
    
    7900
    +            DPRINTF(gencgc_verbose,
    
    7901
    +                    (stderr, "Done scavenging generation %lu\n", i));
    
    7902
    +        }
    
    7903
    +    }
    
    7904
    +
    
    7887 7905
         /*
    
    7888 7906
          * Finally scavenge the new_space generation.  Keep going until no
    
    7889 7907
          * more objects are moved into the new generation.
    

  • src/lisp/os.h
    ... ... @@ -8,7 +8,13 @@
    8 8
     
    
    9 9
     #include "lisp.h"
    
    10 10
     
    
    11
    -#define DPRINTF(t,a) { if (t) fprintf a; }
    
    11
    +#if defined(__GNUC__) || defined(__clang__)
    
    12
    +#define UNLIKELY(x) __builtin_expect(!!(x), 0)
    
    13
    +#else
    
    14
    +#define UNLIKELY(x) (x)
    
    15
    +#endif
    
    16
    +
    
    17
    +#define DPRINTF(t,a) { if (UNLIKELY(t)) fprintf a; }
    
    12 18
     
    
    13 19
     #ifdef DARWIN
    
    14 20
     #include "Darwin-os.h"
    

  • tests/float.lisp
    ... ... @@ -136,5 +136,79 @@
    136 136
         (ext:with-float-traps-masked (:overflow)
    
    137 137
           (* 100 most-negative-double-float)))))
    
    138 138
     
    
    139
    -  
    
    140
    -   
    \ No newline at end of file
    139
    +(define-test float-ratio.single
    
    140
    +    (:tag :issues)
    
    141
    +  ;; least-positive-single-float is 1.4012985e-45.  Let's test with
    
    142
    +  ;; some rationals from 7/10*10^-45 to 1.41*10^-45 to make sure they
    
    143
    +  ;; return 0 or least-positive-single-float
    
    144
    +  (let ((expo (expt 10 -45)))
    
    145
    +    ;; Need to make sure underflows are masked.
    
    146
    +    (kernel::with-float-traps-masked (:underflow)
    
    147
    +      ;; 7/10*10^-45 is just under halfway between 0 and least-positive,
    
    148
    +      ;; so the answer is 0.
    
    149
    +      (assert-equal 0f0 (kernel::float-ratio-float (* 7/10 expo) 'single-float))
    
    150
    +
    
    151
    +      ;; These are all more than half way to
    
    152
    +      ;; least-positive-single-float, so they should return that.
    
    153
    +      (assert-equal least-positive-single-float
    
    154
    +                    (kernel::float-ratio-float (* 8/10 expo) 'single-float))
    
    155
    +      (assert-equal least-positive-single-float
    
    156
    +                    (kernel::float-ratio-float (* 1 expo) 'single-float))
    
    157
    +      (assert-equal least-positive-single-float
    
    158
    +                    (kernel::float-ratio-float (* 14/10 expo) 'single-float))
    
    159
    +      (assert-equal least-positive-single-float
    
    160
    +                    (kernel::float-ratio-float (* 2 expo) 'single-float)))))
    
    161
    +
    
    162
    +(define-test float-ratio.double
    
    163
    +    (:tag :issues)
    
    164
    +  ;; least-positive-double-float is 4.9406564584124654d-324.  Let's
    
    165
    +  ;; test with some rationals from about 2*10^-324 to 4.94*10^-324 to make
    
    166
    +  ;; sure they return 0 or least-positive-double-float
    
    167
    +  (let ((expo (expt 10 -324)))
    
    168
    +    ;; Need to make sure underflows are masked.
    
    169
    +    (kernel::with-float-traps-masked (:underflow)
    
    170
    +      ;; 247/100*10^-324 is just under halfway between 0 and least-positive,
    
    171
    +      ;; so the answer is 0.
    
    172
    +      (assert-equal 0d0 (kernel::float-ratio-float (* 247/100 expo) 'double-float))
    
    173
    +
    
    174
    +      ;; These are all more than half way to
    
    175
    +      ;; least-positive-double-float, so they should return that.
    
    176
    +      (assert-equal least-positive-double-float
    
    177
    +                    (kernel::float-ratio-float (* 248/100 expo) 'double-float))
    
    178
    +      (assert-equal least-positive-double-float
    
    179
    +                    (kernel::float-ratio-float (* 4 expo) 'double-float))
    
    180
    +      (assert-equal least-positive-double-float
    
    181
    +                    (kernel::float-ratio-float (* 494/100 expo) 'double-float))
    
    182
    +      (assert-equal least-positive-double-float
    
    183
    +                    (kernel::float-ratio-float (* 988/100 expo) 'double-float)))))
    
    184
    +    
    
    185
    +(define-test reader-error.small-single-floats
    
    186
    +    (:tag :issues)
    
    187
    +  ;; Test a number less than half of least-positive-single-float,
    
    188
    +  ;; something a bit smaller, hen then something really small that
    
    189
    +  ;; used to appear to hang cmucl because it was trying to compute the
    
    190
    +  ;; a rational with a huge number of digits.
    
    191
    +  (dolist (num '("1e-46" "1e-80" "1e-999999999"))
    
    192
    +    (assert-error 'reader-error (read-from-string num)
    
    193
    +                  num)))
    
    194
    +
    
    195
    +(define-test reader-error.small-double-floats
    
    196
    +    (:tag :issues)
    
    197
    +  ;; Like reader-error.small-single-floats but for doubles
    
    198
    +  (dolist (num '("1d-324" "1d-600" "1d-999999999"))
    
    199
    +    (assert-error 'reader-error (read-from-string num)
    
    200
    +                  num)))
    
    201
    +
    
    202
    +(define-test reader-error.big-single-floats
    
    203
    +    (:tag :issues)
    
    204
    +  ;; Signal error for a number just a bit larger than
    
    205
    +  ;; most-positive-single-float.  And a really big single-float.
    
    206
    +  (assert-error 'reader-error (read-from-string "3.5e38"))
    
    207
    +  (assert-error 'reader-error (read-from-string "1e999999999")))
    
    208
    +
    
    209
    +(define-test reader-error.big-double-floats
    
    210
    +    (:tag :issues)
    
    211
    +  ;; Signal error for a number just a bit larger than
    
    212
    +  ;; most-positive-double-float.  And a really big single-float.
    
    213
    +  (assert-error 'reader-error (read-from-string "1.8d308"))
    
    214
    +  (assert-error 'reader-error (read-from-string "1d999999999")))