factor/core/optimizer/math/math.factor

423 lines
10 KiB
Factor
Raw Normal View History

2008-01-12 21:37:44 -05:00
! Copyright (C) 2005, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
IN: optimizer.math
2008-02-01 00:00:08 -05:00
USING: alien alien.accessors arrays generic hashtables kernel
assocs math math.private kernel.private sequences words parser
2007-09-20 18:09:08 -04:00
inference.class inference.dataflow vectors strings sbufs io
namespaces assocs quotations math.intervals sequences.private
2008-03-24 20:52:21 -04:00
combinators splitting layouts math.parser classes
classes.algebra generic.math optimizer.pattern-match
optimizer.backend optimizer.def-use optimizer.inlining
2008-04-19 03:11:55 -04:00
optimizer.math.partial generic.standard system accessors ;
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
: define-math-identities ( word identities -- )
>r all-derived-ops r> define-identities ;
\ number= {
{ { @ @ } [ 2drop t ] }
} define-math-identities
\ + {
2007-09-20 18:09:08 -04:00
{ { number 0 } [ drop ] }
{ { 0 number } [ nip ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ - {
2007-09-20 18:09:08 -04:00
{ { number 0 } [ drop ] }
{ { @ @ } [ 2drop 0 ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ < {
2007-09-20 18:09:08 -04:00
{ { @ @ } [ 2drop f ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ <= {
2007-09-20 18:09:08 -04:00
{ { @ @ } [ 2drop t ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ > {
2007-09-20 18:09:08 -04:00
{ { @ @ } [ 2drop f ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ >= {
2007-09-20 18:09:08 -04:00
{ { @ @ } [ 2drop t ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ * {
2007-09-20 18:09:08 -04:00
{ { number 1 } [ drop ] }
{ { 1 number } [ nip ] }
{ { number 0 } [ nip ] }
{ { 0 number } [ drop ] }
{ { number -1 } [ drop 0 swap - ] }
{ { -1 number } [ nip 0 swap - ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ / {
2007-09-20 18:09:08 -04:00
{ { number 1 } [ drop ] }
{ { number -1 } [ drop 0 swap - ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ mod {
{ { integer 1 } [ 2drop 0 ] }
} define-math-identities
\ rem {
{ { integer 1 } [ 2drop 0 ] }
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ bitand {
2007-09-20 18:09:08 -04:00
{ { number -1 } [ drop ] }
{ { -1 number } [ nip ] }
{ { @ @ } [ drop ] }
{ { number 0 } [ nip ] }
{ { 0 number } [ drop ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ bitor {
2007-09-20 18:09:08 -04:00
{ { number 0 } [ drop ] }
{ { 0 number } [ nip ] }
{ { @ @ } [ drop ] }
{ { number -1 } [ nip ] }
{ { -1 number } [ drop ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ bitxor {
2007-09-20 18:09:08 -04:00
{ { number 0 } [ drop ] }
{ { 0 number } [ nip ] }
{ { number -1 } [ drop bitnot ] }
{ { -1 number } [ nip bitnot ] }
{ { @ @ } [ 2drop 0 ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
2008-04-18 17:51:09 -04:00
\ shift {
2007-09-20 18:09:08 -04:00
{ { 0 number } [ drop ] }
{ { number 0 } [ drop ] }
2008-04-18 17:51:09 -04:00
} define-math-identities
2007-09-20 18:09:08 -04:00
: math-closure ( class -- newclass )
2008-04-19 03:11:55 -04:00
{ null fixnum bignum integer rational float real number }
2008-05-02 03:51:38 -04:00
[ class<= ] with find nip number or ;
2007-09-20 18:09:08 -04:00
: fits? ( interval class -- ? )
"interval" word-prop dup
[ interval-subset? ] [ 2drop t ] if ;
2008-04-19 03:11:55 -04:00
: math-output-class ( node upgrades -- newclass )
>r
in-d>> null [ value-class* math-closure math-class-max ] reduce
dup r> at swap or ;
2007-09-20 18:09:08 -04:00
: won't-overflow? ( interval node -- ? )
2008-05-02 03:51:38 -04:00
node-in-d [ value-class* fixnum class<= ] all?
2007-09-20 18:09:08 -04:00
swap fixnum fits? and ;
: post-process ( class interval node -- classes intervals )
dupd won't-overflow?
2007-12-08 17:45:51 -05:00
[ >r dup { f integer } member? [ drop fixnum ] when r> ] when
2008-03-29 21:36:58 -04:00
[ dup [ 1array ] when ] bi@ ;
2007-09-20 18:09:08 -04:00
: math-output-interval-1 ( node word -- interval )
dup [
>r node-in-d first value-interval* dup
[ r> execute ] [ r> 2drop f ] if
] [
2drop f
] if ; inline
2008-04-19 03:11:55 -04:00
: math-output-class/interval-1 ( node word -- classes intervals )
2008-04-19 05:52:34 -04:00
[ drop { } math-output-class 1array ]
[ math-output-interval-1 1array ] 2bi ;
2007-09-20 18:09:08 -04:00
{
2008-04-19 03:11:55 -04:00
{ bitnot interval-bitnot }
{ fixnum-bitnot interval-bitnot }
{ bignum-bitnot interval-bitnot }
2007-09-20 18:09:08 -04:00
} [
2008-04-19 03:11:55 -04:00
[ math-output-class/interval-1 ] curry
"output-classes" set-word-prop
] assoc-each
2007-09-20 18:09:08 -04:00
: intervals ( node -- i1 i2 )
2008-03-29 21:36:58 -04:00
node-in-d first2 [ value-interval* ] bi@ ;
2007-09-20 18:09:08 -04:00
: math-output-interval-2 ( node word -- interval )
dup [
>r intervals 2dup and [ r> execute ] [ r> 3drop f ] if
] [
2drop f
] if ; inline
2008-04-19 03:11:55 -04:00
: math-output-class/interval-2 ( node upgrades word -- classes intervals )
2007-09-20 18:09:08 -04:00
pick >r
>r over r>
math-output-interval-2
>r math-output-class r>
r> post-process ; inline
{
2008-04-19 03:11:55 -04:00
{ + { { fixnum integer } } interval+ }
{ - { { fixnum integer } } interval- }
{ * { { fixnum integer } } interval* }
{ / { { fixnum rational } { integer rational } } interval/ }
{ /i { { fixnum integer } } interval/i }
{ shift { { fixnum integer } } interval-shift-safe }
2007-09-20 18:09:08 -04:00
} [
first3 [
2008-04-18 17:51:09 -04:00
[
math-output-class/interval-2
] 2curry "output-classes" set-word-prop
] 2curry each-derived-op
2007-09-20 18:09:08 -04:00
] each
: real-value? ( value -- n ? )
dup value? [ value-literal dup real? ] [ drop f f ] if ;
: mod-range ( n -- interval )
dup neg swap (a,b) ;
: rem-range ( n -- interval )
0 swap [a,b) ;
: bitand-range ( n -- interval )
dup 0 < [ drop f ] [ 0 swap [a,b] ] if ;
: math-output-interval-special ( node word -- interval )
dup [
>r node-in-d second real-value?
[ r> execute ] [ r> 2drop f ] if
] [
2drop f
] if ; inline
: math-output-class/interval-special ( node min word -- classes intervals )
pick >r
>r over r>
math-output-interval-special
>r math-output-class r>
r> post-process ; inline
{
2008-04-19 03:11:55 -04:00
{ mod { } mod-range }
{ rem { { fixnum integer } } rem-range }
2007-09-20 18:09:08 -04:00
2008-04-19 03:11:55 -04:00
{ bitand { } bitand-range }
{ bitor { } f }
{ bitxor { } f }
2007-09-20 18:09:08 -04:00
} [
first3 [
2008-04-18 17:51:09 -04:00
[
math-output-class/interval-special
] 2curry "output-classes" set-word-prop
] 2curry each-derived-op
2007-09-20 18:09:08 -04:00
] each
: twiddle-interval ( i1 -- i2 )
dup [
node get node-in-d
2008-05-02 03:51:38 -04:00
[ value-class* integer class<= ] all?
2007-09-20 18:09:08 -04:00
[ integral-closure ] when
] when ;
: (comparison-constraints) ( i1 i2 word class -- )
node get [
>r execute twiddle-interval 0 `input interval,
r> 0 `output class,
] set-constraints ; inline
: comparison-constraints ( node true false -- )
>r >r dup node set intervals dup [
2dup
r> \ f class-not (comparison-constraints)
2007-09-20 18:09:08 -04:00
r> \ f (comparison-constraints)
] [
r> r> 2drop 2drop
] if ; inline
{
{ < assume< assume>= }
{ <= assume<= assume> }
{ > assume> assume<= }
{ >= assume>= assume< }
} [
2008-04-18 17:51:09 -04:00
first3 [
[
[ comparison-constraints ] with-scope
] 2curry "constraints" set-word-prop
] 2curry each-derived-op
2007-09-20 18:09:08 -04:00
] each
{
alien-signed-1
alien-unsigned-1
alien-signed-2
alien-unsigned-2
alien-signed-4
alien-unsigned-4
alien-signed-8
alien-unsigned-8
} [
dup word-name {
{
[ "alien-signed-" ?head ]
[ string>number 8 * 1- 2^ dup neg swap 1- [a,b] ]
}
{
[ "alien-unsigned-" ?head ]
[ string>number 8 * 2^ 1- 0 swap [a,b] ]
}
} cond 1array
[ nip f swap ] curry "output-classes" set-word-prop
] each
! Associate intervals to classes
\ fixnum
most-negative-fixnum most-positive-fixnum [a,b]
"interval" set-word-prop
\ array-capacity
0 max-array-capacity [a,b]
"interval" set-word-prop
{
{ >fixnum fixnum }
{ >bignum bignum }
{ >float float }
} [
[
over node-in-d first value-interval*
dup pick fits? [ drop f ] unless
rot post-process
] curry "output-classes" set-word-prop
] assoc-each
! Removing overflow checks
: remove-overflow-check? ( #call -- ? )
2008-04-19 03:11:55 -04:00
dup out-d>> first node-class
2008-05-02 03:51:38 -04:00
[ fixnum class<= ] [ null eq? not ] bi and ;
2007-09-20 18:09:08 -04:00
{
{ + [ fixnum+fast ] }
2008-04-18 17:51:09 -04:00
{ +-integer-fixnum [ fixnum+fast ] }
2007-09-20 18:09:08 -04:00
{ - [ fixnum-fast ] }
{ * [ fixnum*fast ] }
2008-04-18 17:51:09 -04:00
{ *-integer-fixnum [ fixnum*fast ] }
{ shift [ fixnum-shift-fast ] }
2007-09-20 18:09:08 -04:00
{ fixnum+ [ fixnum+fast ] }
{ fixnum- [ fixnum-fast ] }
{ fixnum* [ fixnum*fast ] }
{ fixnum-shift [ fixnum-shift-fast ] }
2007-09-20 18:09:08 -04:00
} [
[
[ dup remove-overflow-check? ] ,
[ f splice-quot ] curry ,
2007-09-20 18:09:08 -04:00
] { } make 1array define-optimizers
] assoc-each
! Remove redundant comparisons
2008-03-07 22:27:00 -05:00
: intervals-first2 ( #call -- first second )
2007-09-20 18:09:08 -04:00
dup dup node-in-d first node-interval
2008-03-07 22:27:00 -05:00
swap dup node-in-d second node-interval ;
: known-comparison? ( #call -- ? )
intervals-first2 and ;
2007-09-20 18:09:08 -04:00
: perform-comparison ( #call word -- result )
2008-03-07 22:27:00 -05:00
>r intervals-first2 r> execute ; inline
2007-09-20 18:09:08 -04:00
2008-02-21 15:15:45 -05:00
: foldable-comparison? ( #call word -- ? )
2007-09-20 18:09:08 -04:00
>r dup known-comparison? [
r> perform-comparison incomparable eq? not
] [
r> 2drop f
] if ; inline
: fold-comparison ( #call word -- node )
dupd perform-comparison 1array inline-literals ;
{
{ < interval< }
{ <= interval<= }
{ > interval> }
{ >= interval>= }
} [
[
2008-04-18 17:51:09 -04:00
[
dup [ dupd foldable-comparison? ] curry ,
[ fold-comparison ] curry ,
] { } make 1array define-optimizers
] curry each-derived-op
2007-09-20 18:09:08 -04:00
] assoc-each
! The following words are handled in a similar way except if
! the only consumer is a >fixnum we remove the overflow check
! too
: consumed-by? ( node word -- ? )
swap sole-consumer
dup #call? [ node-param eq? ] [ 2drop f ] if ;
2008-04-17 13:22:24 -04:00
: coerced-to-fixnum? ( #call -- ? )
2008-05-02 03:51:38 -04:00
dup dup node-in-d [ node-class integer class<= ] with all?
2008-04-17 13:22:24 -04:00
[ \ >fixnum consumed-by? ] [ drop f ] if ;
2007-09-20 18:09:08 -04:00
{
2008-04-18 17:51:09 -04:00
{ + [ [ >fixnum ] bi@ fixnum+fast ] }
{ - [ [ >fixnum ] bi@ fixnum-fast ] }
{ * [ [ >fixnum ] bi@ fixnum*fast ] }
2007-09-20 18:09:08 -04:00
} [
2008-04-18 17:51:09 -04:00
>r derived-ops r> [
2007-09-20 18:09:08 -04:00
[
2008-04-18 17:51:09 -04:00
[
dup remove-overflow-check?
over coerced-to-fixnum? or
] ,
[ f splice-quot ] curry ,
] { } make 1array define-optimizers
] curry each
2007-09-20 18:09:08 -04:00
] assoc-each
2008-01-12 21:37:44 -05:00
2008-04-17 13:22:24 -04:00
: convert-rem-to-and? ( #call -- ? )
dup node-in-d {
2008-05-02 03:51:38 -04:00
{ [ 2dup first node-class integer class<= not ] [ f ] }
2008-04-17 13:22:24 -04:00
{ [ 2dup second node-literal integer? not ] [ f ] }
{ [ 2dup second node-literal power-of-2? not ] [ f ] }
[ t ]
} cond 2nip ;
: convert-mod-to-and? ( #call -- ? )
dup dup node-in-d first node-interval 0 [a,inf] interval-subset?
[ convert-rem-to-and? ] [ drop f ] if ;
: convert-mod-to-and ( #call -- node )
dup
dup node-in-d second node-literal 1-
[ nip bitand ] curry f splice-quot ;
2008-04-18 17:51:09 -04:00
\ mod [
2008-04-17 13:22:24 -04:00
{
{
[ dup convert-mod-to-and? ]
[ convert-mod-to-and ]
}
} define-optimizers
2008-04-18 17:51:09 -04:00
] each-derived-op
2008-04-17 13:22:24 -04:00
\ rem {
{
[ dup convert-rem-to-and? ]
[ convert-mod-to-and ]
}
} define-optimizers
: fixnumify-bitand? ( #call -- ? )
dup node-in-d second node-interval fixnum fits? ;
: fixnumify-bitand ( #call -- node )
2008-04-18 17:51:09 -04:00
[ [ >fixnum ] bi@ fixnum-bitand ] f splice-quot ;
2008-04-17 13:22:24 -04:00
\ bitand {
{
[ dup fixnumify-bitand? ]
[ fixnumify-bitand ]
}
} define-optimizers