Fix some problems with arithmetic type inference, exposed by recent changes to log2 word

- declared input type for bignum-shift was stricter than the runtime behavior, leading to bad propagation of type info if shift count was a bignum
- types inferred for type functions which used number-valued/integer-valued/real-valued were not always precise, eg bignum bignum bitxor => integer
- add interval-log2, type function for (log2)
- remove math-class-min, it was useless
db4
Slava Pestov 2008-12-07 19:44:49 -06:00
parent 3469d50b91
commit e4f8448eb1
9 changed files with 116 additions and 51 deletions

View File

@ -375,3 +375,9 @@ DEFER: loop-bbb
: loop-ccc ( -- ) loop-bbb ; : loop-ccc ( -- ) loop-bbb ;
[ 0 ] [ 0 counter set loop-ccc counter get ] unit-test [ 0 ] [ 0 counter set loop-ccc counter get ] unit-test
! Type inference issue
[ 4 3 ] [
1 >bignum 2 >bignum
[ { bignum integer } declare [ shift ] keep 1+ ] compile-call
] unit-test

View File

@ -1,11 +1,12 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel effects accessors math math.private math.libm USING: kernel effects accessors math math.private
math.partial-dispatch math.intervals math.parser math.order math.integers.private math.partial-dispatch math.intervals
layouts words sequences sequences.private arrays assocs classes math.parser math.order layouts words sequences sequences.private
classes.algebra combinators generic.math splitting fry locals arrays assocs classes classes.algebra combinators generic.math
classes.tuple alien.accessors classes.tuple.private slots.private splitting fry locals classes.tuple alien.accessors
definitions strings.private vectors hashtables classes.tuple.private slots.private definitions strings.private
vectors hashtables
stack-checker.state stack-checker.state
compiler.tree.comparisons compiler.tree.comparisons
compiler.tree.propagation.info compiler.tree.propagation.info
@ -76,14 +77,17 @@ most-negative-fixnum most-positive-fixnum [a,b]
[ rational math-class-max ] dip [ rational math-class-max ] dip
] unless ; ] unless ;
: ensure-math-class ( class must-be -- class' )
[ class<= ] 2keep ? ;
: number-valued ( class interval -- class' interval' ) : number-valued ( class interval -- class' interval' )
[ number math-class-min ] dip ; [ number ensure-math-class ] dip ;
: integer-valued ( class interval -- class' interval' ) : integer-valued ( class interval -- class' interval' )
[ integer math-class-min ] dip ; [ integer ensure-math-class ] dip ;
: real-valued ( class interval -- class' interval' ) : real-valued ( class interval -- class' interval' )
[ real math-class-min ] dip ; [ real ensure-math-class ] dip ;
: float-valued ( class interval -- class' interval' ) : float-valued ( class interval -- class' interval' )
over null-class? [ over null-class? [
@ -230,7 +234,7 @@ generic-comparison-ops [
} [ } [
[ [
in-d>> second value-info >literal< in-d>> second value-info >literal<
[ power-of-2? [ 1- bitand ] f ? ] when [ dup integer? [ power-of-2? [ 1- bitand ] f ? ] [ drop f ] if ] when
] "custom-inlining" set-word-prop ] "custom-inlining" set-word-prop
] each ] each
@ -247,6 +251,15 @@ generic-comparison-ops [
] "custom-inlining" set-word-prop ] "custom-inlining" set-word-prop
] each ] each
{ numerator denominator }
[ [ drop integer <class-info> ] "outputs" set-word-prop ] each
{ (log2) fixnum-log2 bignum-log2 } [
[
[ class>> ] [ interval>> interval-log2 ] bi <class/interval-info>
] "outputs" set-word-prop
] each
\ string-nth [ \ string-nth [
2drop fixnum 0 23 2^ [a,b] <class/interval-info> 2drop fixnum 0 23 2^ [a,b] <class/interval-info>
] "outputs" set-word-prop ] "outputs" set-word-prop

View File

@ -34,17 +34,57 @@ IN: compiler.tree.propagation.tests
[ V{ fixnum } ] [ [ { fixnum } declare bitnot ] final-classes ] unit-test [ V{ fixnum } ] [ [ { fixnum } declare bitnot ] final-classes ] unit-test
[ V{ number } ] [ [ + ] final-classes ] unit-test ! Test type propagation for math ops
: cleanup-math-class ( obj -- class )
{ null fixnum bignum integer ratio rational float real complex number }
[ class= ] with find nip ;
[ V{ float } ] [ [ { float integer } declare + ] final-classes ] unit-test : final-math-class ( quot -- class )
final-classes first cleanup-math-class ;
[ V{ float } ] [ [ /f ] final-classes ] unit-test [ number ] [ [ + ] final-math-class ] unit-test
[ V{ integer } ] [ [ /i ] final-classes ] unit-test [ bignum ] [ [ { fixnum bignum } declare + ] final-math-class ] unit-test
[ V{ integer } ] [ [ integer ] [ [ { fixnum integer } declare + ] final-math-class ] unit-test
[ { integer } declare bitnot ] final-classes
] unit-test [ bignum ] [ [ { integer bignum } declare + ] final-math-class ] unit-test
[ integer ] [ [ { fixnum fixnum } declare + ] final-math-class ] unit-test
[ float ] [ [ { float integer } declare + ] final-math-class ] unit-test
[ float ] [ [ { real float } declare + ] final-math-class ] unit-test
[ float ] [ [ { float real } declare + ] final-math-class ] unit-test
[ rational ] [ [ { ratio ratio } declare + ] final-math-class ] unit-test
[ rational ] [ [ { rational ratio } declare + ] final-math-class ] unit-test
[ number ] [ [ { complex complex } declare + ] final-math-class ] unit-test
[ float ] [ [ /f ] final-math-class ] unit-test
[ float ] [ [ { real real } declare /f ] final-math-class ] unit-test
[ integer ] [ [ /i ] final-math-class ] unit-test
[ integer ] [ [ { integer float } declare /i ] final-math-class ] unit-test
[ integer ] [ [ { float float } declare /i ] final-math-class ] unit-test
[ integer ] [ [ { integer } declare bitnot ] final-math-class ] unit-test
[ null ] [ [ { null null } declare + ] final-math-class ] unit-test
[ null ] [ [ { null fixnum } declare + ] final-math-class ] unit-test
[ float ] [ [ { float fixnum } declare + ] final-math-class ] unit-test
[ bignum ] [ [ { bignum bignum } declare bitxor ] final-math-class ] unit-test
[ float ] [ [ { float float } declare mod ] final-math-class ] unit-test
[ V{ integer } ] [ [ 255 bitand ] final-classes ] unit-test [ V{ integer } ] [ [ 255 bitand ] final-classes ] unit-test
@ -66,18 +106,6 @@ IN: compiler.tree.propagation.tests
[ { fixnum } declare 615949 * ] final-classes [ { fixnum } declare 615949 * ] final-classes
] unit-test ] unit-test
[ V{ null } ] [
[ { null null } declare + ] final-classes
] unit-test
[ V{ null } ] [
[ { null fixnum } declare + ] final-classes
] unit-test
[ V{ float } ] [
[ { float fixnum } declare + ] final-classes
] unit-test
[ V{ fixnum } ] [ [ V{ fixnum } ] [
[ 255 bitand >fixnum 3 bitor ] final-classes [ 255 bitand >fixnum 3 bitor ] final-classes
] unit-test ] unit-test
@ -279,14 +307,6 @@ IN: compiler.tree.propagation.tests
] final-classes ] final-classes
] unit-test ] unit-test
[ V{ float } ] [
[ { real float } declare + ] final-classes
] unit-test
[ V{ float } ] [
[ { float real } declare + ] final-classes
] unit-test
[ V{ fixnum } ] [ [ V{ fixnum } ] [
[ { fixnum fixnum } declare 7 bitand neg shift ] final-classes [ { fixnum fixnum } declare 7 bitand neg shift ] final-classes
] unit-test ] unit-test
@ -604,6 +624,22 @@ MIXIN: empty-mixin
[ { integer } declare 127 bitand ] final-info first interval>> [ { integer } declare 127 bitand ] final-info first interval>>
] unit-test ] unit-test
[ V{ bignum } ] [
[ { bignum } declare dup 1- bitxor ] final-classes
] unit-test
[ V{ bignum integer } ] [
[ { bignum integer } declare [ shift ] keep ] final-classes
] unit-test
[ V{ fixnum } ] [
[ { fixnum } declare log2 ] final-classes
] unit-test
[ V{ word } ] [
[ { fixnum } declare log2 0 >= ] final-classes
] unit-test
! [ V{ string } ] [ ! [ V{ string } ] [
! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes ! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes
! ] unit-test ! ] unit-test

View File

@ -44,7 +44,8 @@ ARTICLE: "math-intervals-arithmetic" "Interval arithmetic"
{ $subsection interval-bitnot } { $subsection interval-bitnot }
{ $subsection interval-recip } { $subsection interval-recip }
{ $subsection interval-2/ } { $subsection interval-2/ }
{ $subsection interval-abs } ; { $subsection interval-abs }
{ $subsection interval-log2 } ;
ARTICLE: "math-intervals-sets" "Set-theoretic operations on intervals" ARTICLE: "math-intervals-sets" "Set-theoretic operations on intervals"
{ $subsection interval-contains? } { $subsection interval-contains? }
@ -203,6 +204,10 @@ HELP: interval-abs
{ $values { "i1" interval } { "i2" interval } } { $values { "i1" interval } { "i2" interval } }
{ $description "Absolute value of an interval." } ; { $description "Absolute value of an interval." } ;
HELP: interval-log2
{ $values { "i1" interval } { "i2" interval } }
{ $description "Integer-valued Base-2 logarithm of an interval." } ;
HELP: interval-intersect HELP: interval-intersect
{ $values { "i1" interval } { "i2" interval } { "i3" "an " { $link interval } " or " { $link f } } } { $values { "i1" interval } { "i2" interval } { "i3" "an " { $link interval } " or " { $link f } } }
{ $description "Outputs the set-theoretic intersection of " { $snippet "i1" } " and " { $snippet "i2" } ". If " { $snippet "i1" } " and " { $snippet "i2" } " do not intersect, outputs " { $link f } "." } ; { $description "Outputs the set-theoretic intersection of " { $snippet "i1" } " and " { $snippet "i2" } ". If " { $snippet "i1" } " and " { $snippet "i2" } " do not intersect, outputs " { $link f } "." } ;

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
! Based on Slate's src/unfinished/interval.slate by Brian Rice. ! Based on Slate's src/unfinished/interval.slate by Brian Rice.
USING: accessors kernel sequences arrays math math.order USING: accessors kernel sequences arrays math math.order
combinators generic ; combinators generic layouts ;
IN: math.intervals IN: math.intervals
SYMBOL: empty-interval SYMBOL: empty-interval
@ -365,7 +365,7 @@ SYMBOL: incomparable
2dup [ interval-nonnegative? ] both? 2dup [ interval-nonnegative? ] both?
[ [
[ interval>points [ first ] bi@ ] bi@ [ interval>points [ first ] bi@ ] bi@
4array supremum 0 swap next-power-of-2 [a,b] 4array supremum 0 swap >integer next-power-of-2 [a,b]
] [ 2drop [-inf,inf] ] if ] [ 2drop [-inf,inf] ] if
] do-empty-interval ; ] do-empty-interval ;
@ -373,6 +373,18 @@ SYMBOL: incomparable
#! Inaccurate. #! Inaccurate.
interval-bitor ; interval-bitor ;
: interval-log2 ( i1 -- i2 )
{
{ empty-interval [ empty-interval ] }
{ full-interval [ 0 [a,inf] ] }
[
to>> first 1 max dup most-positive-fixnum >
[ drop full-interval interval-log2 ]
[ 1+ >integer log2 0 swap [a,b] ]
if
]
} case ;
: assume< ( i1 i2 -- i3 ) : assume< ( i1 i2 -- i3 )
dup special-interval? [ drop ] [ dup special-interval? [ drop ] [
to>> first [-inf,a) interval-intersect to>> first [-inf,a) interval-intersect

View File

@ -28,9 +28,6 @@ PREDICATE: math-class < class
: math-class-max ( class1 class2 -- class ) : math-class-max ( class1 class2 -- class )
[ math-class<=> ] most ; [ math-class<=> ] most ;
: math-class-min ( class1 class2 -- class )
[ swap math-class<=> ] most ;
: (math-upgrade) ( max class -- quot ) : (math-upgrade) ( max class -- quot )
dupd = [ drop [ ] ] [ "coercer" word-prop [ ] or ] if ; dupd = [ drop [ ] ] [ "coercer" word-prop [ ] or ] if ;

View File

@ -45,9 +45,6 @@ M: fixnum bit? neg shift 1 bitand 0 > ;
M: fixnum (log2) fixnum-log2 ; M: fixnum (log2) fixnum-log2 ;
M: integer next-power-of-2
dup 2 <= [ drop 2 ] [ 1- log2 1+ 2^ ] if ;
M: bignum >fixnum bignum>fixnum ; M: bignum >fixnum bignum>fixnum ;
M: bignum >bignum ; M: bignum >bignum ;
@ -76,7 +73,7 @@ M: bignum /mod bignum/mod ;
M: bignum bitand bignum-bitand ; M: bignum bitand bignum-bitand ;
M: bignum bitor bignum-bitor ; M: bignum bitor bignum-bitor ;
M: bignum bitxor bignum-bitxor ; M: bignum bitxor bignum-bitxor ;
M: bignum shift bignum-shift ; M: bignum shift >fixnum bignum-shift ;
M: bignum bitnot bignum-bitnot ; M: bignum bitnot bignum-bitnot ;
M: bignum bit? bignum-bit? ; M: bignum bit? bignum-bit? ;

View File

@ -103,9 +103,8 @@ M: float fp-infinity? ( float -- ? )
drop f drop f
] if ; ] if ;
GENERIC: next-power-of-2 ( m -- n ) foldable : next-power-of-2 ( m -- n )
dup 2 <= [ drop 2 ] [ 1- log2 1+ 2^ ] if ; inline
M: real next-power-of-2 1+ >integer next-power-of-2 ;
: power-of-2? ( n -- ? ) : power-of-2? ( n -- ? )
dup 0 <= [ drop f ] [ dup 1- bitand zero? ] if ; foldable dup 0 <= [ drop f ] [ dup 1- bitand zero? ] if ; foldable

View File

@ -197,7 +197,7 @@ void primitive_bignum_xor(void)
void primitive_bignum_shift(void) void primitive_bignum_shift(void)
{ {
F_FIXNUM y = to_fixnum(dpop()); F_FIXNUM y = untag_fixnum_fast(dpop());
F_ARRAY* x = untag_object(dpop()); F_ARRAY* x = untag_object(dpop());
dpush(tag_bignum(bignum_arithmetic_shift(x,y))); dpush(tag_bignum(bignum_arithmetic_shift(x,y)));
} }