factor/core/optimizer/math/math.factor

474 lines
11 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.
2008-07-12 02:08:30 -04:00
USING: effects alien alien.accessors arrays generic hashtables
kernel assocs math math.libm math.private kernel.private
sequences words parser inference.class inference.dataflow
vectors strings sbufs io namespaces assocs quotations
math.intervals sequences.private combinators splitting layouts
math.parser classes classes.algebra generic.math
optimizer.pattern-match optimizer.backend optimizer.def-use
optimizer.inlining optimizer.math.partial generic.standard
system accessors ;
2007-09-20 18:09:08 -04:00
IN: optimizer.math
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/-safe }
2008-04-19 03:11:55 -04:00
{ /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
2008-07-12 02:08:30 -04:00
: math-output-class/interval-2-fast ( node word -- classes intervals )
math-output-interval-2 fixnum [ 1array ] bi@ swap ; inline
[
{ + interval+ }
{ - interval- }
{ * interval* }
{ shift interval-shift-safe }
] [
first2 [
[
math-output-class/interval-2-fast
] curry "output-classes" set-word-prop
] curry each-fast-derived-op
] each
2007-09-20 18:09:08 -04:00
: 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 name>> {
2007-09-20 18:09:08 -04:00
{
[ "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
2008-07-12 02:08:30 -04:00
{ + - * / }
[ { number number } "input-classes" set-word-prop ] each
{ /f < > <= >= }
[ { real real } "input-classes" set-word-prop ] each
{ /i bitand bitor bitxor bitnot shift }
[ { integer integer } "input-classes" set-word-prop ] each
{
fcosh
flog
fsinh
fexp
fasin
facosh
fasinh
ftanh
fatanh
facos
fpow
fatan
fatan2
fcos
ftan
fsin
fsqrt
} [
dup stack-effect
[ in>> length real <repetition> "input-classes" set-word-prop ]
[ out>> length float <repetition> "default-output-classes" set-word-prop ]
2bi
] each