1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors kernel kernel.private math math.private words
4 sequences parser namespaces make assocs quotations arrays
5 generic generic.math hashtables effects compiler.units
6 classes.algebra fry combinators ;
7 IN: math.partial-dispatch
9 PREDICATE: math-partial < word
10 "derived-from" word-prop >boolean ;
12 GENERIC: integer-op-input-classes ( word -- classes )
14 M: math-partial integer-op-input-classes
15 "derived-from" word-prop rest ;
17 ERROR: bad-integer-op word ;
19 M: word integer-op-input-classes
20 dup "input-classes" word-prop
21 [ ] [ bad-integer-op ] ?if ;
23 : generic-variant ( op -- generic-op/f )
24 dup "derived-from" word-prop [ first ] [ ] ?if ;
26 : no-overflow-variant ( op -- fast-op )
28 { fixnum+ fixnum+fast }
29 { fixnum- fixnum-fast }
30 { fixnum* fixnum*fast }
31 { fixnum-shift fixnum-shift-fast }
32 { fixnum/i fixnum/i-fast }
33 { fixnum/mod fixnum/mod-fast }
36 : modular-variant ( op -- fast-op )
37 generic-variant dup H{
41 { shift fixnum-shift-fast }
42 { bitand fixnum-bitand }
43 { bitor fixnum-bitor }
44 { bitxor fixnum-bitxor }
45 { bitnot fixnum-bitnot }
48 : integer-fixnum-op-quot ( fix-word big-word -- quot )
52 [ '[ fixnum>bignum _ execute ] , ] bi*
56 : fixnum-integer-op-quot ( fix-word big-word -- quot )
60 [ '[ [ fixnum>bignum ] dip _ execute ] , ] bi*
64 : integer-integer-op-quot ( fix-word big-word -- quot )
67 2dup integer-fixnum-op-quot ,
69 [ over fixnum? [ [ fixnum>bignum ] dip ] when ] %
75 : integer-op-word ( triple -- word )
76 [ name>> ] map "-" join "math.partial-dispatch" create ;
78 : integer-op-quot ( fix-word big-word triple -- quot )
79 [ second ] [ third ] bi 2array {
80 { { fixnum integer } [ fixnum-integer-op-quot ] }
81 { { integer fixnum } [ integer-fixnum-op-quot ] }
82 { { integer integer } [ integer-integer-op-quot ] }
85 : define-integer-op-word ( fix-word big-word triple -- )
87 [ 2nip integer-op-word ] [ integer-op-quot ] 3bi
88 (( x y -- z )) define-declared
91 [ integer-op-word ] keep
92 "derived-from" set-word-prop
95 : define-integer-op-words ( triples fix-word big-word -- )
96 '[ [ _ _ ] dip define-integer-op-word ] each ;
98 : integer-op-triples ( word -- triples )
103 } swap '[ _ prefix ] map ;
105 : define-integer-ops ( word fix-word big-word -- )
108 [ fixnum fixnum 3array "derived-from" set-word-prop ]
109 [ bignum bignum 3array "derived-from" set-word-prop ]
112 [ integer-op-triples ] 2dip
113 [ define-integer-op-words ]
114 [ 2drop [ dup integer-op-word ] { } map>assoc % ]
118 : define-math-ops ( op -- )
119 { fixnum bignum float }
120 [ [ dup 3array ] [ swap method ] 2bi ] with { } map>assoc
123 [ nip length 1 = ] assoc-filter
124 [ first ] assoc-map % ;
128 SYMBOL: fast-math-ops
130 : math-op ( word left right -- word' ? )
131 3array math-ops get at* ;
133 : math-method* ( word left right -- quot )
135 [ [ 3drop ] dip 1quotation ] [ drop math-method ] if ;
137 : math-both-known? ( word left right -- ? )
140 [ drop math-class-max swap specific-method >boolean ] if ;
142 : (derived-ops) ( word assoc -- words )
143 swap '[ swap first _ eq? nip ] assoc-filter ;
145 : derived-ops ( word -- words )
146 [ 1array ] [ math-ops get (derived-ops) values ] bi append ;
148 : fast-derived-ops ( word -- words )
149 fast-math-ops get (derived-ops) values ;
151 : all-derived-ops ( word -- words )
152 [ derived-ops ] [ fast-derived-ops ] bi append ;
154 : integer-derived-ops ( word -- words )
155 [ math-ops get (derived-ops) ] [ fast-math-ops get (derived-ops) ] bi
159 [ second integer class<= ]
160 [ third integer class<= ]
162 ] assoc-filter values
165 : each-derived-op ( word quot -- )
166 [ derived-ops ] dip each ; inline
168 : each-fast-derived-op ( word quot -- )
169 [ fast-derived-ops ] dip each ; inline
171 : each-integer-derived-op ( word quot -- )
172 [ integer-derived-ops ] dip each ; inline
179 \ mod define-math-ops
182 \ bitand define-math-ops
183 \ bitor define-math-ops
184 \ bitxor define-math-ops
190 \ number= define-math-ops
192 { { shift bignum bignum } bignum-shift } ,
193 { { shift fixnum fixnum } fixnum-shift } ,
195 \ + \ fixnum+ \ bignum+ define-integer-ops
196 \ - \ fixnum- \ bignum- define-integer-ops
197 \ * \ fixnum* \ bignum* define-integer-ops
198 \ shift \ fixnum-shift \ bignum-shift define-integer-ops
199 \ mod \ fixnum-mod \ bignum-mod define-integer-ops
200 \ /i \ fixnum/i \ bignum/i define-integer-ops
202 \ bitand \ fixnum-bitand \ bignum-bitand define-integer-ops
203 \ bitor \ fixnum-bitor \ bignum-bitor define-integer-ops
204 \ bitxor \ fixnum-bitxor \ bignum-bitxor define-integer-ops
206 \ < \ fixnum< \ bignum< define-integer-ops
207 \ <= \ fixnum<= \ bignum<= define-integer-ops
208 \ > \ fixnum> \ bignum> define-integer-ops
209 \ >= \ fixnum>= \ bignum>= define-integer-ops
210 \ number= \ eq? \ bignum= define-integer-ops
211 ] { } make >hashtable math-ops set-global
214 { { + fixnum fixnum } fixnum+fast }
215 { { - fixnum fixnum } fixnum-fast }
216 { { * fixnum fixnum } fixnum*fast }
217 { { shift fixnum fixnum } fixnum-shift-fast }
218 } fast-math-ops set-global
219 ] with-compilation-unit