220 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Factor
		
	
	
| ! Copyright (C) 2008 Slava Pestov.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: accessors kernel kernel.private math math.private words
 | |
| sequences parser namespaces make assocs quotations arrays
 | |
| generic generic.math hashtables effects compiler.units
 | |
| classes.algebra fry combinators ;
 | |
| IN: math.partial-dispatch
 | |
| 
 | |
| PREDICATE: math-partial < word
 | |
|     "derived-from" word-prop >boolean ;
 | |
| 
 | |
| GENERIC: integer-op-input-classes ( word -- classes )
 | |
| 
 | |
| M: math-partial integer-op-input-classes
 | |
|     "derived-from" word-prop rest ;
 | |
| 
 | |
| ERROR: bad-integer-op word ;
 | |
| 
 | |
| M: word integer-op-input-classes
 | |
|     dup "input-classes" word-prop
 | |
|     [ ] [ bad-integer-op ] ?if ;
 | |
| 
 | |
| : generic-variant ( op -- generic-op/f )
 | |
|     dup "derived-from" word-prop [ first ] [ ] ?if ;
 | |
| 
 | |
| : no-overflow-variant ( op -- fast-op )
 | |
|     H{
 | |
|         { fixnum+ fixnum+fast }
 | |
|         { fixnum- fixnum-fast }
 | |
|         { fixnum* fixnum*fast }
 | |
|         { fixnum-shift fixnum-shift-fast }
 | |
|         { fixnum/i fixnum/i-fast }
 | |
|         { fixnum/mod fixnum/mod-fast }
 | |
|     } at ;
 | |
| 
 | |
| : modular-variant ( op -- fast-op )
 | |
|     generic-variant dup H{
 | |
|         { + fixnum+fast }
 | |
|         { - fixnum-fast }
 | |
|         { * fixnum*fast }
 | |
|         { shift fixnum-shift-fast }
 | |
|         { bitand fixnum-bitand }
 | |
|         { bitor fixnum-bitor }
 | |
|         { bitxor fixnum-bitxor }
 | |
|         { bitnot fixnum-bitnot }
 | |
|     } at swap or ;
 | |
| 
 | |
| : integer-fixnum-op-quot ( fix-word big-word -- quot )
 | |
|     [
 | |
|         [ over fixnum? ] %
 | |
|         [ '[ _ execute ] , ]
 | |
|         [ '[ fixnum>bignum _ execute ] , ] bi*
 | |
|         \ if ,
 | |
|     ] [ ] make ;
 | |
| 
 | |
| : fixnum-integer-op-quot ( fix-word big-word -- quot )
 | |
|     [
 | |
|         [ dup fixnum? ] %
 | |
|         [ '[ _ execute ] , ]
 | |
|         [ '[ [ fixnum>bignum ] dip _ execute ] , ] bi*
 | |
|         \ if ,
 | |
|     ] [ ] make ;
 | |
| 
 | |
| : integer-integer-op-quot ( fix-word big-word -- quot )
 | |
|     [
 | |
|         [ dup fixnum? ] %
 | |
|         2dup integer-fixnum-op-quot ,
 | |
|         [
 | |
|             [ over fixnum? [ [ fixnum>bignum ] dip ] when ] %
 | |
|             nip ,
 | |
|         ] [ ] make ,
 | |
|         \ if ,
 | |
|     ] [ ] make ;
 | |
| 
 | |
| : integer-op-word ( triple -- word )
 | |
|     [ name>> ] map "-" join "math.partial-dispatch" create ;
 | |
| 
 | |
| : integer-op-quot ( fix-word big-word triple -- quot )
 | |
|     [ second ] [ third ] bi 2array {
 | |
|         { { fixnum integer } [ fixnum-integer-op-quot ] }
 | |
|         { { integer fixnum } [ integer-fixnum-op-quot ] }
 | |
|         { { integer integer } [ integer-integer-op-quot ] }
 | |
|     } case ;
 | |
| 
 | |
| : define-integer-op-word ( fix-word big-word triple -- )
 | |
|     [
 | |
|         [ 2nip integer-op-word ] [ integer-op-quot ] 3bi
 | |
|         (( x y -- z )) define-declared
 | |
|     ] [
 | |
|         2nip
 | |
|         [ integer-op-word ] keep
 | |
|         "derived-from" set-word-prop
 | |
|     ] 3bi ;
 | |
| 
 | |
| : define-integer-op-words ( triples fix-word big-word -- )
 | |
|     '[ [ _ _ ] dip define-integer-op-word ] each ;
 | |
| 
 | |
| : integer-op-triples ( word -- triples )
 | |
|     {
 | |
|         { fixnum integer }
 | |
|         { integer fixnum }
 | |
|         { integer integer }
 | |
|     } swap '[ _ prefix ] map ;
 | |
| 
 | |
| : define-integer-ops ( word fix-word big-word -- )
 | |
|     [
 | |
|         rot tuck
 | |
|         [ fixnum fixnum 3array "derived-from" set-word-prop ]
 | |
|         [ bignum bignum 3array "derived-from" set-word-prop ]
 | |
|         2bi*
 | |
|     ] [
 | |
|         [ integer-op-triples ] 2dip
 | |
|         [ define-integer-op-words ]
 | |
|         [ 2drop [ dup integer-op-word ] { } map>assoc % ]
 | |
|         3bi
 | |
|     ] 3bi ;
 | |
| 
 | |
| : define-math-ops ( op -- )
 | |
|     { fixnum bignum float }
 | |
|     [ [ dup 3array ] [ swap method ] 2bi ] with { } map>assoc
 | |
|     [ nip ] assoc-filter
 | |
|     [ def>> ] assoc-map
 | |
|     [ nip length 1 = ] assoc-filter
 | |
|     [ first ] assoc-map % ;
 | |
| 
 | |
| SYMBOL: math-ops
 | |
| 
 | |
| SYMBOL: fast-math-ops
 | |
| 
 | |
| : math-op ( word left right -- word' ? )
 | |
|     3array math-ops get at* ;
 | |
| 
 | |
| : math-method* ( word left right -- quot )
 | |
|     3dup math-op
 | |
|     [ [ 3drop ] dip 1quotation ] [ drop math-method ] if ;
 | |
| 
 | |
| : math-both-known? ( word left right -- ? )
 | |
|     3dup math-op
 | |
|     [ 2drop 2drop t ]
 | |
|     [ drop math-class-max swap specific-method >boolean ] if ;
 | |
| 
 | |
| : (derived-ops) ( word assoc -- words )
 | |
|     swap '[ swap first _ eq? nip ] assoc-filter ;
 | |
| 
 | |
| : derived-ops ( word -- words )
 | |
|     [ 1array ] [ math-ops get (derived-ops) values ] bi append ;
 | |
| 
 | |
| : fast-derived-ops ( word -- words )
 | |
|     fast-math-ops get (derived-ops) values ;
 | |
| 
 | |
| : all-derived-ops ( word -- words )
 | |
|     [ derived-ops ] [ fast-derived-ops ] bi append ;
 | |
| 
 | |
| : integer-derived-ops ( word -- words )
 | |
|     [ math-ops get (derived-ops) ] [ fast-math-ops get (derived-ops) ] bi
 | |
|     [
 | |
|         [
 | |
|             drop
 | |
|             [ second integer class<= ]
 | |
|             [ third integer class<= ]
 | |
|             bi and
 | |
|         ] assoc-filter values
 | |
|     ] bi@ append ;
 | |
| 
 | |
| : each-derived-op ( word quot -- )
 | |
|     [ derived-ops ] dip each ; inline
 | |
| 
 | |
| : each-fast-derived-op ( word quot -- )
 | |
|     [ fast-derived-ops ] dip each ; inline
 | |
| 
 | |
| : each-integer-derived-op ( word quot -- )
 | |
|     [ integer-derived-ops ] dip each ; inline
 | |
| 
 | |
| [
 | |
|     [
 | |
|         \ +       define-math-ops
 | |
|         \ -       define-math-ops
 | |
|         \ *       define-math-ops
 | |
|         \ mod     define-math-ops
 | |
|         \ /i      define-math-ops
 | |
| 
 | |
|         \ bitand  define-math-ops
 | |
|         \ bitor   define-math-ops
 | |
|         \ bitxor  define-math-ops
 | |
| 
 | |
|         \ <       define-math-ops
 | |
|         \ <=      define-math-ops
 | |
|         \ >       define-math-ops
 | |
|         \ >=      define-math-ops
 | |
|         \ number= define-math-ops
 | |
| 
 | |
|         { { shift bignum bignum } bignum-shift } ,
 | |
|         { { shift fixnum fixnum } fixnum-shift } ,
 | |
| 
 | |
|         \ + \ fixnum+ \ bignum+ define-integer-ops
 | |
|         \ - \ fixnum- \ bignum- define-integer-ops
 | |
|         \ * \ fixnum* \ bignum* define-integer-ops
 | |
|         \ shift \ fixnum-shift \ bignum-shift define-integer-ops
 | |
|         \ mod \ fixnum-mod \ bignum-mod define-integer-ops
 | |
|         \ /i \ fixnum/i \ bignum/i define-integer-ops
 | |
| 
 | |
|         \ bitand \ fixnum-bitand \ bignum-bitand define-integer-ops
 | |
|         \ bitor \ fixnum-bitor \ bignum-bitor define-integer-ops
 | |
|         \ bitxor \ fixnum-bitxor \ bignum-bitxor define-integer-ops
 | |
| 
 | |
|         \ < \ fixnum< \ bignum< define-integer-ops
 | |
|         \ <= \ fixnum<= \ bignum<= define-integer-ops
 | |
|         \ > \ fixnum> \ bignum> define-integer-ops
 | |
|         \ >= \ fixnum>= \ bignum>= define-integer-ops
 | |
|         \ number= \ eq? \ bignum= define-integer-ops
 | |
|     ] { } make >hashtable math-ops set-global
 | |
| 
 | |
|     H{
 | |
|         { { + fixnum fixnum } fixnum+fast }
 | |
|         { { - fixnum fixnum } fixnum-fast }
 | |
|         { { * fixnum fixnum } fixnum*fast }
 | |
|         { { shift fixnum fixnum } fixnum-shift-fast }
 | |
|     } fast-math-ops set-global
 | |
| ] with-compilation-unit
 |