Intervals now use a special singleton for the full interval to eliminate FP math in the common case; fix a bug in value-info<=

db4
Slava Pestov 2008-11-11 08:30:14 -06:00
parent a1f6bb0999
commit 43335d9c36
4 changed files with 61 additions and 33 deletions

View File

@ -70,3 +70,7 @@ TUPLE: test-tuple { x read-only } ;
f f 3 <literal-info> 3array test-tuple <tuple-info> dup f f 3 <literal-info> 3array test-tuple <tuple-info> dup
object-info value-info-intersect = object-info value-info-intersect =
] unit-test ] unit-test
[ t ] [
null-info 3 <literal-info> value-info<=
] unit-test

View File

@ -34,7 +34,7 @@ slots ;
: null-info T{ value-info f null empty-interval } ; inline : null-info T{ value-info f null empty-interval } ; inline
: object-info T{ value-info f object T{ interval f { -1.0/0.0 t } { 1.0/0.0 t } } } ; inline : object-info T{ value-info f object full-interval } ; inline
: class-interval ( class -- interval ) : class-interval ( class -- interval )
dup real class<= dup real class<=
@ -43,7 +43,7 @@ slots ;
: interval>literal ( class interval -- literal literal? ) : interval>literal ( class interval -- literal literal? )
#! If interval has zero length and the class is sufficiently #! If interval has zero length and the class is sufficiently
#! precise, we can turn it into a literal #! precise, we can turn it into a literal
dup empty-interval eq? [ dup special-interval? [
2drop f f 2drop f f
] [ ] [
dup from>> first { dup from>> first {
@ -243,7 +243,7 @@ DEFER: (value-info-union)
: literals<= ( info1 info2 -- ? ) : literals<= ( info1 info2 -- ? )
{ {
{ [ dup literal?>> not ] [ 2drop t ] } { [ dup literal?>> not ] [ 2drop t ] }
{ [ over literal?>> not ] [ 2drop f ] } { [ over literal?>> not ] [ drop class>> null-class? ] }
[ [ literal>> ] bi@ eql? ] [ [ literal>> ] bi@ eql? ]
} cond ; } cond ;

View File

@ -95,6 +95,10 @@ IN: math.intervals.tests
[ empty-interval ] [ 0 5 (a,b] empty-interval interval-intersect ] unit-test [ empty-interval ] [ 0 5 (a,b] empty-interval interval-intersect ] unit-test
[ t ] [
0 1 (a,b) full-interval interval-intersect 0 1 (a,b) =
] unit-test
[ t ] [ [ t ] [
empty-interval empty-interval interval-subset? empty-interval empty-interval interval-subset?
] unit-test ] unit-test
@ -209,22 +213,28 @@ IN: math.intervals.tests
! Interval random tester ! Interval random tester
: random-element ( interval -- n ) : random-element ( interval -- n )
dup to>> first over from>> first tuck - random + dup full-interval eq? [
2dup swap interval-contains? [ drop 32 random-bits 31 2^ -
nip
] [ ] [
drop random-element dup to>> first over from>> first tuck - random +
2dup swap interval-contains? [
nip
] [
drop random-element
] if
] if ; ] if ;
: random-interval ( -- interval ) : random-interval ( -- interval )
2000 random 1000 - dup 2 1000 random + + 10 random 0 = [ full-interval ] [
1 random zero? [ [ neg ] bi@ swap ] when 2000 random 1000 - dup 2 1000 random + +
4 random { 1 random zero? [ [ neg ] bi@ swap ] when
{ 0 [ [a,b] ] } 4 random {
{ 1 [ [a,b) ] } { 0 [ [a,b] ] }
{ 2 [ (a,b) ] } { 1 [ [a,b) ] }
{ 3 [ (a,b] ] } { 2 [ (a,b) ] }
} case ; { 3 [ (a,b] ] }
} case
] if ;
: random-unary-op ( -- pair ) : random-unary-op ( -- pair )
{ {
@ -263,7 +273,7 @@ IN: math.intervals.tests
{ bitand interval-bitand } { bitand interval-bitand }
{ bitor interval-bitor } { bitor interval-bitor }
{ bitxor interval-bitxor } { bitxor interval-bitxor }
{ shift interval-shift } ! { shift interval-shift }
{ min interval-min } { min interval-min }
{ max interval-max } { max interval-max }
} }

View File

@ -7,6 +7,8 @@ IN: math.intervals
SYMBOL: empty-interval SYMBOL: empty-interval
SYMBOL: full-interval
TUPLE: interval { from read-only } { to read-only } ; TUPLE: interval { from read-only } { to read-only } ;
: <interval> ( from to -- int ) : <interval> ( from to -- int )
@ -46,8 +48,7 @@ TUPLE: interval { from read-only } { to read-only } ;
: (a,inf] ( a -- interval ) 1./0. (a,b] ; inline : (a,inf] ( a -- interval ) 1./0. (a,b] ; inline
: [-inf,inf] ( -- interval ) : [-inf,inf] ( -- interval ) full-interval ; inline
T{ interval f { -1./0. t } { 1./0. t } } ; inline
: compare-endpoints ( p1 p2 quot -- ? ) : compare-endpoints ( p1 p2 quot -- ? )
>r over first over first r> call [ >r over first over first r> call [
@ -99,8 +100,10 @@ TUPLE: interval { from read-only } { to read-only } ;
: do-empty-interval ( i1 i2 quot -- i3 ) : do-empty-interval ( i1 i2 quot -- i3 )
{ {
{ [ pick empty-interval eq? ] [ drop drop ] } { [ pick empty-interval eq? ] [ 2drop ] }
{ [ over empty-interval eq? ] [ drop nip ] } { [ over empty-interval eq? ] [ drop nip ] }
{ [ pick full-interval eq? ] [ 2drop ] }
{ [ over full-interval eq? ] [ drop nip ] }
[ call ] [ call ]
} cond ; inline } cond ; inline
@ -112,8 +115,10 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-intersect ( i1 i2 -- i3 ) : interval-intersect ( i1 i2 -- i3 )
{ {
{ [ dup empty-interval eq? ] [ nip ] }
{ [ over empty-interval eq? ] [ drop ] } { [ over empty-interval eq? ] [ drop ] }
{ [ dup empty-interval eq? ] [ nip ] }
{ [ over full-interval eq? ] [ nip ] }
{ [ dup full-interval eq? ] [ drop ] }
[ [
[ interval>points ] bi@ swapd [ interval>points ] bi@ swapd
[ [ swap endpoint< ] most ] [ [ swap endpoint< ] most ]
@ -127,8 +132,10 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-union ( i1 i2 -- i3 ) : interval-union ( i1 i2 -- i3 )
{ {
{ [ dup empty-interval eq? ] [ drop ] }
{ [ over empty-interval eq? ] [ nip ] } { [ over empty-interval eq? ] [ nip ] }
{ [ dup empty-interval eq? ] [ drop ] }
{ [ over full-interval eq? ] [ drop ] }
{ [ dup full-interval eq? ] [ nip ] }
[ [ interval>points 2array ] bi@ append points>interval ] [ [ interval>points 2array ] bi@ append points>interval ]
} cond ; } cond ;
@ -137,9 +144,11 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-contains? ( x int -- ? ) : interval-contains? ( x int -- ? )
dup empty-interval eq? [ 2drop f ] [ dup empty-interval eq? [ 2drop f ] [
[ from>> first2 [ >= ] [ > ] if ] dup full-interval eq? [ 2drop t ] [
[ to>> first2 [ <= ] [ < ] if ] [ from>> first2 [ >= ] [ > ] if ]
2bi and [ to>> first2 [ <= ] [ < ] if ]
2bi and
] if
] if ; ] if ;
: interval-zero? ( int -- ? ) : interval-zero? ( int -- ? )
@ -160,8 +169,11 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-sq ( i1 -- i2 ) dup interval* ; : interval-sq ( i1 -- i2 ) dup interval* ;
: special-interval? ( interval -- ? )
{ empty-interval full-interval } memq? ;
: interval-singleton? ( int -- ? ) : interval-singleton? ( int -- ? )
dup empty-interval eq? [ dup special-interval? [
drop f drop f
] [ ] [
interval>points interval>points
@ -173,6 +185,7 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-length ( int -- n ) : interval-length ( int -- n )
{ {
{ [ dup empty-interval eq? ] [ drop 0 ] } { [ dup empty-interval eq? ] [ drop 0 ] }
{ [ dup full-interval eq? ] [ drop 1/0. ] }
[ interval>points [ first ] bi@ swap - ] [ interval>points [ first ] bi@ swap - ]
} cond ; } cond ;
@ -211,7 +224,7 @@ TUPLE: interval { from read-only } { to read-only } ;
[ [ interval-closure ] bi@ [ min ] interval-op ] do-empty-interval ; [ [ interval-closure ] bi@ [ min ] interval-op ] do-empty-interval ;
: interval-interior ( i1 -- i2 ) : interval-interior ( i1 -- i2 )
dup empty-interval eq? [ dup special-interval? [
interval>points [ first ] bi@ (a,b) interval>points [ first ] bi@ (a,b)
] unless ; ] unless ;
@ -249,6 +262,7 @@ TUPLE: interval { from read-only } { to read-only } ;
: interval-abs ( i1 -- i2 ) : interval-abs ( i1 -- i2 )
{ {
{ [ dup empty-interval eq? ] [ ] } { [ dup empty-interval eq? ] [ ] }
{ [ dup full-interval eq? ] [ drop 0 [a,inf] ] }
{ [ 0 over interval-contains? ] [ (interval-abs) { 0 t } suffix points>interval ] } { [ 0 over interval-contains? ] [ (interval-abs) { 0 t } suffix points>interval ] }
[ (interval-abs) points>interval ] [ (interval-abs) points>interval ]
} cond ; } cond ;
@ -292,7 +306,7 @@ SYMBOL: incomparable
: interval< ( i1 i2 -- ? ) : interval< ( i1 i2 -- ? )
{ {
{ [ 2dup [ empty-interval eq? ] either? ] [ incomparable ] } { [ 2dup [ special-interval? ] either? ] [ incomparable ] }
{ [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] } { [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] }
{ [ 2dup left-endpoint-< ] [ f ] } { [ 2dup left-endpoint-< ] [ f ] }
{ [ 2dup right-endpoint-< ] [ f ] } { [ 2dup right-endpoint-< ] [ f ] }
@ -307,7 +321,7 @@ SYMBOL: incomparable
: interval<= ( i1 i2 -- ? ) : interval<= ( i1 i2 -- ? )
{ {
{ [ 2dup [ empty-interval eq? ] either? ] [ incomparable ] } { [ 2dup [ special-interval? ] either? ] [ incomparable ] }
{ [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] } { [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] }
{ [ 2dup right-endpoint-<= ] [ t ] } { [ 2dup right-endpoint-<= ] [ t ] }
[ incomparable ] [ incomparable ]
@ -360,27 +374,27 @@ SYMBOL: incomparable
interval-bitor ; interval-bitor ;
: assume< ( i1 i2 -- i3 ) : assume< ( i1 i2 -- i3 )
dup empty-interval eq? [ drop ] [ dup special-interval? [ drop ] [
to>> first [-inf,a) interval-intersect to>> first [-inf,a) interval-intersect
] if ; ] if ;
: assume<= ( i1 i2 -- i3 ) : assume<= ( i1 i2 -- i3 )
dup empty-interval eq? [ drop ] [ dup special-interval? [ drop ] [
to>> first [-inf,a] interval-intersect to>> first [-inf,a] interval-intersect
] if ; ] if ;
: assume> ( i1 i2 -- i3 ) : assume> ( i1 i2 -- i3 )
dup empty-interval eq? [ drop ] [ dup special-interval? [ drop ] [
from>> first (a,inf] interval-intersect from>> first (a,inf] interval-intersect
] if ; ] if ;
: assume>= ( i1 i2 -- i3 ) : assume>= ( i1 i2 -- i3 )
dup empty-interval eq? [ drop ] [ dup special-interval? [ drop ] [
from>> first [a,inf] interval-intersect from>> first [a,inf] interval-intersect
] if ; ] if ;
: integral-closure ( i1 -- i2 ) : integral-closure ( i1 -- i2 )
dup empty-interval eq? [ dup special-interval? [
[ from>> first2 [ 1+ ] unless ] [ from>> first2 [ 1+ ] unless ]
[ to>> first2 [ 1- ] unless ] [ to>> first2 [ 1- ] unless ]
bi [a,b] bi [a,b]