1 USING: accessors alien arrays byte-arrays classes combinators
2 cpu.architecture effects fry functors generalizations generic
3 generic.parser kernel lexer literals locals macros math math.functions
4 math.vectors math.vectors.private math.vectors.simd.intrinsics
5 namespaces parser prettyprint.custom quotations sequences
6 sequences.generalizations sequences.private vocabs vocabs.loader
8 QUALIFIED-WITH: alien.c-types c
11 ERROR: bad-simd-length got expected ;
13 ERROR: bad-simd-vector obj ;
17 ! Primitive SIMD constructors
19 GENERIC: new-underlying ( underlying seq -- seq' )
21 : make-underlying ( seq quot -- seq' )
22 dip new-underlying ; inline
23 : change-underlying ( seq quot -- seq' )
24 '[ underlying>> @ ] keep new-underlying ; inline
30 ! Helper for boolean vector literals
32 : vector-true-value ( class -- value )
33 { c:float c:double } member? [ -1 bits>double ] [ -1 ] if ; foldable
35 : vector-false-value ( type -- value )
36 { c:float c:double } member? [ 0.0 ] [ 0 ] if ; foldable
38 : boolean>element ( bool/elt type -- elt )
40 { t [ vector-true-value ] }
41 { f [ vector-false-value ] }
50 { underlying byte-array read-only initial: $[ 16 <byte-array> ] } ;
52 GENERIC: simd-element-type ( obj -- c-type )
53 GENERIC: simd-rep ( simd -- rep )
54 GENERIC: simd-with ( n exemplar -- v )
56 M: object simd-element-type drop f ;
57 M: object simd-rep drop f ;
62 DEFER: simd-construct-op
64 ! Unboxers for SIMD operations
65 : if-both-vectors ( a b rep t f -- )
66 [ 2over [ simd-128? ] both? ] 2dip if ; inline
68 : if-both-vectors-match ( a b rep t f -- )
69 [ 3dup [ drop [ simd-128? ] both? ] [ '[ simd-rep _ eq? ] both? ] 3bi and ]
72 : simd-unbox ( a -- a (a) )
73 [ ] [ underlying>> ] bi ; inline
75 : v->v-op ( a rep quot: ( (a) rep -- (c) ) fallback-quot -- c )
76 drop [ simd-unbox ] 2dip 2curry make-underlying ; inline
78 : vx->v-op ( a obj rep quot: ( (a) obj rep -- (c) ) fallback-quot -- c )
79 drop [ simd-unbox ] 3dip 3curry make-underlying ; inline
81 : vn->v-op ( a n rep quot: ( (a) n rep -- (c) ) fallback-quot -- c )
82 drop [ [ simd-unbox ] [ >fixnum ] bi* ] 2dip 3curry make-underlying ; inline
84 : vx->x-op ( a obj rep quot: ( (a) obj rep -- obj ) fallback-quot -- obj )
85 drop [ underlying>> ] 3dip call ; inline
87 : v->x-op ( a rep quot: ( (a) rep -- obj ) fallback-quot -- obj )
88 drop [ underlying>> ] 2dip call ; inline
90 : (vv->v-op) ( a b rep quot: ( (a) (b) rep -- (c) ) -- c )
91 [ [ simd-unbox ] [ underlying>> ] bi* ] 2dip 3curry make-underlying ; inline
93 : (vv->x-op) ( a b rep quot: ( (a) (b) rep -- n ) -- n )
94 [ [ underlying>> ] bi@ ] 2dip 3curry call ; inline
96 : (vvx->v-op) ( a b obj rep quot: ( (a) (b) obj rep -- (c) ) -- c )
97 [ [ simd-unbox ] [ underlying>> ] bi* ] 3dip 2curry 2curry make-underlying ; inline
99 : vv->v-op ( a b rep quot: ( (a) (b) rep -- (c) ) fallback-quot -- c )
100 [ '[ _ (vv->v-op) ] ] [ '[ drop @ ] ] bi* if-both-vectors-match ; inline
102 :: vvx->v-op ( a b obj rep quot: ( (a) (b) obj rep -- (c) ) fallback-quot -- c )
104 [ obj swap quot (vvx->v-op) ]
105 [ drop obj fallback-quot call ] if-both-vectors-match ; inline
107 : vv'->v-op ( a b rep quot: ( (a) (b) rep -- (c) ) fallback-quot -- c )
108 [ '[ _ (vv->v-op) ] ] [ '[ drop @ ] ] bi* if-both-vectors ; inline
110 : vv->x-op ( a b rep quot: ( (a) (b) rep -- obj ) fallback-quot -- obj )
111 [ '[ _ (vv->x-op) ] ] [ '[ drop @ ] ] bi* if-both-vectors-match ; inline
118 ! SIMD vectors as sequences
120 M: simd-128 hashcode* underlying>> hashcode* ; inline
121 M: simd-128 clone [ clone ] change-underlying ; inline
122 M: simd-128 byte-length drop 16 ; inline
124 M: simd-128 new-sequence
126 [ nip [ 16 (byte-array) ] make-underlying ]
127 [ length bad-simd-length ] if ; inline
130 dup simd-rep [ drop v= vall? ] [ 3drop f ] if-both-vectors-match ; inline
132 ! SIMD primitive operations
135 dup simd-rep [ (simd-v+) ] [ call-next-method ] vv->v-op ; inline
137 dup simd-rep [ (simd-v-) ] [ call-next-method ] vv->v-op ; inline
139 dup simd-rep [ (simd-vneg) ] [ call-next-method ] v->v-op ; inline
141 dup simd-rep [ (simd-v+-) ] [ call-next-method ] vv->v-op ; inline
143 dup simd-rep [ (simd-vs+) ] [ call-next-method ] vv->v-op ; inline
145 dup simd-rep [ (simd-vs-) ] [ call-next-method ] vv->v-op ; inline
147 dup simd-rep [ (simd-vs*) ] [ call-next-method ] vv->v-op ; inline
149 dup simd-rep [ (simd-v*) ] [ call-next-method ] vv->v-op ; inline
151 dup simd-rep [ (simd-v*high) ] [ call-next-method ] vv->v-op ; inline
153 dup simd-rep [ (simd-v/) ] [ call-next-method ] vv->v-op ; inline
155 dup simd-rep [ (simd-vavg) ] [ call-next-method ] vv->v-op ; inline
157 dup simd-rep [ (simd-vmin) ] [ call-next-method ] vv->v-op ; inline
159 dup simd-rep [ (simd-vmax) ] [ call-next-method ] vv->v-op ; inline
161 dup simd-rep [ (simd-v.) ] [ call-next-method ] vv->x-op ; inline
163 dup simd-rep [ (simd-vsad) ] [ call-next-method ] vv->x-op ; inline
165 dup simd-rep [ (simd-vsqrt) ] [ call-next-method ] v->v-op ; inline
167 dup simd-rep [ (simd-sum) ] [ call-next-method ] v->x-op ; inline
169 dup simd-rep [ (simd-vabs) ] [ call-next-method ] v->v-op ; inline
171 dup simd-rep [ (simd-vbitand) ] [ call-next-method ] vv->v-op ; inline
173 dup simd-rep [ (simd-vbitandn) ] [ call-next-method ] vv->v-op ; inline
175 dup simd-rep [ (simd-vbitor) ] [ call-next-method ] vv->v-op ; inline
177 dup simd-rep [ (simd-vbitxor) ] [ call-next-method ] vv->v-op ; inline
179 dup simd-rep [ (simd-vbitnot) ] [ call-next-method ] v->v-op ; inline
181 dup simd-rep [ (simd-vand) ] [ call-next-method ] vv->v-op ; inline
183 dup simd-rep [ (simd-vandn) ] [ call-next-method ] vv->v-op ; inline
185 dup simd-rep [ (simd-vor) ] [ call-next-method ] vv->v-op ; inline
187 dup simd-rep [ (simd-vxor) ] [ call-next-method ] vv->v-op ; inline
189 dup simd-rep [ (simd-vnot) ] [ call-next-method ] v->v-op ; inline
191 over simd-rep [ (simd-vlshift) ] [ call-next-method ] vn->v-op ; inline
193 over simd-rep [ (simd-vrshift) ] [ call-next-method ] vn->v-op ; inline
195 over simd-rep [ (simd-hlshift) ] [ call-next-method ] vn->v-op ; inline
197 over simd-rep [ (simd-hrshift) ] [ call-next-method ] vn->v-op ; inline
198 M: simd-128 vshuffle-elements
199 over simd-rep [ (simd-vshuffle-elements) ] [ call-next-method ] vx->v-op ; inline
200 M: simd-128 vshuffle2-elements
201 over simd-rep [ (simd-vshuffle2-elements) ] [ call-next-method ] vvx->v-op ; inline
202 M: simd-128 vshuffle-bytes
203 dup simd-rep [ (simd-vshuffle-bytes) ] [ call-next-method ] vv'->v-op ; inline
204 M: simd-128 (vmerge-head)
205 dup simd-rep [ (simd-vmerge-head) ] [ call-next-method ] vv->v-op ; inline
206 M: simd-128 (vmerge-tail)
207 dup simd-rep [ (simd-vmerge-tail) ] [ call-next-method ] vv->v-op ; inline
209 dup simd-rep [ (simd-v<=) ] [ call-next-method ] vv->v-op ; inline
211 dup simd-rep [ (simd-v<) ] [ call-next-method ] vv->v-op ; inline
213 dup simd-rep [ (simd-v=) ] [ call-next-method ] vv->v-op ; inline
215 dup simd-rep [ (simd-v>) ] [ call-next-method ] vv->v-op ; inline
217 dup simd-rep [ (simd-v>=) ] [ call-next-method ] vv->v-op ; inline
218 M: simd-128 vunordered?
219 dup simd-rep [ (simd-vunordered?) ] [ call-next-method ] vv->v-op ; inline
221 dup simd-rep [ (simd-vany?) ] [ call-next-method ] v->x-op ; inline
223 dup simd-rep [ (simd-vall?) ] [ call-next-method ] v->x-op ; inline
225 dup simd-rep [ (simd-vnone?) ] [ call-next-method ] v->x-op ; inline
227 ! SIMD high-level specializations
229 M: simd-128 vbroadcast swap [ nth ] [ simd-with ] bi ; inline
230 M: simd-128 n+v [ simd-with ] keep v+ ; inline
231 M: simd-128 n-v [ simd-with ] keep v- ; inline
232 M: simd-128 n*v [ simd-with ] keep v* ; inline
233 M: simd-128 n/v [ simd-with ] keep v/ ; inline
234 M: simd-128 v+n over simd-with v+ ; inline
235 M: simd-128 v-n over simd-with v- ; inline
236 M: simd-128 v*n over simd-with v* ; inline
237 M: simd-128 v/n over simd-with v/ ; inline
238 M: simd-128 norm-sq dup v. assert-positive ; inline
239 M: simd-128 distance v- norm ; inline
241 M: simd-128 >pprint-sequence ;
242 M: simd-128 pprint* pprint-object ;
246 ! SIMD concrete type functor
248 FUNCTOR: define-simd-128 ( T -- )
253 A-boa DEFINES ${T}-boa
254 A-with DEFINES ${T}-with
255 A-cast DEFINES ${T}-cast
258 ELT [ A-rep rep-component-type ]
259 N [ A-rep rep-length ]
260 COERCER [ ELT c:c-type-class "coercer" word-prop [ ] or ]
262 BOA-EFFECT [ N "n" <array> { "v" } <effect> ]
266 TUPLE: A < simd-128 ; final
268 M: A new-underlying drop \ A boa ; inline
269 M: A simd-rep drop A-rep ; inline
270 M: A simd-element-type drop ELT ; inline
271 M: A simd-with drop A-with ; inline
274 swap \ A-rep [ (simd-select) ] [ call-next-method ] vx->x-op ; inline
276 [ ELT boolean>element ] 2dip
277 underlying>> ELT c:set-alien-element ; inline
279 : >A ( seq -- simd ) \ A new clone-like ; inline
281 M: A like drop dup \ A instance? [ >A ] unless ; inline
283 : A-with ( n -- v ) COERCER call \ A-rep (simd-with) \ A boa ; inline
284 : A-cast ( v -- v' ) underlying>> \ A boa ; inline
286 M: A length drop N ; inline
289 [ COERCER N napply ] N {
290 { 2 [ [ A-rep (simd-gather-2) A boa ] ] }
291 { 4 [ [ A-rep (simd-gather-4) A boa ] ] }
292 [ \ A new '[ _ _ nsequence ] ]
294 BOA-EFFECT define-inline
296 M: A pprint-delims drop \ A{ \ } ;
297 SYNTAX: A{ \ } [ >A ] parse-literal ;
304 { A-rep alien-vector A boa } >quotation >>getter
306 [ dup simd-128? [ bad-simd-vector ] unless underlying>> ] 2dip
307 A-rep set-alien-vector
308 } >quotation >>setter
317 scan-token define-simd-128 ;
332 SIMD-128: ulonglong-2
338 M: simd-128 vshuffle ( u perm -- v )
339 vshuffle-bytes ; inline
342 uchar-16-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op short-8-cast ; inline
344 ushort-8-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op uint-4-cast ; inline
346 uint-4-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op ulonglong-2-cast ; inline
348 char-16-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op short-8-cast ; inline
350 short-8-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op int-4-cast ; inline
352 int-4-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op longlong-2-cast ; inline
354 { "math.vectors.simd" "mirrors" } "math.vectors.simd.mirrors" require-when