]> gitweb.factorcode.org Git - factor.git/blob - basis/math/vectors/simd/simd-tests.factor
math.vectors.simd.cords: implement new-sequence and like methods on cords to make...
[factor.git] / basis / math / vectors / simd / simd-tests.factor
1 USING: accessors arrays classes compiler.test compiler.tree.debugger
2 effects fry io kernel kernel.private math math.functions
3 math.private math.vectors math.vectors.simd
4 math.vectors.simd.private prettyprint random sequences system
5 tools.test vocabs assocs compiler.cfg.debugger words
6 locals combinators cpu.architecture namespaces byte-arrays alien
7 specialized-arrays classes.struct eval classes.algebra sets
8 quotations math.constants compiler.units splitting math.matrices
9 math.vectors.simd.cords ;
10 FROM: math.vectors.simd.intrinsics => alien-vector set-alien-vector ;
11 QUALIFIED-WITH: alien.c-types c
12 SPECIALIZED-ARRAY: c:float
13 IN: math.vectors.simd.tests
14
15 ! Test type propagation
16 [ V{ float } ] [ [ { float-4 } declare norm-sq ] final-classes ] unit-test
17
18 [ V{ float } ] [ [ { float-4 } declare norm ] final-classes ] unit-test
19
20 [ V{ float-4 } ] [ [ { float-4 } declare normalize ] final-classes ] unit-test
21
22 [ V{ float-4 } ] [ [ { float-4 float-4 } declare v+ ] final-classes ] unit-test
23
24 [ V{ float } ] [ [ { float-4 } declare second ] final-classes ] unit-test
25
26 [ V{ int-4 } ] [ [ { int-4 int-4 } declare v+ ] final-classes ] unit-test
27
28 [ t ] [ [ { int-4 } declare second ] final-classes first integer class<= ] unit-test
29
30 [ V{ longlong-2 } ] [ [ { longlong-2 longlong-2 } declare v+ ] final-classes ] unit-test
31
32 [ V{ integer } ] [ [ { longlong-2 } declare second ] final-classes ] unit-test
33
34 ! Test puns; only on x86
35 cpu x86? [
36     [ double-2{ 4 1024 } ] [
37         float-4{ 0 1 0 2 }
38         [ { float-4 } declare dup v+ underlying>> double-2 boa dup v+ ] compile-call
39     ] unit-test
40 ] when
41
42 ! Fuzz testing
43 CONSTANT: simd-classes
44     {
45         char-16
46         uchar-16
47         short-8
48         ushort-8
49         int-4
50         uint-4
51         longlong-2
52         ulonglong-2
53         float-4
54         double-2
55     }
56
57 SYMBOLS: -> +vector+ +any-vector+ +scalar+ +boolean+ +nonnegative+ +literal+ ;
58
59 CONSTANT: vector-words
60     H{
61         { [v-] { +vector+ +vector+ -> +vector+ } }
62         { distance { +vector+ +vector+ -> +nonnegative+ } }
63         { n*v { +scalar+ +vector+ -> +vector+ } }
64         { n+v { +scalar+ +vector+ -> +vector+ } }
65         { n-v { +scalar+ +vector+ -> +vector+ } }
66         { n/v { +scalar+ +vector+ -> +vector+ } }
67         { norm { +vector+ -> +nonnegative+ } }
68         { norm-sq { +vector+ -> +nonnegative+ } }
69         { normalize { +vector+ -> +vector+ } }
70         { v* { +vector+ +vector+ -> +vector+ } }
71         { vs* { +vector+ +vector+ -> +vector+ } }
72         { v*n { +vector+ +scalar+ -> +vector+ } }
73         { v*high { +vector+ +vector+ -> +vector+ } }
74         { v*hs+ { +vector+ +vector+ -> +vector+ } }
75         { v+ { +vector+ +vector+ -> +vector+ } }
76         { vs+ { +vector+ +vector+ -> +vector+ } }
77         { v+- { +vector+ +vector+ -> +vector+ } }
78         { v+n { +vector+ +scalar+ -> +vector+ } }
79         { v- { +vector+ +vector+ -> +vector+ } }
80         { vneg { +vector+ -> +vector+ } }
81         { vs- { +vector+ +vector+ -> +vector+ } }
82         { v-n { +vector+ +scalar+ -> +vector+ } }
83         { v. { +vector+ +vector+ -> +scalar+ } }
84         { vsad { +vector+ +vector+ -> +scalar+ } }
85         { v/ { +vector+ +vector+ -> +vector+ } }
86         { v/n { +vector+ +scalar+ -> +vector+ } }
87         { vceiling { +vector+ -> +vector+ } }
88         { vfloor { +vector+ -> +vector+ } }
89         { vmax { +vector+ +vector+ -> +vector+ } }
90         { vmin { +vector+ +vector+ -> +vector+ } }
91         { vavg { +vector+ +vector+ -> +vector+ } }
92         { vneg { +vector+ -> +vector+ } }
93         { vtruncate { +vector+ -> +vector+ } }
94         { sum { +vector+ -> +scalar+ } }
95         { vabs { +vector+ -> +vector+ } }
96         { vsqrt { +vector+ -> +vector+ } }
97         { vbitand { +vector+ +vector+ -> +vector+ } }
98         { vbitandn { +vector+ +vector+ -> +vector+ } }
99         { vbitor { +vector+ +vector+ -> +vector+ } }
100         { vbitxor { +vector+ +vector+ -> +vector+ } }
101         { vbitnot { +vector+ -> +vector+ } }
102         { vand { +vector+ +vector+ -> +vector+ } }
103         { vandn { +vector+ +vector+ -> +vector+ } }
104         { vor { +vector+ +vector+ -> +vector+ } }
105         { vxor { +vector+ +vector+ -> +vector+ } }
106         { vnot { +vector+ -> +vector+ } }
107         { vlshift { +vector+ +scalar+ -> +vector+ } }
108         { vrshift { +vector+ +scalar+ -> +vector+ } }
109         { (vmerge-head) { +vector+ +vector+ -> +vector+ } }
110         { (vmerge-tail) { +vector+ +vector+ -> +vector+ } }
111         { v<= { +vector+ +vector+ -> +vector+ } }
112         { v< { +vector+ +vector+ -> +vector+ } }
113         { v= { +vector+ +vector+ -> +vector+ } }
114         { v> { +vector+ +vector+ -> +vector+ } }
115         { v>= { +vector+ +vector+ -> +vector+ } }
116         { vunordered? { +vector+ +vector+ -> +vector+ } }
117     }
118
119 : vector-word-inputs ( schema -- seq ) { -> } split first ;
120
121 : with-ctors ( -- seq )
122     simd-classes [ [ name>> "-with" append ] [ vocabulary>> ] bi lookup ] map ;
123
124 : boa-ctors ( -- seq )
125     simd-classes [ [ name>> "-boa" append ] [ vocabulary>> ] bi lookup ] map ;
126
127 : check-optimizer ( seq quot eq-quot -- failures )
128     dup '[
129         @
130         [ dup [ class ] { } map-as ] dip '[ _ declare @ ]
131         {
132             [ "print-mr" get [ nip regs. ] [ 2drop ] if ]
133             [ "print-checks" get [ [ . ] bi@ ] [ 2drop ] if ]
134             [ [ [ call ] dip call ] call( quot quot -- result ) ]
135             [ [ [ call ] dip compile-call ] call( quot quot -- result ) ]
136             [ [ t "always-inline-simd-intrinsics" [ [ call ] dip compile-call ] with-variable ] call( quot quot -- result ) ]
137         } 2cleave
138         [ drop @ ] [ nip @ ] 3bi and not
139     ] filter ; inline
140
141 "== Checking -new constructors" print
142
143 [ { } ] [
144     simd-classes [ [ [ ] ] dip '[ _ new ] ] [ = ] check-optimizer
145 ] unit-test
146
147 [ { } ] [
148     simd-classes [ '[ _ new ] compile-call [ zero? ] all? not ] filter
149 ] unit-test
150
151 "== Checking -with constructors" print
152
153 [ { } ] [
154     with-ctors [
155         [ 1000 random '[ _ ] ] dip '[ _ execute ]
156     ] [ = ] check-optimizer
157 ] unit-test
158
159 [ HEX: ffffffff ] [ HEX: ffffffff uint-4-with first ] unit-test
160
161 [ HEX: ffffffff ] [ HEX: ffffffff [ uint-4-with ] compile-call first ] unit-test
162
163 [ HEX: ffffffff ] [ [ HEX: ffffffff uint-4-with ] compile-call first ] unit-test
164
165 "== Checking -boa constructors" print
166
167 [ { } ] [
168     boa-ctors [
169         [ stack-effect in>> length [ 1000 random ] [ ] replicate-as ] keep
170         '[ _ execute ]
171     ] [ = ] check-optimizer
172 ] unit-test
173
174 [ HEX: ffffffff ] [ HEX: ffffffff 2 3 4 [ uint-4-boa ] compile-call first ] unit-test
175
176 "== Checking vector operations" print
177
178 : random-int-vector ( class -- vec )
179     new [ drop 1000 random ] map ;
180
181 : random-float-vector ( class -- vec )
182     new [
183         drop
184         1000 random
185         10 swap <array> 0/0. suffix random
186     ] map ;
187
188 : random-vector ( class elt-class -- vec )
189     float =
190     [ random-float-vector ]
191     [ random-int-vector ] if ;
192
193 :: check-vector-op ( word inputs class elt-class -- inputs quot )
194     inputs [
195         {
196             { +vector+ [ class elt-class random-vector ] }
197             { +scalar+ [ 1000 random elt-class float = [ >float ] when ] }
198         } case
199     ] [ ] map-as
200     word '[ _ execute ] ;
201
202 : remove-float-words ( alist -- alist' )
203     { vsqrt n/v v/n v/ normalize } unique assoc-diff ;
204
205 : remove-integer-words ( alist -- alist' )
206     { vlshift vrshift v*high v*hs+ } unique assoc-diff ;
207
208 : boolean-ops ( -- words )
209     { vand vandn vor vxor vnot } ;
210
211 : remove-boolean-words ( alist -- alist' )
212     boolean-ops unique assoc-diff ;
213
214 : ops-to-check ( elt-class -- alist )
215     [ vector-words >alist ] dip
216     float = [ remove-integer-words ] [ remove-float-words ] if
217     remove-boolean-words ;
218
219 : check-vector-ops ( class elt-class compare-quot -- )
220     [
221         [ nip ops-to-check ] 2keep
222         '[ first2 vector-word-inputs _ _ check-vector-op ]
223     ] dip check-optimizer ; inline
224
225 : (approx=) ( x y -- ? )
226     {
227         { [ 2dup [ fp-nan? ] both? ] [ 2drop t ] }
228         { [ 2dup [ fp-nan? ] either? ] [ 2drop f ] }
229         { [ 2dup [ fp-infinity? ] either? ] [ fp-bitwise= ] }
230         { [ 2dup [ float? ] both? ] [ -1.e8 ~ ] }
231     } cond ;
232
233 : approx= ( x y -- ? )
234     2dup [ sequence? ] both?
235     [ [ (approx=) ] 2all? ] [ (approx=) ] if ;
236
237 : exact= ( x y -- ? )
238     {
239         { [ 2dup [ float? ] both? ] [ fp-bitwise= ] }
240         { [ 2dup [ sequence? ] both? ] [ [ fp-bitwise= ] 2all? ] }
241     } cond ;
242
243 : simd-classes&reps ( -- alist )
244     simd-classes [
245         {
246             { [ dup name>> "float" head? ] [ float [ approx= ] ] }
247             { [ dup name>> "double" head? ] [ float [ exact= ] ] }
248             [ fixnum [ = ] ]
249         } cond 3array
250     ] map ;
251
252 simd-classes&reps [
253     [ [ { } ] ] dip first3 '[ _ _ _ check-vector-ops ] unit-test
254 ] each
255
256 "== Checking boolean operations" print
257
258 : random-boolean-vector ( class -- vec )
259     new [ drop 2 random zero? ] map ;
260
261 :: check-boolean-op ( word inputs class elt-class -- inputs quot )
262     inputs [
263         {
264             { +vector+ [ class random-boolean-vector ] }
265             { +scalar+ [ 1000 random elt-class float = [ >float ] when ] }
266         } case
267     ] [ ] map-as
268     word '[ _ execute ] ;
269
270 : check-boolean-ops ( class elt-class compare-quot -- seq )
271     [
272         [ boolean-ops [ dup vector-words at ] { } map>assoc ] 2dip
273         '[ first2 vector-word-inputs _ _ check-boolean-op ]
274     ] dip check-optimizer ; inline
275
276 simd-classes&reps [
277     [ [ { } ] ] dip first3 '[ _ _ _ check-boolean-ops ] unit-test
278 ] each
279
280 "== Checking vector blend" print
281
282 [ char-16{ 0 1 22 33 4 5 6 77 8 99 110 121 12 143 14 15 } ]
283 [
284     char-16{ t  t  f  f  t  t  t  f  t  f   f   f   t   f   t   t }
285     char-16{ 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 }
286     char-16{ 0 11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 } v?
287 ] unit-test
288
289 [ char-16{ 0 1 22 33 4 5 6 77 8 99 110 121 12 143 14 15 } ]
290 [
291     char-16{ t  t  f  f  t  t  t  f  t  f   f   f   t   f   t   t }
292     char-16{ 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 }
293     char-16{ 0 11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 }
294     [ { char-16 char-16 char-16 } declare v? ] compile-call
295 ] unit-test
296
297 [ int-4{ 1 22 33 4 } ]
298 [ int-4{ t f f t } int-4{ 1 2 3 4 } int-4{ 11 22 33 44 } v? ] unit-test
299
300 [ int-4{ 1 22 33 4 } ]
301 [
302     int-4{ t f f t } int-4{ 1 2 3 4 } int-4{ 11 22 33 44 }
303     [ { int-4 int-4 int-4 } declare v? ] compile-call
304 ] unit-test
305
306 [ float-4{ 1.0 22.0 33.0 4.0 } ]
307 [ float-4{ t f f t } float-4{ 1.0 2.0 3.0 4.0 } float-4{ 11.0 22.0 33.0 44.0 } v? ] unit-test
308
309 [ float-4{ 1.0 22.0 33.0 4.0 } ]
310 [
311     float-4{ t f f t } float-4{ 1.0 2.0 3.0 4.0 } float-4{ 11.0 22.0 33.0 44.0 }
312     [ { float-4 float-4 float-4 } declare v? ] compile-call
313 ] unit-test
314
315 "== Checking shifts and permutations" print
316
317 [ char-16{ 0 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 } ]
318 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } 1 hlshift ] unit-test
319
320 [ char-16{ 0 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 } ]
321 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } [ { char-16 } declare 1 hlshift ] compile-call ] unit-test
322
323 [ char-16{ 0 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 } ]
324 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } 1 [ { char-16 fixnum } declare hlshift ] compile-call ] unit-test
325
326 [ char-16{ 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 0 } ]
327 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } 1 hrshift ] unit-test
328
329 [ char-16{ 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 0 } ]
330 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } [ { char-16 } declare 1 hrshift ] compile-call ] unit-test
331
332 [ char-16{ 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 0 } ]
333 [ char-16{ 1 2 4 8 1 2 4 8 1 2 4 8 1 2 4 8 } 1 [ { char-16 fixnum } declare hrshift ] compile-call ] unit-test
334
335 ! Invalid inputs should not cause the compiler to throw errors
336 [ ] [
337     [ [ { int-4 } declare t hrshift ] (( a -- b )) define-temp drop ] with-compilation-unit
338 ] unit-test
339
340 [ ] [
341     [ [ { int-4 } declare { 3 2 1 } vshuffle ] (( a -- b )) define-temp drop ] with-compilation-unit
342 ] unit-test
343
344 ! Shuffles
345 : shuffles-for ( n -- shuffles )
346     {
347         { 2 [
348             {
349                 { 0 1 }
350                 { 1 1 }
351                 { 1 0 }
352                 { 0 0 }
353             }
354         ] }
355         { 4 [
356             {
357                 { 1 2 3 0 }
358                 { 0 1 2 3 }
359                 { 1 1 2 2 }
360                 { 0 0 1 1 }
361                 { 2 2 3 3 }
362                 { 0 1 0 1 }
363                 { 2 3 2 3 }
364                 { 0 0 2 2 }
365                 { 1 1 3 3 }
366                 { 0 1 0 1 }
367                 { 2 2 3 3 }
368             }
369         ] }
370         { 8 [
371             4 shuffles-for
372             4 shuffles-for
373             [ [ 4 + ] map ] map
374             [ append ] 2map
375         ] }
376         [ dup '[ _ random ] replicate 1array ]
377     } case ;
378
379 simd-classes [
380     [ [ { } ] ] dip
381     [ new length shuffles-for ] keep
382     '[
383         _ [ [ _ new [ length iota ] keep like 1quotation ] dip '[ _ vshuffle ] ]
384         [ = ] check-optimizer
385     ] unit-test
386 ] each
387
388 "== Checking variable shuffles" print
389
390 : random-shift-vector ( class -- vec )
391     new [ drop 16 random ] map ;
392
393 :: test-shift-vector ( class -- ? )
394     [
395         class random-int-vector :> src
396         char-16 random-shift-vector :> perm
397         { class char-16 } :> decl
398     
399         src perm vshuffle
400         src perm [ decl declare vshuffle ] compile-call
401         =
402     ] call( -- ? ) ;
403
404 { char-16 uchar-16 short-8 ushort-8 int-4 uint-4 longlong-2 ulonglong-2 }
405 [ 10 swap '[ [ t ] [ _ test-shift-vector ] unit-test ] times ] each
406
407 "== Checking vector tests" print
408
409 :: test-vector-tests-bool ( vector declaration -- none? any? all? )
410     [
411         vector
412         [ [ declaration declare vnone? ] compile-call ]
413         [ [ declaration declare vany?  ] compile-call ]
414         [ [ declaration declare vall?  ] compile-call ] tri
415     ] call( -- none? any? all? ) ;
416
417 : yes ( -- x ) t ;
418 : no ( -- x ) f ;
419
420 :: test-vector-tests-branch ( vector declaration -- none? any? all? )
421     [
422         vector
423         [ [ declaration declare vnone? [ yes ] [ no ] if ] compile-call ]
424         [ [ declaration declare vany?  [ yes ] [ no ] if ] compile-call ]
425         [ [ declaration declare vall?  [ yes ] [ no ] if ] compile-call ] tri
426     ] call( -- none? any? all? ) ;
427
428 TUPLE: inconsistent-vector-test bool branch ;
429
430 : ?inconsistent ( bool branch -- ?/inconsistent )
431     2dup = [ drop ] [ inconsistent-vector-test boa ] if ;
432
433 :: test-vector-tests ( vector decl -- none? any? all? )
434     [
435         vector decl test-vector-tests-bool :> ( bool-none bool-any bool-all )
436         vector decl test-vector-tests-branch :> ( branch-none branch-any branch-all )
437         
438         bool-none branch-none ?inconsistent
439         bool-any  branch-any  ?inconsistent
440         bool-all  branch-all  ?inconsistent
441     ] call( -- none? any? all? ) ;
442
443 [ f t t ]
444 [ float-4{ t t t t } { float-4 } test-vector-tests ] unit-test
445 [ f t f ]
446 [ float-4{ f t t t } { float-4 } test-vector-tests ] unit-test
447 [ t f f ]
448 [ float-4{ f f f f } { float-4 } test-vector-tests ] unit-test
449
450 [ f t t ]
451 [ double-2{ t t } { double-2 } test-vector-tests ] unit-test
452 [ f t f ]
453 [ double-2{ f t } { double-2 } test-vector-tests ] unit-test
454 [ t f f ]
455 [ double-2{ f f } { double-2 } test-vector-tests ] unit-test
456
457 [ f t t ]
458 [ int-4{ t t t t } { int-4 } test-vector-tests ] unit-test
459 [ f t f ]
460 [ int-4{ f t t t } { int-4 } test-vector-tests ] unit-test
461 [ t f f ]
462 [ int-4{ f f f f } { int-4 } test-vector-tests ] unit-test
463
464 "== Checking element access" print
465
466 ! Test element access -- it should box bignums for int-4 on x86
467 : test-accesses ( seq -- failures )
468     [ length iota >array ] keep
469     '[ [ _ 1quotation ] dip '[ _ swap nth ] ] [ = ] check-optimizer ; inline
470
471 [ { } ] [ float-4{ 1.0 2.0 3.0 4.0 } test-accesses ] unit-test
472 [ { } ] [ int-4{ HEX: 7fffffff 3 4 -8 } test-accesses ] unit-test
473 [ { } ] [ uint-4{ HEX: ffffffff 2 3 4 } test-accesses ] unit-test
474
475 [ HEX: 7fffffff ] [ int-4{ HEX: 7fffffff 3 4 -8 } first ] unit-test
476 [ -8 ] [ int-4{ HEX: 7fffffff 3 4 -8 } last ] unit-test
477 [ HEX: ffffffff ] [ uint-4{ HEX: ffffffff 2 3 4 } first ] unit-test
478
479 [ { } ] [ double-2{ 1.0 2.0 } test-accesses ] unit-test
480 [ { } ] [ longlong-2{ 1 2 } test-accesses ] unit-test
481 [ { } ] [ ulonglong-2{ 1 2 } test-accesses ] unit-test
482
483 "== Checking broadcast" print
484 : test-broadcast ( seq -- failures )
485     [ length iota >array ] keep
486     '[ [ _ 1quotation ] dip '[ _ vbroadcast ] ] [ = ] check-optimizer ;
487
488 [ { } ] [ float-4{ 1.0 2.0 3.0 4.0 } test-broadcast ] unit-test
489 [ { } ] [ int-4{ HEX: 7fffffff 3 4 -8 } test-broadcast ] unit-test
490 [ { } ] [ uint-4{ HEX: ffffffff 2 3 4 } test-broadcast ] unit-test
491
492 [ { } ] [ double-2{ 1.0 2.0 } test-broadcast ] unit-test
493 [ { } ] [ longlong-2{ 1 2 } test-broadcast ] unit-test
494 [ { } ] [ ulonglong-2{ 1 2 } test-broadcast ] unit-test
495
496 ! Make sure we use the fallback in the correct situations
497 [ int-4{ 3 3 3 3 } ] [ int-4{ 12 34 3 17 } 2 [ { int-4 fixnum } declare vbroadcast ] compile-call ] unit-test
498
499 "== Checking alien operations" print
500
501 [ float-4{ 1 2 3 4 } ] [
502     [
503         float-4{ 1 2 3 4 }
504         underlying>> 0 float-4-rep alien-vector
505     ] compile-call float-4 boa
506 ] unit-test
507
508 [ B{ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } ] [
509     16 [ 1 ] B{ } replicate-as 16 <byte-array>
510     [
511         0 [
512             { byte-array c-ptr fixnum } declare
513             float-4-rep set-alien-vector
514         ] compile-call
515     ] keep
516 ] unit-test
517
518 [ float-array{ 1 2 3 4 } ] [
519     [
520         float-array{ 1 2 3 4 } underlying>>
521         float-array{ 4 3 2 1 } clone
522         [ underlying>> 0 float-4-rep set-alien-vector ] keep
523     ] compile-call
524 ] unit-test
525
526 STRUCT: simd-struct
527 { x float-4 }
528 { y longlong-2 }
529 { z double-2 }
530 { w int-4 } ;
531
532 [ t ] [ [ simd-struct <struct> ] compile-call >c-ptr [ 0 = ] all? ] unit-test
533
534 [
535     float-4{ 1 2 3 4 }
536     longlong-2{ 2 1 }
537     double-2{ 4 3 }
538     int-4{ 1 2 3 4 }
539 ] [
540     simd-struct <struct>
541     float-4{ 1 2 3 4 } >>x
542     longlong-2{ 2 1 } >>y
543     double-2{ 4 3 } >>z
544     int-4{ 1 2 3 4 } >>w
545     { [ x>> ] [ y>> ] [ z>> ] [ w>> ] } cleave
546 ] unit-test
547
548 [
549     float-4{ 1 2 3 4 }
550     longlong-2{ 2 1 }
551     double-2{ 4 3 }
552     int-4{ 1 2 3 4 }
553 ] [
554     [
555         simd-struct <struct>
556         float-4{ 1 2 3 4 } >>x
557         longlong-2{ 2 1 } >>y
558         double-2{ 4 3 } >>z
559         int-4{ 1 2 3 4 } >>w
560         { [ x>> ] [ y>> ] [ z>> ] [ w>> ] } cleave
561     ] compile-call
562 ] unit-test
563
564 "== Misc tests" print
565
566 [ ] [ char-16 new 1array stack. ] unit-test
567
568 ! CSSA bug
569 [ 4000000 ] [
570     int-4{ 1000 1000 1000 1000 }
571     [ { int-4 } declare dup [ * ] [ + ] 2map-reduce ] compile-call
572 ] unit-test
573
574 ! Coalescing was too aggressive
575 :: broken ( axis theta -- a b c )
576    axis { float-4 } declare drop
577    theta { float } declare drop
578
579    theta cos float-4-with :> cc
580    theta sin float-4-with :> ss
581    
582    axis cc v+ :> diagonal
583
584    diagonal cc ss ; inline
585
586 [ t ] [
587     float-4{ 1.0 0.0 1.0 0.0 } pi [ broken 3array ]
588     [ compile-call ] [ call ] 3bi =
589 ] unit-test
590
591 ! Spilling SIMD values -- this basically just tests that the
592 ! stack was aligned properly by the runtime
593
594 : simd-spill-test-1 ( a b c -- v )
595     { float-4 float-4 float } declare 
596     [ v+ ] dip sin v*n ;
597
598 [ float-4{ 0 0 0 0 } ]
599 [ float-4{ 1 2 3 4 } float-4{ 4 5 6 7 } 0.0 simd-spill-test-1 ] unit-test
600
601 : simd-spill-test-2 ( a b d c -- v )
602     { float float-4 float-4 float } declare 
603     [ [ 3.0 + ] 2dip v+ ] dip sin v*n n*v ;
604
605 [ float-4{ 0 0 0 0 } ]
606 [ 5.0 float-4{ 1 2 3 4 } float-4{ 4 5 6 7 } 0.0 simd-spill-test-2 ] unit-test
607
608 ! Test some sequence protocol stuff
609 [ t ] [ 4 double-4{ 1 2 3 4 } new-sequence double-4? ] unit-test
610 [ double-4{ 2 3 4 5 } ] [ double-4{ 1 2 3 4 } [ 1 + ] map ] unit-test
611
612 ! Test cross product
613 [ float-4{ 0.0 0.0 1.0 0.0 } ] [ float-4{ 1.0 0.0 0.0 0.0 } float-4{ 0.0 1.0 0.0 0.0 } cross ] unit-test
614 [ float-4{ 0.0 -1.0 0.0 0.0 } ] [ float-4{ 1.0 0.0 0.0 0.0 } float-4{ 0.0 0.0 1.0 0.0 } cross ] unit-test
615
616 [ double-4{ 0.0 0.0 1.0 0.0 } ] [ double-4{ 1.0 0.0 0.0 0.0 } double-4{ 0.0 1.0 0.0 0.0 } cross ] unit-test
617 [ double-4{ 0.0 -1.0 0.0 0.0 } ] [ double-4{ 1.0 0.0 0.0 0.0 } double-4{ 0.0 0.0 1.0 0.0 } cross ] unit-test