Raymond Toy pushed to branch master at cmucl / cmucl
Commits:
-
9bba906a
by Raymond Toy at 2017-12-14T19:31:56-08:00
-
b119b34f
by Raymond Toy at 2017-12-15T09:00:38-08:00
-
8707116f
by Raymond Toy at 2017-12-15T15:40:08-08:00
-
eea11e07
by Raymond Toy at 2017-12-15T15:41:13-08:00
-
192fe3b6
by Raymond Toy at 2017-12-16T08:16:46-08:00
-
c62e3467
by Raymond Toy at 2017-12-16T08:17:24-08:00
-
edcbb7d3
by Raymond Toy at 2017-12-16T20:53:21-08:00
-
95a01145
by Raymond Toy at 2017-12-16T21:05:41-08:00
-
d539b6a0
by Raymond Toy at 2017-12-17T13:04:59-08:00
-
dbc0518d
by Raymond Toy at 2017-12-18T21:02:39-08:00
-
0b94ee3d
by Raymond Toy at 2017-12-19T09:02:25-08:00
-
f9203f85
by Raymond Toy at 2017-12-19T10:04:50-08:00
-
09bbc248
by Raymond Toy at 2017-12-19T17:32:05-08:00
-
38db18cb
by Raymond Toy at 2017-12-19T17:33:27-08:00
-
cba9bad7
by Raymond Toy at 2017-12-19T17:34:28-08:00
-
8d363473
by Raymond Toy at 2017-12-19T17:35:19-08:00
-
7362e561
by Raymond Toy at 2017-12-19T17:35:41-08:00
-
68596489
by Raymond Toy at 2017-12-19T17:36:27-08:00
-
b8d326cc
by Raymond Toy at 2017-12-19T17:46:39-08:00
-
f5df8745
by Raymond Toy at 2017-12-19T18:18:23-08:00
-
be17d9f4
by Raymond Toy at 2017-12-19T19:01:35-08:00
-
0c2284a7
by Raymond Toy at 2017-12-19T19:03:21-08:00
-
4720c794
by Raymond Toy at 2017-12-19T19:03:27-08:00
-
5ca98fb1
by Raymond Toy at 2017-12-20T13:59:20-08:00
-
96c90caf
by Raymond Toy at 2017-12-20T14:00:25-08:00
-
9cd66071
by Raymond Toy at 2017-12-20T16:30:41-08:00
-
96c58393
by Raymond Toy at 2017-12-27T09:46:59-08:00
-
ab6d2c6a
by Raymond Toy at 2017-12-27T10:29:26-08:00
-
164cf685
by Raymond Toy at 2017-12-27T12:17:25-08:00
-
6fbd959e
by Raymond Toy at 2017-12-28T09:04:13-08:00
-
11a14537
by Raymond Toy at 2017-12-28T09:04:27-08:00
-
448e9970
by Raymond Toy at 2017-12-28T09:53:39-08:00
-
58f107b1
by Raymond Toy at 2017-12-28T12:26:31-08:00
-
86599903
by Raymond Toy at 2017-12-28T19:53:42-08:00
-
562752c0
by Raymond Toy at 2017-12-28T19:54:11-08:00
-
e5bd7ef7
by Raymond Toy at 2017-12-29T08:57:34-08:00
-
d8ef7876
by Raymond Toy at 2017-12-29T10:20:13-08:00
-
fb3f58ea
by Raymond Toy at 2017-12-29T18:32:07+00:00
18 changed files:
- .gitlab-ci.yml
- bin/build.sh
- + src/bootfiles/21c/boot-21c-cross-sparc.lisp
- + src/bootfiles/21c/boot-21c-cross-x86.lisp
- + src/bootfiles/21c/boot-21c-cross.lisp
- src/code/exports.lisp
- + src/code/rand-xoroshiro.lisp
- src/code/x86-vm.lisp
- src/compiler/float-tran.lisp
- src/compiler/sparc/arith.lisp
- src/compiler/x86/arith.lisp
- src/compiler/x86/insts.lisp
- src/general-info/release-21d.md
- src/i18n/locale/cmucl.pot
- src/tools/worldbuild.lisp
- src/tools/worldcom.lisp
- src/tools/worldload.lisp
- + tests/rng.lisp
Changes:
... | ... | @@ -8,7 +8,10 @@ linux-runner: |
8 | 8 |
- mkdir snapshot
|
9 | 9 |
- (cd snapshot; tar xjf ../cmucl-21c-x86-linux.tar.bz2; tar xjf ../cmucl-21c-x86-linux.extra.tar.bz2)
|
10 | 10 |
script:
|
11 |
- - bin/build.sh -C "" -o ./snapshot/bin/lisp
|
|
11 |
+ - bin/create-target.sh xtarget x86_linux x86
|
|
12 |
+ - bin/create-target.sh xcross x86_linux x86
|
|
13 |
+ - bin/cross-build-world.sh -crl xtarget xcross src/bootfiles/21c/boot-21c-cross.lisp ./snapshot/bin/lisp
|
|
14 |
+ - bin/build.sh -C "" -o xtarget/lisp/lisp
|
|
12 | 15 |
- bin/make-dist.sh -I dist linux-4
|
13 | 16 |
- bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
|
14 | 17 |
|
... | ... | @@ -20,6 +23,9 @@ osx-runner: |
20 | 23 |
- mkdir snapshot
|
21 | 24 |
- (cd snapshot; tar xjf ../cmucl-21c-x86-darwin.tar.bz2)
|
22 | 25 |
script:
|
23 |
- - bin/build.sh -C "" -o ./snapshot/bin/lisp
|
|
26 |
+ - bin/create-target.sh xtarget x86_darwin
|
|
27 |
+ - bin/create-target.sh xcross x86_darwin
|
|
28 |
+ - bin/cross-build-world.sh -crl xtarget xcross src/bootfiles/21c/boot-21c-cross.lisp ./snapshot/bin/lisp
|
|
29 |
+ - bin/build.sh -C "" -o xtarget/lisp/lisp
|
|
24 | 30 |
- bin/make-dist.sh -I dist darwin-4
|
25 | 31 |
- bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
|
... | ... | @@ -39,7 +39,7 @@ ENABLE2="yes" |
39 | 39 |
ENABLE3="yes"
|
40 | 40 |
ENABLE4="yes"
|
41 | 41 |
|
42 |
-version=21b
|
|
42 |
+version=21c
|
|
43 | 43 |
SRCDIR=src
|
44 | 44 |
BINDIR=bin
|
45 | 45 |
TOOLDIR=$BINDIR
|
1 |
+(in-package :cl-user)
|
|
2 |
+ |
|
3 |
+;;; Rename the SPARC package and backend so that new-backend does the
|
|
4 |
+;;; right thing.
|
|
5 |
+(rename-package "SPARC" "OLD-SPARC" '("OLD-VM"))
|
|
6 |
+(setf (c:backend-name c:*native-backend*) "OLD-SPARC")
|
|
7 |
+ |
|
8 |
+(c::new-backend "SPARC"
|
|
9 |
+ ;; Features to add here
|
|
10 |
+ '(:sparc
|
|
11 |
+ :sparc-v9 ; For Ultrasparc processors
|
|
12 |
+ :complex-fp-vops ; Some slightly faster FP vops on complex numbers
|
|
13 |
+ :linkage-table
|
|
14 |
+ :stack-checking ; Throw error if we run out of stack
|
|
15 |
+ :heap-overflow-check ; Throw error if we run out of
|
|
16 |
+ ; heap (This requires gencgc!)
|
|
17 |
+ :gencgc ; Generational GC
|
|
18 |
+ :relative-package-names ; Relative package names from Allegro
|
|
19 |
+ :conservative-float-type
|
|
20 |
+ :hash-new
|
|
21 |
+ :random-xoroshiro ; xoroshiro128+ RNG
|
|
22 |
+ :cmu ; Announce this is CMUCL
|
|
23 |
+ :cmu20 :cmu20a ; Current version identifier
|
|
24 |
+ :modular-arith ; Modular arithmetic
|
|
25 |
+ :double-double ; Double-double float support
|
|
26 |
+ )
|
|
27 |
+ ;; Features to remove from current *features* here
|
|
28 |
+ '(:sparc-v8 :sparc-v7 ; Choose only one of :sparc-v7, :sparc-v8, :sparc-v9
|
|
29 |
+ ;; Other architectures we aren't using.
|
|
30 |
+ :x86 :x86-bootstrap
|
|
31 |
+ :alpha :osf1 :mips
|
|
32 |
+ ;; Really old stuff that should have been removed long ago.
|
|
33 |
+ :propagate-fun-type :propagate-float-type :constrain-float-type
|
|
34 |
+ ;; Other OSes were not using
|
|
35 |
+ :openbsd :freebsd :glibc2 :linux
|
|
36 |
+ :pentium
|
|
37 |
+ :long-float
|
|
38 |
+ :new-random
|
|
39 |
+ :random-mt19937 ; MT-19937 generator
|
|
40 |
+ :small))
|
|
41 |
+ |
|
42 |
+;;; May need to add some symbols to *features* and
|
|
43 |
+;;; sys::*runtime-features* as well. This might be needed even if we
|
|
44 |
+;;; have those listed above, because of the code checks for things in
|
|
45 |
+;;; *features* and not in the backend-features.. So do that here.
|
|
46 |
+ |
|
47 |
+ |
|
48 |
+;;; Extern-alien-name for the new backend.
|
|
49 |
+(in-package :vm)
|
|
50 |
+(defun extern-alien-name (name)
|
|
51 |
+ (declare (type simple-string name))
|
|
52 |
+ #+(and bsd (not elf))
|
|
53 |
+ (concatenate 'string "_" name)
|
|
54 |
+ #-(and bsd (not elf))
|
|
55 |
+ name)
|
|
56 |
+;; When compiling the compiler, vm:fixup-code-object and
|
|
57 |
+;; vm:sanctify-for-execution are undefined. Import these to get rid
|
|
58 |
+;; of that error.
|
|
59 |
+(import 'old-vm::fixup-code-object)
|
|
60 |
+(import 'old-vm::sanctify-for-execution)
|
|
61 |
+(export 'extern-alien-name)
|
|
62 |
+(export 'fixup-code-object)
|
|
63 |
+(export 'sanctify-for-execution)
|
|
64 |
+ |
|
65 |
+(in-package :cl-user)
|
|
66 |
+ |
|
67 |
+;;; Compile the new backend.
|
|
68 |
+(pushnew :bootstrap *features*)
|
|
69 |
+(pushnew :building-cross-compiler *features*)
|
|
70 |
+(load "target:tools/comcom")
|
|
71 |
+ |
|
72 |
+;;; Load the new backend.
|
|
73 |
+(setf (search-list "c:")
|
|
74 |
+ '("target:compiler/"))
|
|
75 |
+(setf (search-list "vm:")
|
|
76 |
+ '("c:sparc/" "c:generic/"))
|
|
77 |
+(setf (search-list "assem:")
|
|
78 |
+ '("target:assembly/" "target:assembly/sparc/"))
|
|
79 |
+ |
|
80 |
+;; Load the backend of the compiler.
|
|
81 |
+ |
|
82 |
+(in-package "C")
|
|
83 |
+ |
|
84 |
+(load "vm:vm-macs")
|
|
85 |
+(load "vm:parms")
|
|
86 |
+(load "vm:objdef")
|
|
87 |
+(load "vm:interr")
|
|
88 |
+(load "assem:support")
|
|
89 |
+ |
|
90 |
+(load "target:compiler/srctran")
|
|
91 |
+(load "vm:vm-typetran")
|
|
92 |
+(load "target:compiler/float-tran")
|
|
93 |
+(load "target:compiler/saptran")
|
|
94 |
+ |
|
95 |
+(load "vm:macros")
|
|
96 |
+(load "vm:utils")
|
|
97 |
+ |
|
98 |
+(load "vm:vm")
|
|
99 |
+(load "vm:insts")
|
|
100 |
+(load "vm:primtype")
|
|
101 |
+(load "vm:move")
|
|
102 |
+(load "vm:sap")
|
|
103 |
+(load "vm:system")
|
|
104 |
+(load "vm:char")
|
|
105 |
+(load "vm:float")
|
|
106 |
+ |
|
107 |
+(load "vm:memory")
|
|
108 |
+(load "vm:static-fn")
|
|
109 |
+(load "vm:arith")
|
|
110 |
+(load "vm:cell")
|
|
111 |
+(load "vm:subprim")
|
|
112 |
+(load "vm:debug")
|
|
113 |
+(load "vm:c-call")
|
|
114 |
+(load "vm:print")
|
|
115 |
+(load "vm:alloc")
|
|
116 |
+(load "vm:call")
|
|
117 |
+(load "vm:nlx")
|
|
118 |
+(load "vm:values")
|
|
119 |
+(load "vm:array")
|
|
120 |
+(load "vm:pred")
|
|
121 |
+(load "vm:type-vops")
|
|
122 |
+ |
|
123 |
+(load "assem:assem-rtns")
|
|
124 |
+ |
|
125 |
+(load "assem:array")
|
|
126 |
+(load "assem:arith")
|
|
127 |
+(load "assem:alloc")
|
|
128 |
+ |
|
129 |
+(load "c:pseudo-vops")
|
|
130 |
+ |
|
131 |
+(check-move-function-consistency)
|
|
132 |
+ |
|
133 |
+(load "vm:new-genesis")
|
|
134 |
+ |
|
135 |
+;;; OK, the cross compiler backend is loaded.
|
|
136 |
+ |
|
137 |
+(setf *features* (remove :building-cross-compiler *features*))
|
|
138 |
+ |
|
139 |
+;;; Info environment hacks.
|
|
140 |
+(macrolet ((frob (&rest syms)
|
|
141 |
+ `(progn ,@(mapcar #'(lambda (sym)
|
|
142 |
+ `(defconstant ,sym
|
|
143 |
+ (symbol-value
|
|
144 |
+ (find-symbol ,(symbol-name sym)
|
|
145 |
+ :vm))))
|
|
146 |
+ syms))))
|
|
147 |
+ (frob OLD-VM:BYTE-BITS OLD-VM:WORD-BITS
|
|
148 |
+ OLD-VM:CHAR-BITS
|
|
149 |
+ OLD-VM:CHAR-BYTES
|
|
150 |
+ OLD-VM:LOWTAG-BITS
|
|
151 |
+ #+long-float OLD-VM:SIMPLE-ARRAY-LONG-FLOAT-TYPE
|
|
152 |
+ OLD-VM:SIMPLE-ARRAY-DOUBLE-FLOAT-TYPE
|
|
153 |
+ OLD-VM:SIMPLE-ARRAY-SINGLE-FLOAT-TYPE
|
|
154 |
+ #+long-float OLD-VM:SIMPLE-ARRAY-COMPLEX-LONG-FLOAT-TYPE
|
|
155 |
+ OLD-VM:SIMPLE-ARRAY-COMPLEX-DOUBLE-FLOAT-TYPE
|
|
156 |
+ OLD-VM:SIMPLE-ARRAY-COMPLEX-SINGLE-FLOAT-TYPE
|
|
157 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-2-TYPE
|
|
158 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-4-TYPE
|
|
159 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-8-TYPE
|
|
160 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-16-TYPE
|
|
161 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-32-TYPE
|
|
162 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-8-TYPE
|
|
163 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-16-TYPE
|
|
164 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-30-TYPE
|
|
165 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-32-TYPE
|
|
166 |
+ OLD-VM:SIMPLE-BIT-VECTOR-TYPE
|
|
167 |
+ OLD-VM:SIMPLE-STRING-TYPE OLD-VM:SIMPLE-VECTOR-TYPE
|
|
168 |
+ OLD-VM:SIMPLE-ARRAY-TYPE OLD-VM:VECTOR-DATA-OFFSET
|
|
169 |
+ OLD-VM:DOUBLE-FLOAT-DIGITS
|
|
170 |
+ old-vm:single-float-digits
|
|
171 |
+ OLD-VM:DOUBLE-FLOAT-EXPONENT-BYTE
|
|
172 |
+ OLD-VM:DOUBLE-FLOAT-NORMAL-EXPONENT-MAX
|
|
173 |
+ OLD-VM:DOUBLE-FLOAT-SIGNIFICAND-BYTE
|
|
174 |
+ OLD-VM:SINGLE-FLOAT-EXPONENT-BYTE
|
|
175 |
+ OLD-VM:SINGLE-FLOAT-NORMAL-EXPONENT-MAX
|
|
176 |
+ OLD-VM:SINGLE-FLOAT-SIGNIFICAND-BYTE
|
|
177 |
+ )
|
|
178 |
+ #+double-double
|
|
179 |
+ (frob OLD-VM:SIMPLE-ARRAY-COMPLEX-DOUBLE-DOUBLE-FLOAT-TYPE
|
|
180 |
+ OLD-VM:SIMPLE-ARRAY-DOUBLE-DOUBLE-FLOAT-TYPE)
|
|
181 |
+ )
|
|
182 |
+ |
|
183 |
+;; Modular arith hacks. When cross-compiling, the compiler wants to
|
|
184 |
+;; constant-fold some stuff, and it needs the following functions to
|
|
185 |
+;; do so. This just gets rid of the hundreds of errors that happen.
|
|
186 |
+(setf (fdefinition 'vm::ash-left-mod32) #'old-vm::ash-left-mod32)
|
|
187 |
+(setf (fdefinition 'vm::lognot-mod32) #'old-vm::lognot-mod32)
|
|
188 |
+;; End modular arith hacks
|
|
189 |
+ |
|
190 |
+(let ((function (symbol-function 'kernel:error-number-or-lose)))
|
|
191 |
+ (let ((*info-environment* (c:backend-info-environment c:*target-backend*)))
|
|
192 |
+ (setf (symbol-function 'kernel:error-number-or-lose) function)
|
|
193 |
+ (setf (info function kind 'kernel:error-number-or-lose) :function)
|
|
194 |
+ (setf (info function where-from 'kernel:error-number-or-lose) :defined)))
|
|
195 |
+ |
|
196 |
+(defun fix-class (name)
|
|
197 |
+ (let* ((new-value (find-class name))
|
|
198 |
+ (new-layout (kernel::%class-layout new-value))
|
|
199 |
+ (new-cell (kernel::find-class-cell name))
|
|
200 |
+ (*info-environment* (c:backend-info-environment c:*target-backend*)))
|
|
201 |
+ (remhash name kernel::*forward-referenced-layouts*)
|
|
202 |
+ (kernel::%note-type-defined name)
|
|
203 |
+ (setf (info type kind name) :instance)
|
|
204 |
+ (setf (info type class name) new-cell)
|
|
205 |
+ (setf (info type compiler-layout name) new-layout)
|
|
206 |
+ new-value))
|
|
207 |
+(fix-class 'c::vop-parse)
|
|
208 |
+(fix-class 'c::operand-parse)
|
|
209 |
+ |
|
210 |
+#+random-mt19937
|
|
211 |
+(declaim (notinline kernel:random-chunk))
|
|
212 |
+ |
|
213 |
+(setf c:*backend* c:*target-backend*)
|
|
214 |
+ |
|
215 |
+;;; Extern-alien-name for the new backend.
|
|
216 |
+(in-package :vm)
|
|
217 |
+(defun extern-alien-name (name)
|
|
218 |
+ (declare (type simple-string name))
|
|
219 |
+ name)
|
|
220 |
+(export 'extern-alien-name)
|
|
221 |
+(export 'fixup-code-object)
|
|
222 |
+(export 'sanctify-for-execution)
|
|
223 |
+(in-package :cl-user)
|
|
224 |
+ |
|
225 |
+;;; Don't load compiler parts from the target compilation
|
|
226 |
+ |
|
227 |
+(defparameter *load-stuff* nil)
|
|
228 |
+ |
|
229 |
+;; Sometimes during cross-compile sparc::any-reg isn't defined during
|
|
230 |
+;; cross-compile.
|
|
231 |
+;;
|
|
232 |
+;; hack, hack, hack: Make old-vm::any-reg the same as
|
|
233 |
+;; sparc::any-reg as an SC. Do this by adding old-vm::any-reg
|
|
234 |
+;; to the hash table with the same value as sparc::any-reg.
|
|
235 |
+(let ((ht (c::backend-sc-names c::*target-backend*)))
|
|
236 |
+ (setf (gethash 'old-vm::any-reg ht)
|
|
237 |
+ (gethash 'vm::any-reg ht)))
|
1 |
+;; Basic cross-compile script for cross-compiling from x86 to x86.
|
|
2 |
+;; May require tweaking for more difficult cross-compiles.
|
|
3 |
+ |
|
4 |
+(in-package :cl-user)
|
|
5 |
+ |
|
6 |
+;;; Rename the X86 package and backend so that new-backend does the
|
|
7 |
+;;; right thing.
|
|
8 |
+(rename-package "X86" "OLD-X86" '("OLD-VM"))
|
|
9 |
+(setf (c:backend-name c:*native-backend*) "OLD-X86")
|
|
10 |
+ |
|
11 |
+(c::new-backend "X86"
|
|
12 |
+ ;; Features to add here. These are just examples. You may not
|
|
13 |
+ ;; need to list anything here. We list them here anyway as a
|
|
14 |
+ ;; record of typical features for all x86 ports.
|
|
15 |
+ '(:x86 :i486 :pentium
|
|
16 |
+ :stack-checking ; Catches stack overflow
|
|
17 |
+ :heap-overflow-check ; Catches heap overflows
|
|
18 |
+ :relative-package-names ; relative package names
|
|
19 |
+ :mp ; multiprocessing
|
|
20 |
+ :gencgc ; Generational GC
|
|
21 |
+ :conservative-float-type
|
|
22 |
+ :hash-new
|
|
23 |
+ :random-xoroshiro ; xoroshiro128+ RNG
|
|
24 |
+ :cmu :cmu20 :cmu20a ; Version features
|
|
25 |
+ :double-double ; double-double float support
|
|
26 |
+ )
|
|
27 |
+ ;; Features to remove from current *features* here. Normally don't
|
|
28 |
+ ;; need to list anything here unless you are trying to remove a
|
|
29 |
+ ;; feature.
|
|
30 |
+ '(:x86-bootstrap
|
|
31 |
+ ;; :alpha :osf1 :mips
|
|
32 |
+ :propagate-fun-type :propagate-float-type :constrain-float-type
|
|
33 |
+ ;; :openbsd :freebsd :glibc2 :linux
|
|
34 |
+ :long-float :new-random :small
|
|
35 |
+ :random-mt19937))
|
|
36 |
+ |
|
37 |
+;;; Compile the new backend.
|
|
38 |
+(pushnew :bootstrap *features*)
|
|
39 |
+(pushnew :building-cross-compiler *features*)
|
|
40 |
+ |
|
41 |
+;; Make fixup-code-object and sanctify-for-execution in the VM package
|
|
42 |
+;; be the same as the original. Needed to get rid of a compiler error
|
|
43 |
+;; in generic/core.lisp. (This halts cross-compilations if the
|
|
44 |
+;; compiling lisp uses the -batch flag.
|
|
45 |
+(import 'old-vm::fixup-code-object "VM")
|
|
46 |
+(import 'old-vm::sanctify-for-execution "VM")
|
|
47 |
+(export 'vm::fixup-code-object "VM")
|
|
48 |
+(export 'vm::sanctify-for-execution "VM")
|
|
49 |
+ |
|
50 |
+(do-external-symbols (sym "OLD-VM")
|
|
51 |
+ (export (intern (symbol-name sym) "VM") "VM"))
|
|
52 |
+ |
|
53 |
+(load "target:tools/comcom")
|
|
54 |
+ |
|
55 |
+;;; Load the new backend.
|
|
56 |
+(setf (search-list "c:")
|
|
57 |
+ '("target:compiler/"))
|
|
58 |
+(setf (search-list "vm:")
|
|
59 |
+ '("c:x86/" "c:generic/"))
|
|
60 |
+(setf (search-list "assem:")
|
|
61 |
+ '("target:assembly/" "target:assembly/x86/"))
|
|
62 |
+ |
|
63 |
+;; Load the backend of the compiler.
|
|
64 |
+ |
|
65 |
+(in-package "C")
|
|
66 |
+ |
|
67 |
+(load "vm:vm-macs")
|
|
68 |
+(load "vm:parms")
|
|
69 |
+(load "vm:objdef")
|
|
70 |
+(load "vm:interr")
|
|
71 |
+(load "assem:support")
|
|
72 |
+ |
|
73 |
+(load "target:compiler/srctran")
|
|
74 |
+(load "vm:vm-typetran")
|
|
75 |
+(load "target:compiler/float-tran")
|
|
76 |
+(load "target:compiler/saptran")
|
|
77 |
+ |
|
78 |
+(load "vm:macros")
|
|
79 |
+(load "vm:utils")
|
|
80 |
+ |
|
81 |
+(load "vm:vm")
|
|
82 |
+(load "vm:insts")
|
|
83 |
+(load "vm:primtype")
|
|
84 |
+(load "vm:move")
|
|
85 |
+(load "vm:sap")
|
|
86 |
+(when (target-featurep :sse2)
|
|
87 |
+ (load "vm:sse2-sap"))
|
|
88 |
+(load "vm:system")
|
|
89 |
+(load "vm:char")
|
|
90 |
+(if (target-featurep :sse2)
|
|
91 |
+ (load "vm:float-sse2")
|
|
92 |
+ (load "vm:float"))
|
|
93 |
+ |
|
94 |
+(load "vm:memory")
|
|
95 |
+(load "vm:static-fn")
|
|
96 |
+(load "vm:arith")
|
|
97 |
+(load "vm:cell")
|
|
98 |
+(load "vm:subprim")
|
|
99 |
+(load "vm:debug")
|
|
100 |
+(load "vm:c-call")
|
|
101 |
+(if (target-featurep :sse2)
|
|
102 |
+ (load "vm:sse2-c-call")
|
|
103 |
+ (load "vm:x87-c-call"))
|
|
104 |
+ |
|
105 |
+(load "vm:print")
|
|
106 |
+(load "vm:alloc")
|
|
107 |
+(load "vm:call")
|
|
108 |
+(load "vm:nlx")
|
|
109 |
+(load "vm:values")
|
|
110 |
+;; These need to be loaded before array because array wants to use
|
|
111 |
+;; some vops as templates.
|
|
112 |
+(load (if (target-featurep :sse2)
|
|
113 |
+ "vm:sse2-array"
|
|
114 |
+ "vm:x87-array"))
|
|
115 |
+(load "vm:array")
|
|
116 |
+(load "vm:pred")
|
|
117 |
+(load "vm:type-vops")
|
|
118 |
+ |
|
119 |
+(load "assem:assem-rtns")
|
|
120 |
+ |
|
121 |
+(load "assem:array")
|
|
122 |
+(load "assem:arith")
|
|
123 |
+(load "assem:alloc")
|
|
124 |
+ |
|
125 |
+(load "c:pseudo-vops")
|
|
126 |
+ |
|
127 |
+(check-move-function-consistency)
|
|
128 |
+ |
|
129 |
+(load "vm:new-genesis")
|
|
130 |
+ |
|
131 |
+;;; OK, the cross compiler backend is loaded.
|
|
132 |
+ |
|
133 |
+(setf *features* (remove :building-cross-compiler *features*))
|
|
134 |
+ |
|
135 |
+;;; Info environment hacks.
|
|
136 |
+(macrolet ((frob (&rest syms)
|
|
137 |
+ `(progn ,@(mapcar #'(lambda (sym)
|
|
138 |
+ `(defconstant ,sym
|
|
139 |
+ (symbol-value
|
|
140 |
+ (find-symbol ,(symbol-name sym)
|
|
141 |
+ :vm))))
|
|
142 |
+ syms))))
|
|
143 |
+ (frob OLD-VM:BYTE-BITS OLD-VM:WORD-BITS
|
|
144 |
+ OLD-VM:CHAR-BITS
|
|
145 |
+ OLD-VM:CHAR-BYTES
|
|
146 |
+ #+long-float OLD-VM:SIMPLE-ARRAY-LONG-FLOAT-TYPE
|
|
147 |
+ OLD-VM:SIMPLE-ARRAY-DOUBLE-FLOAT-TYPE
|
|
148 |
+ OLD-VM:SIMPLE-ARRAY-SINGLE-FLOAT-TYPE
|
|
149 |
+ #+long-float OLD-VM:SIMPLE-ARRAY-COMPLEX-LONG-FLOAT-TYPE
|
|
150 |
+ OLD-VM:SIMPLE-ARRAY-COMPLEX-DOUBLE-FLOAT-TYPE
|
|
151 |
+ OLD-VM:SIMPLE-ARRAY-COMPLEX-SINGLE-FLOAT-TYPE
|
|
152 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-2-TYPE
|
|
153 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-4-TYPE
|
|
154 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-8-TYPE
|
|
155 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-16-TYPE
|
|
156 |
+ OLD-VM:SIMPLE-ARRAY-UNSIGNED-BYTE-32-TYPE
|
|
157 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-8-TYPE
|
|
158 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-16-TYPE
|
|
159 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-30-TYPE
|
|
160 |
+ OLD-VM:SIMPLE-ARRAY-SIGNED-BYTE-32-TYPE
|
|
161 |
+ OLD-VM:SIMPLE-BIT-VECTOR-TYPE
|
|
162 |
+ OLD-VM:SIMPLE-STRING-TYPE OLD-VM:SIMPLE-VECTOR-TYPE
|
|
163 |
+ OLD-VM:SIMPLE-ARRAY-TYPE OLD-VM:VECTOR-DATA-OFFSET
|
|
164 |
+ OLD-VM:DOUBLE-FLOAT-EXPONENT-BYTE
|
|
165 |
+ OLD-VM:DOUBLE-FLOAT-NORMAL-EXPONENT-MAX
|
|
166 |
+ OLD-VM:DOUBLE-FLOAT-SIGNIFICAND-BYTE
|
|
167 |
+ OLD-VM:SINGLE-FLOAT-EXPONENT-BYTE
|
|
168 |
+ OLD-VM:SINGLE-FLOAT-NORMAL-EXPONENT-MAX
|
|
169 |
+ OLD-VM:SINGLE-FLOAT-SIGNIFICAND-BYTE
|
|
170 |
+ )
|
|
171 |
+ #+double-double
|
|
172 |
+ (frob OLD-VM:SIMPLE-ARRAY-COMPLEX-DOUBLE-DOUBLE-FLOAT-TYPE
|
|
173 |
+ OLD-VM:SIMPLE-ARRAY-DOUBLE-DOUBLE-FLOAT-TYPE))
|
|
174 |
+ |
|
175 |
+;; Modular arith hacks
|
|
176 |
+(setf (fdefinition 'vm::ash-left-mod32) #'old-vm::ash-left-mod32)
|
|
177 |
+(setf (fdefinition 'vm::lognot-mod32) #'old-vm::lognot-mod32)
|
|
178 |
+;; End arith hacks
|
|
179 |
+ |
|
180 |
+(let ((function (symbol-function 'kernel:error-number-or-lose)))
|
|
181 |
+ (let ((*info-environment* (c:backend-info-environment c:*target-backend*)))
|
|
182 |
+ (setf (symbol-function 'kernel:error-number-or-lose) function)
|
|
183 |
+ (setf (info function kind 'kernel:error-number-or-lose) :function)
|
|
184 |
+ (setf (info function where-from 'kernel:error-number-or-lose) :defined)))
|
|
185 |
+ |
|
186 |
+(defun fix-class (name)
|
|
187 |
+ (let* ((new-value (find-class name))
|
|
188 |
+ (new-layout (kernel::%class-layout new-value))
|
|
189 |
+ (new-cell (kernel::find-class-cell name))
|
|
190 |
+ (*info-environment* (c:backend-info-environment c:*target-backend*)))
|
|
191 |
+ (remhash name kernel::*forward-referenced-layouts*)
|
|
192 |
+ (kernel::%note-type-defined name)
|
|
193 |
+ (setf (info type kind name) :instance)
|
|
194 |
+ (setf (info type class name) new-cell)
|
|
195 |
+ (setf (info type compiler-layout name) new-layout)
|
|
196 |
+ new-value))
|
|
197 |
+(fix-class 'c::vop-parse)
|
|
198 |
+(fix-class 'c::operand-parse)
|
|
199 |
+ |
|
200 |
+#+random-mt19937
|
|
201 |
+(declaim (notinline kernel:random-chunk))
|
|
202 |
+ |
|
203 |
+(setf c:*backend* c:*target-backend*)
|
|
204 |
+ |
|
205 |
+;;; Extern-alien-name for the new backend.
|
|
206 |
+(in-package :vm)
|
|
207 |
+(defun extern-alien-name (name)
|
|
208 |
+ (declare (type simple-string name))
|
|
209 |
+ #-elf
|
|
210 |
+ (concatenate 'simple-string "_" name)
|
|
211 |
+ #+elf
|
|
212 |
+ name)
|
|
213 |
+(export 'extern-alien-name)
|
|
214 |
+(in-package :cl-user)
|
|
215 |
+ |
|
216 |
+;;; Don't load compiler parts from the target compilation
|
|
217 |
+ |
|
218 |
+(defparameter *load-stuff* nil)
|
|
219 |
+ |
|
220 |
+;; hack, hack, hack: Make old-vm::any-reg the same as
|
|
221 |
+;; x86::any-reg as an SC. Do this by adding old-vm::any-reg
|
|
222 |
+;; to the hash table with the same value as x86::any-reg.
|
|
223 |
+(let ((ht (c::backend-sc-names c::*target-backend*)))
|
|
224 |
+ (setf (gethash 'old-vm::any-reg ht)
|
|
225 |
+ (gethash 'vm::any-reg ht)))
|
1 |
+;; Cross-compile script to change the default random number generator
|
|
2 |
+;; from MT19937 to xoroshiro128+.
|
|
3 |
+ |
|
4 |
+;; The cross-script is basically the default platform script, but we
|
|
5 |
+;; remove :random-mt19937 and add :random-xoroshiro to the backend
|
|
6 |
+;; features.
|
|
7 |
+ |
|
8 |
+#+x86
|
|
9 |
+(load "src/bootfiles/21c/boot-21c-cross-x86.lisp")
|
|
10 |
+ |
|
11 |
+#+sparc
|
|
12 |
+(load "src/bootfiles/21c/boot-21c-cross-sparc.lisp")
|
|
13 |
+ |
... | ... | @@ -2550,7 +2550,9 @@ |
2550 | 2550 |
"SIMPLE-ARRAY-COMPLEX-DOUBLE-DOUBLE-FLOAT-P"
|
2551 | 2551 |
"OBJECT-NOT-SIMPLE-ARRAY-COMPLEX-DOUBLE-DOUBLE-FLOAT-ERROR"
|
2552 | 2552 |
"DD-PI"
|
2553 |
- "INVALID-CASE"))
|
|
2553 |
+ "INVALID-CASE")
|
|
2554 |
+ #+random-xoroshiro
|
|
2555 |
+ (:export "RANDOM-STATE-JUMP"))
|
|
2554 | 2556 |
|
2555 | 2557 |
(dolist
|
2556 | 2558 |
(name
|
1 |
+;;; -*- Mode: Lisp; Package: Kernel -*-
|
|
2 |
+;;;
|
|
3 |
+;;; **********************************************************************
|
|
4 |
+;;; This code was written as part of CMU Common Lisp and has been
|
|
5 |
+;;; placed in the public domain, and is provided 'as is'.
|
|
6 |
+;;;
|
|
7 |
+(ext:file-comment
|
|
8 |
+ "$Header: src/code/rand-xoroshiro.lisp $")
|
|
9 |
+ |
|
10 |
+;;;
|
|
11 |
+;;; **********************************************************************
|
|
12 |
+;;;
|
|
13 |
+;;; Support for the xoroshiro128+ random number generator by David
|
|
14 |
+;;; Blackman and Sebastiano Vigna (vigna@acm.org). See
|
|
15 |
+;;; http://xoroshiro.di.unimi.it/.
|
|
16 |
+ |
|
17 |
+(in-package "LISP")
|
|
18 |
+(intl:textdomain "cmucl")
|
|
19 |
+ |
|
20 |
+(export '(random-state random-state-p random *random-state*
|
|
21 |
+ make-random-state))
|
|
22 |
+ |
|
23 |
+(in-package "KERNEL")
|
|
24 |
+(export '(%random-single-float %random-double-float random-chunk init-random-state
|
|
25 |
+ random-state-jump))
|
|
26 |
+ |
|
27 |
+(sys:register-lisp-feature :random-xoroshiro)
|
|
28 |
+ |
|
29 |
+ |
|
30 |
+;;;; Random state hackery:
|
|
31 |
+ |
|
32 |
+;; Generate a random seed that can be used for seeding the generator.
|
|
33 |
+;; If /dev/urandom is available, it is used to generate random data as
|
|
34 |
+;; the seed. Otherwise, the current time is used as the seed.
|
|
35 |
+(defun generate-seed (&optional (nwords 1))
|
|
36 |
+ ;; On some systems (as reported by Ole Rohne on cmucl-imp),
|
|
37 |
+ ;; /dev/urandom isn't what we think it is, so if it doesn't work,
|
|
38 |
+ ;; silently generate the seed from the current time.
|
|
39 |
+ (or (ignore-errors
|
|
40 |
+ (let ((words (make-array nwords :element-type '(unsigned-byte 32))))
|
|
41 |
+ (with-open-file (rand "/dev/urandom"
|
|
42 |
+ :direction :input
|
|
43 |
+ :element-type '(unsigned-byte 32))
|
|
44 |
+ (read-sequence words rand))
|
|
45 |
+ (if (= nwords 1)
|
|
46 |
+ (aref words 0)
|
|
47 |
+ (let ((vec (make-array (floor nwords 2) :element-type '(unsigned-byte 64))))
|
|
48 |
+ (do ((k 0 (+ k 1))
|
|
49 |
+ (j 0 (+ j 2)))
|
|
50 |
+ ((>= k (length vec))
|
|
51 |
+ vec)
|
|
52 |
+ (setf (aref vec k)
|
|
53 |
+ (logior (ash (aref words j) 32)
|
|
54 |
+ (aref words (+ j 1)))))))))
|
|
55 |
+ (logand (get-universal-time) #xffffffff)))
|
|
56 |
+ |
|
57 |
+(defun int-init-xoro-state (&optional (seed 5772156649015328606) state)
|
|
58 |
+ (let ((state (or state (make-array 2 :element-type 'double-float)))
|
|
59 |
+ (splitmix-state (ldb (byte 64 0) seed)))
|
|
60 |
+ (flet ((splitmix64 ()
|
|
61 |
+ ;; See http://xoroshiro.di.unimi.it/splitmix64.c for the
|
|
62 |
+ ;; definitive reference. The basic algorithm, where x is
|
|
63 |
+ ;; the 64-bit state of the generator, is:
|
|
64 |
+ ;;
|
|
65 |
+ ;; uint64_t z = (x += 0x9e3779b97f4a7c15);
|
|
66 |
+ ;; z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
|
67 |
+ ;; z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
|
68 |
+ ;; return z ^ (z >> 31);
|
|
69 |
+ ;;
|
|
70 |
+ ;; This is only used occasionally for initializing the
|
|
71 |
+ ;; RNG, so this is a very straight-forward
|
|
72 |
+ ;; implementation.
|
|
73 |
+ (let ((z (setf splitmix-state
|
|
74 |
+ (ldb (byte 64 0) (+ splitmix-state #x9e3779b97f4a7c15)))))
|
|
75 |
+ (declare (type (unsigned-byte 64) z))
|
|
76 |
+ (setf z (ldb (byte 64 0)
|
|
77 |
+ (* (logxor z (ash z -30))
|
|
78 |
+ #xbf58476d1ce4e5b9)))
|
|
79 |
+ (setf z (ldb (byte 64 0)
|
|
80 |
+ (* (logxor z (ash z -27))
|
|
81 |
+ #x94d049bb133111eb)))
|
|
82 |
+ (logxor z (ash z -31))))
|
|
83 |
+ (make-double (x)
|
|
84 |
+ (let ((lo (ldb (byte 32 0) x))
|
|
85 |
+ (hi (ldb (byte 32 32) x)))
|
|
86 |
+ (kernel:make-double-float
|
|
87 |
+ (if (< hi #x80000000)
|
|
88 |
+ hi
|
|
89 |
+ (- hi #x100000000))
|
|
90 |
+ lo))))
|
|
91 |
+ (let* ((s0 (splitmix64))
|
|
92 |
+ (s1 (splitmix64)))
|
|
93 |
+ (setf (aref state 0) (make-double s0)
|
|
94 |
+ (aref state 1) (make-double s1))
|
|
95 |
+ state))))
|
|
96 |
+ |
|
97 |
+;; Initialize from an array. The KEY is a 2-element array of unsigned
|
|
98 |
+;; 64-bit integers. The state is set to the given 64-bit integer
|
|
99 |
+;; values.
|
|
100 |
+(defun vec-init-xoro-state (key &optional (state (make-array 2 :element-type 'double-float)))
|
|
101 |
+ (declare (type (array (unsigned-byte 64) (2)) key)
|
|
102 |
+ (type (simple-array double-float (2)) state))
|
|
103 |
+ (flet ((make-double (x)
|
|
104 |
+ (declare (type (unsigned-byte 64) x))
|
|
105 |
+ (let ((hi (ldb (byte 32 32) x))
|
|
106 |
+ (lo (ldb (byte 32 0) x)))
|
|
107 |
+ (kernel:make-double-float
|
|
108 |
+ (if (< hi #x80000000)
|
|
109 |
+ hi
|
|
110 |
+ (- hi #x100000000))
|
|
111 |
+ lo))))
|
|
112 |
+ (setf (aref state 0) (make-double (aref key 0))
|
|
113 |
+ (aref state 1) (make-double (aref key 1)))
|
|
114 |
+ state))
|
|
115 |
+ |
|
116 |
+;; The default seed is the digits of Euler's constant, 0.5772....
|
|
117 |
+(defun init-random-state (&optional (seed 5772156649015328606) state)
|
|
118 |
+ _N"Generate an random state vector from the given SEED. The seed can be
|
|
119 |
+ either an integer or a vector of (unsigned-byte 64)"
|
|
120 |
+ (declare (type (or null integer
|
|
121 |
+ (array (unsigned-byte 64) (*)))
|
|
122 |
+ seed))
|
|
123 |
+ (let ((state (or state (make-array 2 :element-type 'double-float))))
|
|
124 |
+ (etypecase seed
|
|
125 |
+ (integer
|
|
126 |
+ (int-init-xoro-state (ldb (byte 64 0) seed) state))
|
|
127 |
+ ((array (unsigned-byte 64) (2))
|
|
128 |
+ (vec-init-xoro-state seed state)))))
|
|
129 |
+ |
|
130 |
+(defstruct (random-state
|
|
131 |
+ (:constructor make-random-object)
|
|
132 |
+ (:print-function %print-xoro-state)
|
|
133 |
+ (:make-load-form-fun :just-dump-it-normally))
|
|
134 |
+ ;; The state of the RNG. The actual algorithm uses 2 64-bit words
|
|
135 |
+ ;; of state. To reduce consing, we use an array of double-float's
|
|
136 |
+ ;; since a double-float is 64 bits long. At no point do we operate
|
|
137 |
+ ;; on these as floats; they're just convenient objects to hold the
|
|
138 |
+ ;; state we need.
|
|
139 |
+ (state (init-random-state)
|
|
140 |
+ :type (simple-array double-float (2)))
|
|
141 |
+ ;; The generator produces 64-bit results. We separate the 64-bit
|
|
142 |
+ ;; result into two parts. One is returned and the other is cached
|
|
143 |
+ ;; here for later use.
|
|
144 |
+ (rand 0 :type (unsigned-byte 32))
|
|
145 |
+ ;; Indicates if RAND holds a valid value. If NIL, we need to
|
|
146 |
+ ;; generate a new 64-bit result.
|
|
147 |
+ (cached-p nil :type (member t nil)))
|
|
148 |
+ |
|
149 |
+(defun %print-xoro-state (rng-state stream depth)
|
|
150 |
+ (declare (ignore depth))
|
|
151 |
+ ;; Basically the same as the default structure printer, but we want
|
|
152 |
+ ;; to print the state as an array of integers instead of doubles,
|
|
153 |
+ ;; because it's a bit confusing to see the state as doubles.
|
|
154 |
+ (let ((state (random-state-state rng-state)))
|
|
155 |
+ (pprint-logical-block (stream nil :prefix "#S(" :suffix ")")
|
|
156 |
+ (prin1 'random-state stream)
|
|
157 |
+ (write-char #\space stream)
|
|
158 |
+ (pprint-indent :block 2 stream)
|
|
159 |
+ (pprint-newline :linear stream)
|
|
160 |
+ (prin1 :state stream)
|
|
161 |
+ (write-char #\space stream)
|
|
162 |
+ (pprint-newline :miser stream)
|
|
163 |
+ (pprint-logical-block (stream nil :prefix "#.(" :suffix ")")
|
|
164 |
+ (prin1 'init-random-state stream)
|
|
165 |
+ (write-char #\space stream)
|
|
166 |
+ (flet ((c (x)
|
|
167 |
+ (multiple-value-bind (hi lo)
|
|
168 |
+ (double-float-bits x)
|
|
169 |
+ (logior (ash (ldb (byte 32 0) hi) 32)
|
|
170 |
+ lo))))
|
|
171 |
+ (write (make-array 2 :element-type '(unsigned-byte 64)
|
|
172 |
+ :initial-contents (list (c (aref state 0))
|
|
173 |
+ (c (aref state 1))))
|
|
174 |
+ :stream stream
|
|
175 |
+ :base 16
|
|
176 |
+ :radix t)))
|
|
177 |
+ (write-char #\space stream)
|
|
178 |
+ (pprint-newline :linear stream)
|
|
179 |
+ |
|
180 |
+ (prin1 :rand stream)
|
|
181 |
+ (write-char #\space stream)
|
|
182 |
+ (pprint-newline :miser stream)
|
|
183 |
+ (prin1 (random-state-rand rng-state) stream)
|
|
184 |
+ (write-char #\space stream)
|
|
185 |
+ (pprint-newline :linear stream)
|
|
186 |
+ |
|
187 |
+ (prin1 :cached-p stream)
|
|
188 |
+ (write-char #\space stream)
|
|
189 |
+ (pprint-newline :miser stream)
|
|
190 |
+ (prin1 (random-state-cached-p rng-state) stream))))
|
|
191 |
+ |
|
192 |
+(defvar *random-state*
|
|
193 |
+ (make-random-object))
|
|
194 |
+ |
|
195 |
+(defun make-random-state (&optional state)
|
|
196 |
+ _N"Make a random state object. If STATE is not supplied, return a copy
|
|
197 |
+ of the default random state. If STATE is a random state, then return a
|
|
198 |
+ copy of it. If STATE is T then return a random state generated from
|
|
199 |
+ the universal time or /dev/urandom if available."
|
|
200 |
+ (flet ((copy-random-state (state)
|
|
201 |
+ (let ((old-state (random-state-state state))
|
|
202 |
+ (new-state
|
|
203 |
+ (make-array 2 :element-type 'double-float)))
|
|
204 |
+ (setf (aref new-state 0) (aref old-state 0))
|
|
205 |
+ (setf (aref new-state 1) (aref old-state 1))
|
|
206 |
+ (make-random-object :state new-state
|
|
207 |
+ :rand (random-state-rand state)
|
|
208 |
+ :cached-p (random-state-cached-p state)))))
|
|
209 |
+ (cond ((not state)
|
|
210 |
+ (copy-random-state *random-state*))
|
|
211 |
+ ((random-state-p state)
|
|
212 |
+ (copy-random-state state))
|
|
213 |
+ ((eq state t)
|
|
214 |
+ (make-random-object :state (init-random-state (generate-seed 4))
|
|
215 |
+ :rand 0
|
|
216 |
+ :cached-p nil))
|
|
217 |
+ (t
|
|
218 |
+ (error _"Argument is not a RANDOM-STATE, T, or NIL: ~S" state)))))
|
|
219 |
+ |
|
220 |
+(defun rand-initializer ()
|
|
221 |
+ (init-random-state (generate-seed)
|
|
222 |
+ (random-state-state *random-state*)))
|
|
223 |
+ |
|
224 |
+(pushnew 'rand-initializer ext:*after-save-initializations*)
|
|
225 |
+ |
|
226 |
+;;;; Random entries:
|
|
227 |
+ |
|
228 |
+;; Sparc and x86 have vops to implement xoroshiro-gen that are much
|
|
229 |
+;; faster than the portable lisp version. Use them.
|
|
230 |
+#+(or x86 sparc)
|
|
231 |
+(declaim (inline xoroshiro-gen))
|
|
232 |
+#+(or x86 sparc)
|
|
233 |
+(defun xoroshiro-gen (state)
|
|
234 |
+ (declare (type (simple-array double-float (2)) state)
|
|
235 |
+ (optimize (speed 3) (safety 0)))
|
|
236 |
+ (vm::xoroshiro-next state))
|
|
237 |
+ |
|
238 |
+#-(or x86 sparc)
|
|
239 |
+(defun xoroshiro-gen (state)
|
|
240 |
+ (declare (type (simple-array double-float (2)) state)
|
|
241 |
+ (optimize (speed 3) (safety 0)))
|
|
242 |
+ ;; Portable implementation of the xoroshiro128+ generator. See
|
|
243 |
+ ;; http://xoroshiro.di.unimi.it/xoroshiro128plus.c for the
|
|
244 |
+ ;; definitive definition.
|
|
245 |
+ ;;
|
|
246 |
+ ;; uint64_t s[2];
|
|
247 |
+ ;;
|
|
248 |
+ ;; static inline uint64_t rotl(const uint64_t x, int k) {
|
|
249 |
+ ;; return (x << k) | (x >> (64 - k));
|
|
250 |
+ ;; }
|
|
251 |
+ ;;
|
|
252 |
+ ;; uint64_t next(void) {
|
|
253 |
+ ;; const uint64_t s0 = s[0];
|
|
254 |
+ ;; uint64_t s1 = s[1];
|
|
255 |
+ ;; const uint64_t result = s0 + s1;
|
|
256 |
+ ;;
|
|
257 |
+ ;; s1 ^= s0;
|
|
258 |
+ ;; s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
|
|
259 |
+ ;; s[1] = rotl(s1, 36); // c
|
|
260 |
+ ;;
|
|
261 |
+ ;; return result;
|
|
262 |
+ ;; }
|
|
263 |
+ ;;
|
|
264 |
+ (flet ((rotl-55 (x1 x0)
|
|
265 |
+ ;; Rotate [x1|x0] left 55 bits, returning the result as two
|
|
266 |
+ ;; values.
|
|
267 |
+ (declare (type (unsigned-byte 32) x0 x1)
|
|
268 |
+ (optimize (speed 3) (safety 0)))
|
|
269 |
+ ;; x << 55
|
|
270 |
+ (let ((sl55-h (ldb (byte 32 0) (ash x0 (- 55 32))))
|
|
271 |
+ (sl55-l 0))
|
|
272 |
+ ;; x >> 9
|
|
273 |
+ (let ((sr9-h (ash x1 -9))
|
|
274 |
+ (sr9-l (ldb (byte 32 0)
|
|
275 |
+ (logior (ash x0 -9)
|
|
276 |
+ (ash x1 23)))))
|
|
277 |
+ (values (logior sl55-h sr9-h)
|
|
278 |
+ (logior sl55-l sr9-l)))))
|
|
279 |
+ (rotl-36 (x1 x0)
|
|
280 |
+ ;; Rotate [x1|x0] left 36 bits, returning the result as two
|
|
281 |
+ ;; values.
|
|
282 |
+ (declare (type (unsigned-byte 32) x0 x1)
|
|
283 |
+ (optimize (speed 3) (safety 0)))
|
|
284 |
+ ;; x << 36
|
|
285 |
+ (let ((sl36-h (ldb (byte 32 0) (ash x0 4))))
|
|
286 |
+ ;; x >> 28
|
|
287 |
+ (let ((sr28-l (ldb (byte 32 0)
|
|
288 |
+ (logior (ash x0 -28)
|
|
289 |
+ (ash x1 4))))
|
|
290 |
+ (sr28-h (ash x1 -28)))
|
|
291 |
+ (values (logior sl36-h sr28-h)
|
|
292 |
+ sr28-l))))
|
|
293 |
+ (shl-14 (x1 x0)
|
|
294 |
+ ;; Shift [x1|x0] left by 14 bits, returning the result as
|
|
295 |
+ ;; two values.
|
|
296 |
+ (declare (type (unsigned-byte 32) x1 x0)
|
|
297 |
+ (optimize (speed 3) (safety 0)))
|
|
298 |
+ (values (ldb (byte 32 0)
|
|
299 |
+ (logior (ash x1 14)
|
|
300 |
+ (ash x0 (- 14 32))))
|
|
301 |
+ (ldb (byte 32 0)
|
|
302 |
+ (ash x0 14))))
|
|
303 |
+ (make-double (hi lo)
|
|
304 |
+ (kernel:make-double-float
|
|
305 |
+ (if (< hi #x80000000)
|
|
306 |
+ hi
|
|
307 |
+ (- hi #x100000000))
|
|
308 |
+ lo)))
|
|
309 |
+ (let ((s0-1 0)
|
|
310 |
+ (s0-0 0)
|
|
311 |
+ (s1-1 0)
|
|
312 |
+ (s1-0 0))
|
|
313 |
+ (declare (type (unsigned-byte 32) s0-1 s0-0 s1-1 s1-0))
|
|
314 |
+ ;; Load the state to s0 and s1. s0-1 is the high 32-bit part and
|
|
315 |
+ ;; s0-0 is the low 32-bit part of the 64-bit value. Similarly
|
|
316 |
+ ;; for s1.
|
|
317 |
+ (multiple-value-bind (x1 x0)
|
|
318 |
+ (kernel:double-float-bits (aref state 0))
|
|
319 |
+ (setf s0-1 (ldb (byte 32 0) x1)
|
|
320 |
+ s0-0 x0))
|
|
321 |
+ (multiple-value-bind (x1 x0)
|
|
322 |
+ (kernel:double-float-bits (aref state 1))
|
|
323 |
+ (setf s1-1 (ldb (byte 32 0) x1)
|
|
324 |
+ s1-0 x0))
|
|
325 |
+ |
|
326 |
+ ;; Compute the 64-bit random value: s0 + s1
|
|
327 |
+ (multiple-value-prog1
|
|
328 |
+ (multiple-value-bind (sum-0 c)
|
|
329 |
+ (bignum::%add-with-carry s0-0 s1-0 0)
|
|
330 |
+ (values (bignum::%add-with-carry s0-1 s1-1 c)
|
|
331 |
+ sum-0))
|
|
332 |
+ ;; s1 ^= s0
|
|
333 |
+ (setf s1-1 (logxor s1-1 s0-1)
|
|
334 |
+ s1-0 (logxor s1-0 s0-0))
|
|
335 |
+ ;; s[0] = rotl(s0,55) ^ s1 ^ (s1 << 14)
|
|
336 |
+ (multiple-value-setq (s0-1 s0-0)
|
|
337 |
+ (rotl-55 s0-1 s0-0))
|
|
338 |
+ (setf s0-1 (logxor s0-1 s1-1)
|
|
339 |
+ s0-0 (logxor s0-0 s1-0))
|
|
340 |
+ (multiple-value-bind (s14-1 s14-0)
|
|
341 |
+ (shl-14 s1-1 s1-0)
|
|
342 |
+ (setf s0-1 (logxor s0-1 s14-1)
|
|
343 |
+ s0-0 (logxor s0-0 s14-0)))
|
|
344 |
+ |
|
345 |
+ (multiple-value-bind (r1 r0)
|
|
346 |
+ (rotl-36 s1-1 s1-0)
|
|
347 |
+ (setf (aref state 0) (make-double s0-1 s0-0)
|
|
348 |
+ (aref state 1) (make-double r1 r0)))))))
|
|
349 |
+ |
|
350 |
+;;; Size of the chunks returned by random-chunk.
|
|
351 |
+;;;
|
|
352 |
+(defconstant random-chunk-length 32)
|
|
353 |
+ |
|
354 |
+;;; random-chunk -- Internal
|
|
355 |
+;;;
|
|
356 |
+;;; This function generaters a 32bit integer between 0 and #xffffffff
|
|
357 |
+;;; inclusive.
|
|
358 |
+;;;
|
|
359 |
+(declaim (inline random-chunk))
|
|
360 |
+ |
|
361 |
+(defun random-chunk (rng-state)
|
|
362 |
+ (declare (type random-state rng-state)
|
|
363 |
+ (optimize (speed 3) (safety 0)))
|
|
364 |
+ (let ((cached (random-state-cached-p rng-state)))
|
|
365 |
+ (cond (cached
|
|
366 |
+ (setf (random-state-cached-p rng-state) nil)
|
|
367 |
+ (random-state-rand rng-state))
|
|
368 |
+ (t
|
|
369 |
+ (let ((s (random-state-state rng-state)))
|
|
370 |
+ (declare (type (simple-array double-float (2)) s))
|
|
371 |
+ (multiple-value-bind (r1 r0)
|
|
372 |
+ (xoroshiro-gen s)
|
|
373 |
+ (setf (random-state-rand rng-state) r0)
|
|
374 |
+ (setf (random-state-cached-p rng-state) t)
|
|
375 |
+ r1))))))
|
|
376 |
+ |
|
377 |
+ |
|
378 |
+;;; %RANDOM-SINGLE-FLOAT, %RANDOM-DOUBLE-FLOAT -- Interface
|
|
379 |
+;;;
|
|
380 |
+;;; Handle the single or double float case of RANDOM. We generate a float
|
|
381 |
+;;; between 0.0 and 1.0 by clobbering the significand of 1.0 with random bits,
|
|
382 |
+;;; then subtracting 1.0. This hides the fact that we have a hidden bit.
|
|
383 |
+;;;
|
|
384 |
+(declaim (inline %random-single-float %random-double-float))
|
|
385 |
+(declaim (ftype (function ((single-float (0f0)) random-state)
|
|
386 |
+ (single-float 0f0))
|
|
387 |
+ %random-single-float))
|
|
388 |
+;;;
|
|
389 |
+(defun %random-single-float (arg state)
|
|
390 |
+ (declare (type (single-float (0f0)) arg)
|
|
391 |
+ (type random-state state))
|
|
392 |
+ (* arg
|
|
393 |
+ (- (make-single-float
|
|
394 |
+ (dpb (ash (random-chunk state)
|
|
395 |
+ (- vm:single-float-digits random-chunk-length))
|
|
396 |
+ vm:single-float-significand-byte
|
|
397 |
+ (single-float-bits 1.0)))
|
|
398 |
+ 1.0)))
|
|
399 |
+;;;
|
|
400 |
+(declaim (ftype (function ((double-float (0d0)) random-state)
|
|
401 |
+ (double-float 0d0))
|
|
402 |
+ %random-double-float))
|
|
403 |
+;;;
|
|
404 |
+;;; 53-bit version.
|
|
405 |
+;;;
|
|
406 |
+(defun %random-double-float (arg state)
|
|
407 |
+ (declare (type (double-float (0d0)) arg)
|
|
408 |
+ (type random-state state))
|
|
409 |
+ ;; xoroshiro-gen produces 64-bit values. Should we use that
|
|
410 |
+ ;; directly to get the random bits instead of two calls to
|
|
411 |
+ ;; RANDOM-CHUNK?
|
|
412 |
+ (* arg
|
|
413 |
+ (- (lisp::make-double-float
|
|
414 |
+ (dpb (ash (random-chunk state)
|
|
415 |
+ (- vm:double-float-digits random-chunk-length
|
|
416 |
+ vm:word-bits))
|
|
417 |
+ vm:double-float-significand-byte
|
|
418 |
+ (lisp::double-float-high-bits 1d0))
|
|
419 |
+ (random-chunk state))
|
|
420 |
+ 1d0)))
|
|
421 |
+ |
|
422 |
+#+double-double
|
|
423 |
+(defun %random-double-double-float (arg state)
|
|
424 |
+ (declare (type (double-double-float (0w0)) arg)
|
|
425 |
+ (type random-state state))
|
|
426 |
+ ;; Generate a 31-bit integer, scale it and sum them up
|
|
427 |
+ (let* ((r 0w0)
|
|
428 |
+ (scale (scale-float 1d0 -31))
|
|
429 |
+ (mult scale))
|
|
430 |
+ (declare (double-float mult)
|
|
431 |
+ (type double-double-float r)
|
|
432 |
+ (optimize (speed 3) (inhibit-warnings 3)))
|
|
433 |
+ (dotimes (k 4)
|
|
434 |
+ (setf r (+ r (* mult (ldb (byte 31 0) (random-chunk state)))))
|
|
435 |
+ (setf mult (* mult scale)))
|
|
436 |
+ (* arg r)))
|
|
437 |
+ |
|
438 |
+;;;; Random integers:
|
|
439 |
+ |
|
440 |
+;;; Amount we overlap chunks by when building a large integer to make up for
|
|
441 |
+;;; the loss of randomness in the low bits.
|
|
442 |
+;;;
|
|
443 |
+(defconstant random-integer-overlap 3)
|
|
444 |
+ |
|
445 |
+;;; Extra bits of randomness that we generate before taking the value MOD the
|
|
446 |
+;;; limit, to avoid loss of randomness near the limit.
|
|
447 |
+;;;
|
|
448 |
+(defconstant random-integer-extra-bits 10)
|
|
449 |
+ |
|
450 |
+;;; Largest fixnum we can compute from one chunk of bits.
|
|
451 |
+;;;
|
|
452 |
+(defconstant random-fixnum-max
|
|
453 |
+ (1- (ash 1 (- random-chunk-length random-integer-extra-bits))))
|
|
454 |
+ |
|
455 |
+ |
|
456 |
+;;; %RANDOM-INTEGER -- Internal
|
|
457 |
+;;;
|
|
458 |
+(defun %random-integer (arg state)
|
|
459 |
+ (declare (type (integer 1) arg)
|
|
460 |
+ (type random-state state))
|
|
461 |
+ (let ((shift (- random-chunk-length random-integer-overlap)))
|
|
462 |
+ (do ((bits (random-chunk state)
|
|
463 |
+ (logxor (ash bits shift) (random-chunk state)))
|
|
464 |
+ (count (+ (integer-length arg)
|
|
465 |
+ (- random-integer-extra-bits shift))
|
|
466 |
+ (- count shift)))
|
|
467 |
+ ((minusp count)
|
|
468 |
+ (rem bits arg))
|
|
469 |
+ (declare (fixnum count)))))
|
|
470 |
+ |
|
471 |
+(defun random (arg &optional (state *random-state*))
|
|
472 |
+ _N"Generate a uniformly distributed pseudo-random number between zero
|
|
473 |
+ and Arg. State, if supplied, is the random state to use."
|
|
474 |
+ (declare (inline %random-single-float %random-double-float))
|
|
475 |
+ (cond
|
|
476 |
+ ((typep arg '(integer 1 #x100000000))
|
|
477 |
+ ;; Let the compiler deftransform take care of this case.
|
|
478 |
+ (%random-integer arg state))
|
|
479 |
+ ((and (typep arg 'single-float) (> arg 0.0F0))
|
|
480 |
+ (%random-single-float arg state))
|
|
481 |
+ ((and (typep arg 'double-float) (> arg 0.0D0))
|
|
482 |
+ (%random-double-float arg state))
|
|
483 |
+ #+double-double
|
|
484 |
+ ((and (typep arg 'double-double-float) (> arg 0.0w0))
|
|
485 |
+ (%random-double-double-float arg state))
|
|
486 |
+ ((and (integerp arg) (> arg 0))
|
|
487 |
+ (%random-integer arg state))
|
|
488 |
+ (t
|
|
489 |
+ (error 'simple-type-error
|
|
490 |
+ :expected-type '(or (integer 1) (float (0.0))) :datum arg
|
|
491 |
+ :format-control _"Argument is not a positive integer or a positive float: ~S")
|
|
492 |
+ :format-arguments (list arg)))))
|
|
493 |
+ |
|
494 |
+;; Jump function for the generator. See the jump function in
|
|
495 |
+;; http://xoroshiro.di.unimi.it/xoroshiro128plus.c
|
|
496 |
+(defun random-state-jump (&optional (rng-state *random-state*))
|
|
497 |
+ _N"Jump the RNG-STATE. This is equivalent to 2^64 calls to the
|
|
498 |
+ xoroshiro128+ generator. It can be used to generate 2^64
|
|
499 |
+ non-overlapping subsequences for parallel computations."
|
|
500 |
+ (declare (type random-state rng-state))
|
|
501 |
+ (let ((state (random-state-state rng-state))
|
|
502 |
+ (s0-0 0)
|
|
503 |
+ (s0-1 0)
|
|
504 |
+ (s1-0 0)
|
|
505 |
+ (s1-1 0))
|
|
506 |
+ (declare (type (unsigned-byte 32) s0-0 s0-1 s1-0 s1-1)
|
|
507 |
+ (optimize (speed 3) (safety 0)))
|
|
508 |
+ ;; The constants are #xbeac0467eba5facb and #xd86b048b86aa9922,
|
|
509 |
+ ;; and we process these numbers starting from the LSB. We want ot
|
|
510 |
+ ;; process these in 32-bit chunks, so word-reverse the constants.
|
|
511 |
+ (dolist (jump '(#xeba5facb #xbeac0467 #x86aa9922 #xd86b048b))
|
|
512 |
+ (declare (type (unsigned-byte 32) jump))
|
|
513 |
+ (dotimes (b 32)
|
|
514 |
+ (declare (fixnum b))
|
|
515 |
+ (when (logbitp b jump)
|
|
516 |
+ (multiple-value-bind (x1 x0)
|
|
517 |
+ (kernel:double-float-bits (aref state 0))
|
|
518 |
+ (setf s0-1 (logxor s0-1 (ldb (byte 32 0) x1))
|
|
519 |
+ s0-0 (logxor s0-0 x0)))
|
|
520 |
+
|
|
521 |
+ (multiple-value-bind (x1 x0)
|
|
522 |
+ (kernel:double-float-bits (aref state 1))
|
|
523 |
+ (setf s1-1 (logxor s1-1 (ldb (byte 32 0) x1))
|
|
524 |
+ s1-0 (logxor s1-0 x0))))
|
|
525 |
+ (xoroshiro-gen state)))
|
|
526 |
+ |
|
527 |
+ (flet ((convert (x1 x0)
|
|
528 |
+ (declare (type (unsigned-byte 32) x1 x0))
|
|
529 |
+ (kernel:make-double-float
|
|
530 |
+ (if (< x1 #x80000000) x1 (- x1 #x100000000))
|
|
531 |
+ x0)))
|
|
532 |
+ (setf (aref state 0) (convert s0-1 s0-0))
|
|
533 |
+ (setf (aref state 1) (convert s1-1 s1-0)))
|
|
534 |
+ rng-state))
|
... | ... | @@ -413,6 +413,7 @@ |
413 | 413 |
;;; transformed to a call to this routine allowing its use in byte
|
414 | 414 |
;;; compiled code.
|
415 | 415 |
;;;
|
416 |
+#+random-mt19937
|
|
416 | 417 |
(defun random-mt19937 (state)
|
417 | 418 |
(declare (type (simple-array (unsigned-byte 32) (627)) state))
|
418 | 419 |
(random-mt19937 state))
|
... | ... | @@ -236,7 +236,7 @@ |
236 | 236 |
(frob %random-single-float single-float)
|
237 | 237 |
(frob %random-double-float double-float))
|
238 | 238 |
|
239 |
-#-(or new-random random-mt19937)
|
|
239 |
+#-(or new-random random-mt19937 rand-xoroshiro)
|
|
240 | 240 |
(deftransform random ((num &optional state)
|
241 | 241 |
((integer 1 #.random-fixnum-max) &optional *))
|
242 | 242 |
_N"use inline fixnum operations"
|
... | ... | @@ -259,7 +259,7 @@ |
259 | 259 |
'(values (truncate (%random-double-float (coerce num 'double-float)
|
260 | 260 |
(or state *random-state*)))))
|
261 | 261 |
|
262 |
-#+random-mt19937
|
|
262 |
+#+(or random-mt19937)
|
|
263 | 263 |
(deftransform random ((num &optional state)
|
264 | 264 |
((integer 1 #.(expt 2 32)) &optional *))
|
265 | 265 |
_N"use inline (unsigned-byte 32) operations"
|
... | ... | @@ -2588,3 +2588,60 @@ |
2588 | 2588 |
(unsigned-byte 32))
|
2589 | 2589 |
"recode as shifts and adds"
|
2590 | 2590 |
(*-transformer y))
|
2591 |
+ |
|
2592 |
+(in-package "VM")
|
|
2593 |
+ |
|
2594 |
+#+random-xoroshiro
|
|
2595 |
+(progn
|
|
2596 |
+(defknown xoroshiro-next ((simple-array double-float (2)))
|
|
2597 |
+ (values (unsigned-byte 32) (unsigned-byte 32))
|
|
2598 |
+ (movable))
|
|
2599 |
+ |
|
2600 |
+(define-vop (xoroshiro-next)
|
|
2601 |
+ (:policy :fast-safe)
|
|
2602 |
+ (:translate xoroshiro-next)
|
|
2603 |
+ (:args (state :scs (descriptor-reg) :to (:result 3)))
|
|
2604 |
+ (:arg-types simple-array-double-float)
|
|
2605 |
+ (:results (r1 :scs (unsigned-reg))
|
|
2606 |
+ (r0 :scs (unsigned-reg)))
|
|
2607 |
+ (:result-types unsigned-num unsigned-num)
|
|
2608 |
+ ;; Must be sure to use %o registers for temps because we want to use
|
|
2609 |
+ ;; 64-bit registers that will get preserved.
|
|
2610 |
+ (:temporary (:sc unsigned-reg :offset nl5-offset) s0)
|
|
2611 |
+ (:temporary (:sc unsigned-reg :offset nl4-offset) s1)
|
|
2612 |
+ (:temporary (:sc unsigned-reg :offset nl3-offset) t0)
|
|
2613 |
+ (:generator 10
|
|
2614 |
+ (let ((s0-offset (+ (* 0 double-float-bytes)
|
|
2615 |
+ (- (* vm:vector-data-offset vm:word-bytes)
|
|
2616 |
+ vm:other-pointer-type)))
|
|
2617 |
+ (s1-offset (+ (* 1 double-float-bytes)
|
|
2618 |
+ (- (* vm:vector-data-offset vm:word-bytes)
|
|
2619 |
+ vm:other-pointer-type))))
|
|
2620 |
+ (inst ldx s0 state s0-offset)
|
|
2621 |
+ (inst ldx s1 state s1-offset)
|
|
2622 |
+ ;; result = s0 + s1, split into low 32-bits in r0 and high 32-bits
|
|
2623 |
+ ;; in r1
|
|
2624 |
+ (inst add r0 s0 s1)
|
|
2625 |
+ (inst srlx r1 r0 32)
|
|
2626 |
+ |
|
2627 |
+ ;; s1 = s1 ^ s0
|
|
2628 |
+ (inst xor s1 s0)
|
|
2629 |
+ |
|
2630 |
+ ;; s0 = rotl(s0,55) = s0 << 55 | s0 >> 9
|
|
2631 |
+ (inst sllx t0 s0 55)
|
|
2632 |
+ (inst srlx s0 s0 9)
|
|
2633 |
+ (inst or s0 t0)
|
|
2634 |
+ |
|
2635 |
+ (inst xor s0 s1) ; s0 = s0 ^ s1
|
|
2636 |
+ (inst sllx t0 s1 14) ; t0 = s1 << 14
|
|
2637 |
+ (inst xor s0 t0) ; s0 = s0 ^ t0
|
|
2638 |
+ |
|
2639 |
+ (inst stx s0 state s0-offset)
|
|
2640 |
+ |
|
2641 |
+ ;; s1 = rotl(s1, 36) = s1 << 36 | s1 >> 28, using t0 as temp
|
|
2642 |
+ (inst sllx t0 s1 36)
|
|
2643 |
+ (inst srlx s1 28)
|
|
2644 |
+ (inst or s1 t0)
|
|
2645 |
+ |
|
2646 |
+ (inst stx s1 state s1-offset))))
|
|
2647 |
+)
|
... | ... | @@ -1833,3 +1833,78 @@ |
1833 | 1833 |
(vm::ash-right-unsigned num (- shift)))))
|
1834 | 1834 |
(t
|
1835 | 1835 |
(give-up)))))
|
1836 |
+ |
|
1837 |
+(in-package "VM")
|
|
1838 |
+ |
|
1839 |
+#+random-xoroshiro
|
|
1840 |
+(progn
|
|
1841 |
+(defknown xoroshiro-next ((simple-array double-float (2)))
|
|
1842 |
+ (values (unsigned-byte 32) (unsigned-byte 32))
|
|
1843 |
+ (movable))
|
|
1844 |
+ |
|
1845 |
+(define-vop (xoroshiro-next)
|
|
1846 |
+ (:policy :fast-safe)
|
|
1847 |
+ (:translate xoroshiro-next)
|
|
1848 |
+ (:args (state :scs (descriptor-reg) :to (:result 3)))
|
|
1849 |
+ (:arg-types simple-array-double-float)
|
|
1850 |
+ (:results (r1 :scs (unsigned-reg))
|
|
1851 |
+ (r0 :scs (unsigned-reg)))
|
|
1852 |
+ (:result-types unsigned-num unsigned-num)
|
|
1853 |
+ (:temporary (:sc double-reg) s0)
|
|
1854 |
+ (:temporary (:sc double-reg) s1)
|
|
1855 |
+ (:temporary (:sc double-reg) t0)
|
|
1856 |
+ (:generator 10
|
|
1857 |
+ ;; s0 = state[0]
|
|
1858 |
+ (inst movsd s0 (make-ea :dword :base state
|
|
1859 |
+ :disp (- (+ (* vm:vector-data-offset
|
|
1860 |
+ vm:word-bytes)
|
|
1861 |
+ (* 8 0))
|
|
1862 |
+ vm:other-pointer-type)))
|
|
1863 |
+ ;; s1 = state[1]
|
|
1864 |
+ (inst movsd s1 (make-ea :dword :base state
|
|
1865 |
+ :disp (- (+ (* vm:vector-data-offset
|
|
1866 |
+ vm:word-bytes)
|
|
1867 |
+ (* 8 1))
|
|
1868 |
+ vm:other-pointer-type)))
|
|
1869 |
+ ;; Compute result = s0 + s1
|
|
1870 |
+ (inst movapd t0 s0)
|
|
1871 |
+ (inst paddq t0 s1)
|
|
1872 |
+ ;; Save the 64-bit result as two 32-bit results
|
|
1873 |
+ (inst movd r0 t0)
|
|
1874 |
+ (inst psrlq t0 32)
|
|
1875 |
+ (inst movd r1 t0)
|
|
1876 |
+ |
|
1877 |
+ ;; s1 = s1 ^ s0
|
|
1878 |
+ (inst xorpd s1 s0)
|
|
1879 |
+ |
|
1880 |
+ ;; s0 = rotl(s0,55) = s0 << 55 | s0 >> 9
|
|
1881 |
+ (inst movapd t0 s0)
|
|
1882 |
+ (inst psllq s0 55) ; s0 = s0 << 55
|
|
1883 |
+ (inst psrlq t0 9) ; t0 = s0 >> 9
|
|
1884 |
+ (inst orpd s0 t0) ; s0 = rotl(s0, 55)
|
|
1885 |
+ |
|
1886 |
+ (inst movapd t0 s1)
|
|
1887 |
+ (inst xorpd s0 s1) ; s0 = s0 ^ s1
|
|
1888 |
+ (inst psllq t0 14) ; t0 = s1 << 14
|
|
1889 |
+ (inst xorpd s0 t0) ; s0 = s0 ^ t0
|
|
1890 |
+ (inst movsd (make-ea :dword :base state
|
|
1891 |
+ :disp (- (+ (* vm:vector-data-offset
|
|
1892 |
+ vm:word-bytes)
|
|
1893 |
+ (* 8 0))
|
|
1894 |
+ vm:other-pointer-type))
|
|
1895 |
+ s0)
|
|
1896 |
+ |
|
1897 |
+ ;; s1 = rotl(s1, 36) = s1 << 36 | s1 >> 28, using t0 as temp
|
|
1898 |
+ (inst movapd t0 s1)
|
|
1899 |
+ (inst psllq s1 36)
|
|
1900 |
+ (inst psrlq t0 28)
|
|
1901 |
+ (inst orpd s1 t0)
|
|
1902 |
+ |
|
1903 |
+ (inst movsd (make-ea :dword :base state
|
|
1904 |
+ :disp (- (+ (* vm:vector-data-offset
|
|
1905 |
+ vm:word-bytes)
|
|
1906 |
+ (* 8 1))
|
|
1907 |
+ vm:other-pointer-type))
|
|
1908 |
+ s1)))
|
|
1909 |
+)
|
|
1910 |
+
|
|
\ No newline at end of file |
... | ... | @@ -3195,7 +3195,11 @@ |
3195 | 3195 |
;; dst[63:0] = dst[63:0]
|
3196 | 3196 |
;; dst[127:64] = src[63:0]
|
3197 | 3197 |
(define-regular-sse-inst unpcklpd #x66 #x14 t)
|
3198 |
- (define-regular-sse-inst unpcklps nil #x14 t))
|
|
3198 |
+ (define-regular-sse-inst unpcklps nil #x14 t)
|
|
3199 |
+ |
|
3200 |
+ ;; PADDQ 64-bit integer add
|
|
3201 |
+ (define-regular-sse-inst paddq #x66 #xd4)
|
|
3202 |
+ )
|
|
3199 | 3203 |
|
3200 | 3204 |
(define-instruction popcnt (segment dst src)
|
3201 | 3205 |
(:printer ext-reg-reg/mem
|
... | ... | @@ -3539,4 +3543,3 @@ |
3539 | 3543 |
(packed-shift psllw #x71 #xf1 6)
|
3540 | 3544 |
(packed-shift psrad #x72 #xe2 4)
|
3541 | 3545 |
(packed-shift psraw #x71 #xe1 4))
|
3542 |
- |
... | ... | @@ -21,6 +21,11 @@ public domain. |
21 | 21 |
* Feature enhancements
|
22 | 22 |
* Update to ASDF 3.3.1, fixing issues introduced in 3.3.0
|
23 | 23 |
* Changes
|
24 |
+ * x86 and sparc have replaced the MT19937 RNG with xoroshiro128+ RNG.
|
|
25 |
+ * The required state for this generator is just 4 32-bit words instead of the 600+ for MT19937.
|
|
26 |
+ * The generator is also faster than MT19937 (approximately 28% faster on x86 and 18% on sparc).
|
|
27 |
+ * The new function `KERNEL:RANDOM-STATE-JUMP` modifies the given state to jump 2^64 samples ahead, allowing 2^64 non-overlapping sequences.
|
|
28 |
+ |
|
24 | 29 |
* ANSI compliance fixes:
|
25 | 30 |
* Bug fixes:
|
26 | 31 |
* Gitlab tickets:
|
... | ... | @@ -33,7 +33,7 @@ msgstr "" |
33 | 33 |
#: src/code/intl.lisp src/compiler/globaldb.lisp src/code/defstruct.lisp
|
34 | 34 |
#: src/code/remote.lisp src/code/wire.lisp src/code/internet.lisp
|
35 | 35 |
#: src/code/loop.lisp src/code/run-program.lisp src/code/parse-time.lisp
|
36 |
-#: src/code/profile.lisp src/code/ntrace.lisp src/code/rand-mt19937.lisp
|
|
36 |
+#: src/code/profile.lisp src/code/ntrace.lisp src/code/rand-xoroshiro.lisp
|
|
37 | 37 |
#: src/code/debug.lisp src/code/debug-int.lisp src/code/debug-info.lisp
|
38 | 38 |
#: src/code/eval.lisp src/code/filesys.lisp src/code/pathname.lisp
|
39 | 39 |
#: src/code/fd-stream.lisp src/code/extfmts.lisp src/code/serve-event.lisp
|
... | ... | @@ -12105,13 +12105,13 @@ msgstr "" |
12105 | 12105 |
msgid "Type \"yes\" for yes or \"no\" for no. "
|
12106 | 12106 |
msgstr ""
|
12107 | 12107 |
|
12108 |
-#: src/code/rand-mt19937.lisp
|
|
12108 |
+#: src/code/rand-xoroshiro.lisp
|
|
12109 | 12109 |
msgid ""
|
12110 | 12110 |
"Generate an random state vector from the given SEED. The seed can be\n"
|
12111 |
-" either an integer or a vector of (unsigned-byte 32)"
|
|
12111 |
+" either an integer or a vector of (unsigned-byte 64)"
|
|
12112 | 12112 |
msgstr ""
|
12113 | 12113 |
|
12114 |
-#: src/code/rand-mt19937.lisp
|
|
12114 |
+#: src/code/rand-xoroshiro.lisp
|
|
12115 | 12115 |
msgid ""
|
12116 | 12116 |
"Make a random state object. If STATE is not supplied, return a copy\n"
|
12117 | 12117 |
" of the default random state. If STATE is a random state, then return a\n"
|
... | ... | @@ -12119,20 +12119,27 @@ msgid "" |
12119 | 12119 |
" the universal time or /dev/urandom if available."
|
12120 | 12120 |
msgstr ""
|
12121 | 12121 |
|
12122 |
-#: src/code/rand-mt19937.lisp
|
|
12123 |
-msgid "Argument is not a RANDOM-STATE, T or NIL: ~S"
|
|
12122 |
+#: src/code/rand-xoroshiro.lisp
|
|
12123 |
+msgid "Argument is not a RANDOM-STATE, T, or NIL: ~S"
|
|
12124 | 12124 |
msgstr ""
|
12125 | 12125 |
|
12126 |
-#: src/code/rand-mt19937.lisp
|
|
12126 |
+#: src/code/rand-xoroshiro.lisp
|
|
12127 | 12127 |
msgid ""
|
12128 | 12128 |
"Generate a uniformly distributed pseudo-random number between zero\n"
|
12129 | 12129 |
" and Arg. State, if supplied, is the random state to use."
|
12130 | 12130 |
msgstr ""
|
12131 | 12131 |
|
12132 |
-#: src/code/rand-mt19937.lisp
|
|
12132 |
+#: src/code/rand-xoroshiro.lisp
|
|
12133 | 12133 |
msgid "Argument is not a positive integer or a positive float: ~S"
|
12134 | 12134 |
msgstr ""
|
12135 | 12135 |
|
12136 |
+#: src/code/rand-xoroshiro.lisp
|
|
12137 |
+msgid ""
|
|
12138 |
+"Jump the RNG-STATE. This is equivalent to 2^64 calls to the\n"
|
|
12139 |
+" xoroshiro128+ generator. It can be used to generate 2^64\n"
|
|
12140 |
+" non-overlapping subsequences for parallel computations."
|
|
12141 |
+msgstr ""
|
|
12142 |
+ |
|
12136 | 12143 |
#: src/code/ntrace.lisp
|
12137 | 12144 |
msgid ""
|
12138 | 12145 |
"This is bound to the returned values when evaluating :BREAK-AFTER and\n"
|
... | ... | @@ -18869,10 +18876,6 @@ msgid "use inline (unsigned-byte 32) operations" |
18869 | 18876 |
msgstr ""
|
18870 | 18877 |
|
18871 | 18878 |
#: src/compiler/float-tran.lisp
|
18872 |
-msgid "Shouldn't happen"
|
|
18873 |
-msgstr ""
|
|
18874 |
- |
|
18875 |
-#: src/compiler/float-tran.lisp
|
|
18876 | 18879 |
msgid "Can't open-code float to rational comparison."
|
18877 | 18880 |
msgstr ""
|
18878 | 18881 |
|
... | ... | @@ -121,9 +121,13 @@ |
121 | 121 |
"target:code/scavhook"
|
122 | 122 |
|
123 | 123 |
"target:code/save"
|
124 |
- ,@(if (c:backend-featurep :random-mt19937)
|
|
125 |
- '("target:code/rand-mt19937")
|
|
126 |
- '("target:code/rand"))
|
|
124 |
+ ,@(cond ((c:backend-featurep :random-mt19937)
|
|
125 |
+ '("target:code/rand-mt19937"))
|
|
126 |
+ ((c:backend-featurep :random-xoroshiro)
|
|
127 |
+ '("target:code/rand-xoroshiro"))
|
|
128 |
+ (t
|
|
129 |
+ '("target:code/rand")))
|
|
130 |
+ "target:code/rand-xoroshiro"
|
|
127 | 131 |
"target:code/alieneval"
|
128 | 132 |
"target:code/c-call"
|
129 | 133 |
"target:code/sap"
|
... | ... | @@ -268,9 +268,12 @@ |
268 | 268 |
(comf "target:code/debug" :byte-compile t)
|
269 | 269 |
|
270 | 270 |
(comf "target:code/query" :byte-compile *byte-compile*)
|
271 |
-(if (c:backend-featurep :random-mt19937)
|
|
272 |
- (comf "target:code/rand-mt19937")
|
|
273 |
- (comf "target:code/rand"))
|
|
271 |
+(cond ((c:backend-featurep :random-mt19937)
|
|
272 |
+ (comf "target:code/rand-mt19937"))
|
|
273 |
+ ((c:backend-featurep :random-xoroshiro)
|
|
274 |
+ (comf "target:code/rand-xoroshiro"))
|
|
275 |
+ (t
|
|
276 |
+ (comf "target:code/rand")))
|
|
274 | 277 |
(comf "target:code/ntrace" :byte-compile *byte-compile*)
|
275 | 278 |
(comf "target:code/profile")
|
276 | 279 |
(comf "target:code/sort")
|
... | ... | @@ -96,8 +96,13 @@ |
96 | 96 |
(maybe-byte-load "code:time")
|
97 | 97 |
(maybe-byte-load "code:tty-inspect")
|
98 | 98 |
(maybe-byte-load "code:describe")
|
99 |
-#+random-mt19937 (maybe-byte-load "code:rand-mt19937")
|
|
100 |
-#-random-mt19937 (maybe-byte-load "code:rand")
|
|
99 |
+#+random-mt19937
|
|
100 |
+(maybe-byte-load "code:rand-mt19937")
|
|
101 |
+#+random-xoroshiro
|
|
102 |
+(maybe-byte-load "code:rand-xoroshiro")
|
|
103 |
+#-(or random-mt19937 random-xoroshiro)
|
|
104 |
+(maybe-byte-load "code:rand")
|
|
105 |
+(maybe-byte-load "code:rand-xoroshiro")
|
|
101 | 106 |
(maybe-byte-load "target:pcl/walk")
|
102 | 107 |
(maybe-byte-load "code:fwrappers")
|
103 | 108 |
(maybe-byte-load "code:ntrace")
|
1 |
+;; Tests for RNG
|
|
2 |
+ |
|
3 |
+(defpackage :rng-tests
|
|
4 |
+ (:use :cl :lisp-unit))
|
|
5 |
+ |
|
6 |
+(in-package "RNG-TESTS")
|
|
7 |
+ |
|
8 |
+(defun 64-bit-rng-state (rng)
|
|
9 |
+ (let ((state (kernel::random-state-state rng)))
|
|
10 |
+ (flet ((convert (x)
|
|
11 |
+ (multiple-value-bind (hi lo)
|
|
12 |
+ (kernel:double-float-bits x)
|
|
13 |
+ (logior (ash (ldb (byte 32 0) hi) 32)
|
|
14 |
+ lo))))
|
|
15 |
+ (values (convert (aref state 0)) (convert (aref state 1))))))
|
|
16 |
+ |
|
17 |
+(defun 64-bit-value (rng)
|
|
18 |
+ (logior (ash (kernel::random-chunk rng) 32)
|
|
19 |
+ (kernel::random-chunk rng)))
|
|
20 |
+ |
|
21 |
+(defvar *test-state*)
|
|
22 |
+
|
|
23 |
+#+random-xoroshiro
|
|
24 |
+(define-test rng.initial-state
|
|
25 |
+ (setf *test-state*
|
|
26 |
+ (kernel::make-random-object :state (kernel::init-random-state #x12345678)
|
|
27 |
+ :rand 0
|
|
28 |
+ :cached-p nil))
|
|
29 |
+ (multiple-value-bind (s0 s1)
|
|
30 |
+ (64-bit-rng-state *test-state*)
|
|
31 |
+ (assert-equal #x38f1dc39d1906b6f s0)
|
|
32 |
+ (assert-equal #xdfe4142236dd9517 s1)
|
|
33 |
+ (assert-equal 0 (kernel::random-state-rand *test-state*))
|
|
34 |
+ (assert-equal nil (kernel::random-state-cached-p *test-state*))))
|
|
35 |
+ |
|
36 |
+ |
|
37 |
+#+random-xoroshiro
|
|
38 |
+(define-test rng.values-test
|
|
39 |
+ (assert-equal (list #x38f1dc39d1906b6f #xdfe4142236dd9517)
|
|
40 |
+ (multiple-value-list (64-bit-rng-state *test-state*)))
|
|
41 |
+ (assert-equal 0 (kernel::random-state-rand *test-state*))
|
|
42 |
+ (assert-equal nil (kernel::random-state-cached-p *test-state*))
|
|
43 |
+ |
|
44 |
+ (dolist (item '((#x18d5f05c086e0086 (#x228f4926843b364d #x74dfe78e715c81be))
|
|
45 |
+ (#x976f30b4f597b80b (#x5b6bd4558bd96a68 #x567b7f35650aea8f))
|
|
46 |
+ (#xb1e7538af0e454f7 (#x13e5253e242fac52 #xed380e70d10ab60e))
|
|
47 |
+ (#x011d33aef53a6260 (#x9d0764952ca00d8a #x5251a5cfedd2b4ef))
|
|
48 |
+ (#xef590a651a72c279 (#xba4ef2b425bda963 #x172b965cf56c15ac))
|
|
49 |
+ (#xd17a89111b29bf0f (#x458277a5e5f0a21b #xd1bccfad6564e8d))
|
|
50 |
+ (#x529e44a0bc46f0a8 (#x2becb68d5a7194c7 #x3a6ec964899bb5f3))
|
|
51 |
+ (#x665b7ff1e40d4aba (#xededfd481d0a19fe #x3ea213411827fe9d))
|
|
52 |
+ (#x2c9010893532189b (#xd7bb59bcd8fba26f #x52de763d34fee090))
|
|
53 |
+ (#x2a99cffa0dfa82ff (#xf96e892c62d6ff2e #xc0542ff85652f81e))))
|
|
54 |
+ (destructuring-bind (value state)
|
|
55 |
+ item
|
|
56 |
+ (assert-equal value (64-bit-value *test-state*))
|
|
57 |
+ (assert-equal state (multiple-value-list (64-bit-rng-state *test-state*))))))
|
|
58 |
+ |
|
59 |
+(define-test rng.jump
|
|
60 |
+ (setf *test-state*
|
|
61 |
+ (kernel::make-random-object :state (kernel::init-random-state #x12345678)
|
|
62 |
+ :rand 0
|
|
63 |
+ :cached-p nil))
|
|
64 |
+ (dolist (result '((#x291ddf8e6f6a7b67 #x1f9018a12f9e031f)
|
|
65 |
+ (#x88a7aa12158558d0 #xe264d785ab1472d9)
|
|
66 |
+ (#x207e16f73c51e7ba #x999c8a0a9a8d87c0)
|
|
67 |
+ (#x28f8959d3bcf5ff1 #x38091e563ab6eb98)))
|
|
68 |
+ (kernel:random-state-jump *test-state*)
|
|
69 |
+ (assert-equal result (multiple-value-list
|
|
70 |
+ (64-bit-rng-state *test-state*)))))
|