]> gitweb.factorcode.org Git - factor.git/commitdiff
Change equality semantics
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 2 Sep 2008 07:02:05 +0000 (02:02 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 2 Sep 2008 07:02:05 +0000 (02:02 -0500)
25 files changed:
basis/cocoa/cocoa-tests.factor
basis/compiler/tree/cleanup/cleanup-tests.factor
basis/compiler/tree/finalization/finalization.factor
basis/compiler/tree/propagation/known-words/known-words.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/math/complex/complex-docs.factor
basis/math/complex/complex-tests.factor
basis/math/complex/complex.factor
basis/math/functions/functions-docs.factor
basis/math/functions/functions-tests.factor
basis/math/functions/functions.factor
basis/math/intervals/intervals-tests.factor
basis/math/ratios/ratios-tests.factor
basis/math/ratios/ratios.factor
core/classes/tuple/tuple-tests.factor
core/generic/standard/standard-tests.factor
core/hashtables/hashtables-tests.factor
core/kernel/kernel-docs.factor
core/math/floats/floats-tests.factor
core/math/floats/floats.factor
core/math/integers/integers.factor
core/math/math-docs.factor
core/math/math.factor
core/sequences/sequences-tests.factor
core/sequences/sequences.factor

index 4b56d81626922c73020c51f2c6546d6b75ef403c..631695340e07b440f53087d2370ec7ccc0a9d459 100644 (file)
@@ -20,10 +20,10 @@ CLASS: {
 
 test-foo
 
-[ 1 ] [ "x" get NSRect-x ] unit-test
-[ 2 ] [ "x" get NSRect-y ] unit-test
-[ 101 ] [ "x" get NSRect-w ] unit-test
-[ 102 ] [ "x" get NSRect-h ] unit-test
+[ 1.0 ] [ "x" get NSRect-x ] unit-test
+[ 2.0 ] [ "x" get NSRect-y ] unit-test
+[ 101.0 ] [ "x" get NSRect-w ] unit-test
+[ 102.0 ] [ "x" get NSRect-h ] unit-test
 
 CLASS: {
     { +superclass+ "NSObject" }
index 8072a4229e52d30c33ecb5b69502c42bf16784fd..bb30cda68567c1d2f1f75aaee10926d4100444fd 100644 (file)
@@ -229,10 +229,6 @@ M: float detect-float ;
     \ detect-float inlined?
 ] unit-test
 
-[ t ] [
-    [ 3 + = ] \ equal? inlined?
-] unit-test
-
 [ f ] [
     [ { fixnum fixnum } declare 7 bitand neg shift ]
     \ fixnum-shift-fast inlined?
index 08734ec0950a4e7cbd487ba08ac80405d8ce3501..f08116b9360d0fe1e17d9c2bd50b720e9e66044a 100644 (file)
@@ -1,7 +1,15 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences
-compiler.tree compiler.tree.combinators ;
+USING: kernel accessors sequences words namespaces
+classes.builtin
+compiler.tree
+compiler.tree.builder
+compiler.tree.normalization
+compiler.tree.propagation
+compiler.tree.cleanup
+compiler.tree.def-use
+compiler.tree.dead-code
+compiler.tree.combinators ;
 IN: compiler.tree.finalization
 
 GENERIC: finalize* ( node -- nodes )
@@ -13,6 +21,25 @@ M: #shuffle finalize*
     [ in>> ] [ out>> ] bi sequence=
     [ drop f ] when ;
 
+: builtin-predicate? ( word -- ? )
+    "predicating" word-prop builtin-class? ;
+
+: splice-quot ( quot -- nodes )
+    [
+        build-tree
+        normalize
+        propagate
+        cleanup
+        compute-def-use
+        remove-dead-code
+        but-last
+    ] with-scope ;
+
+M: #call finalize*
+    dup word>> builtin-predicate? [
+        word>> def>> splice-quot
+    ] when ;
+
 M: node finalize* ;
 
 : finalize ( nodes -- nodes' ) [ finalize* ] map-nodes ;
index c07c5a5cb54d80140069ca527bedc8986ebe4e55..4d3d2c781c3d15c495b483d7f6b3571e81b8e30c 100644 (file)
@@ -211,7 +211,7 @@ generic-comparison-ops [
 \ eq? [
     [ info-intervals-intersect? ]
     [ info-classes-intersect? ]
-    2bi or maybe-or-never
+    2bi and maybe-or-never
 ] "outputs" set-word-prop
 
 {
index 559a9bf60b6f652147d970ef8a3e63df5f19af20..f04460f32a65aa053bceb6cde858a351206eb7fe 100644 (file)
@@ -589,6 +589,10 @@ MIXIN: empty-mixin
     ] final-classes
 ] unit-test
 
+[ V{ POSTPONE: f } ] [
+    [ { float } declare 0 eq? ] final-classes
+] unit-test
+
 ! [ V{ string } ] [
 !     [ dup string? t xor [ "A" throw ] [ ] if ] final-classes
 ! ] unit-test
index d723d55cb3f812f6ab8158ae82546806fe6e503a..bed3a655b18ab3e8c6e010430e4997cd3ec45390 100755 (executable)
@@ -2,18 +2,24 @@ USING: help.markup help.syntax math math.private math.functions
 math.complex.private ;
 IN: math.complex
 
+ARTICLE: "complex-numbers-zero" "Embedding of real numbers in complex numbers"
+"Constructing a complex number with an imaginary component equal to an integer zero simply returns the real number corresponding to the real component:"
+{ $example "USING: math prettyprint ;" "C{ 1 2 } C{ 3 -2 } + ." "4" }
+"Constructing a complex number with an imaginary component equal to floating point zero will still output a new complex number, however:"
+{ $example "USING: math prettyprint ;" "C{ 0.0 2.0 } C{ 0.0 1.0 } * ." "C{ 2.0 0.0 }" }
+"Unlike math, where all real numbers are also complex numbers, Factor only considers a number to be a complex number if its imaginary part is non-zero. However, complex number operations are fully supported for real numbers; they are treated as having an imaginary part of zero." ;
+
 ARTICLE: "complex-numbers" "Complex numbers"
 { $subsection complex }
 "Complex numbers arise as solutions to quadratic equations whose graph does not intersect the " { $emphasis "x" } " axis. Their literal syntax is covered in " { $link "syntax-complex-numbers" } "."
 $nl
-"Unlike math, where all real numbers are also complex numbers, Factor only considers a number to be a complex number if its imaginary part is non-zero. However, complex number operations are fully supported for real numbers; they are treated as having an imaginary part of zero."
-$nl
 "Complex numbers can be taken apart:"
 { $subsection real-part }
 { $subsection imaginary-part }
 { $subsection >rect }
 "Complex numbers can be constructed from real numbers:"
 { $subsection rect> }
+{ $subsection "complex-numbers-zero" }
 { $see-also "syntax-complex-numbers" } ;
 HELP: complex
 { $class-description "The class of complex numbers with non-zero imaginary part." } ;
index 063871ce5be5b8b80f464f756577965b4b99383e..4b0481eca1eb808d514736f37d97a4ed2fce8d1c 100755 (executable)
@@ -5,9 +5,14 @@ IN: math.complex.tests
 [ 1 C{ 0 1 } rect> ] must-fail
 [ C{ 0 1 } 1 rect> ] must-fail
 
-[ f ] [ C{ 5 12.5 } 5  = ] unit-test
-[ t ] [ C{ 1.0 2.0 } C{ 1 2 }  = ] unit-test
-[ f ] [ C{ 1.0 2.3 } C{ 1 2 }  = ] unit-test
+[ f ] [ C{ 5 12.5 } 5 = ] unit-test
+[ f ] [ C{ 5 12.5 } 5 number= ] unit-test
+
+[ f ] [ C{ 1.0 2.0 } C{ 1 2 } = ] unit-test
+[ t ] [ C{ 1.0 2.0 } C{ 1 2 } number= ] unit-test
+
+[ f ] [ C{ 1.0 2.3 } C{ 1 2 } = ] unit-test
+[ f ] [ C{ 1.0 2.3 } C{ 1 2 } number= ] unit-test
 
 [ C{ 2 5 } ] [ 2 5  rect> ] unit-test
 [ 2 5 ] [ C{ 2 5 }  >rect ] unit-test
@@ -30,7 +35,7 @@ IN: math.complex.tests
 
 [ C{ 0 1 } ] [ C{ 0 1 } 1  * ] unit-test
 [ C{ 0 1 } ] [ 1 C{ 0 1 }  * ] unit-test
-[ C{ 0 1.0 } ] [ 1.0 C{ 0 1 }  * ] unit-test
+[ C{ 0.0 1.0 } ] [ 1.0 C{ 0 1 }  * ] unit-test
 [ -1 ] [ C{ 0 1 } C{ 0 1 }  * ] unit-test
 [ C{ 0 1 } ] [ 1 C{ 0 1 }  * ] unit-test
 [ C{ 0 1 } ] [ C{ 0 1 } 1  * ] unit-test
@@ -45,18 +50,18 @@ IN: math.complex.tests
 
 [ C{ -3 4 } ] [ C{ 3 -4 }  neg ] unit-test
 
-[ 5 ] [ C{ 3 4 } abs ] unit-test
-[ 5 ] [ -5.0 abs ] unit-test
+[ 5.0 ] [ C{ 3 4 } abs ] unit-test
+[ 5.0 ] [ -5.0 abs ] unit-test
 
 ! Make sure arguments are sane
-[ 0 ] [ 0 arg ] unit-test
-[ 0 ] [ 1 arg ] unit-test
+[ 0.0 ] [ 0 arg ] unit-test
+[ 0.0 ] [ 1 arg ] unit-test
 [ t ] [ -1 arg 3.14 3.15 between? ] unit-test
 [ t ] [ C{ 0 1 } arg 1.57 1.58 between? ] unit-test
 [ t ] [ C{ 0 -1 } arg -1.58 -1.57 between? ] unit-test
 
-[ 1 0 ] [ 1 >polar ] unit-test
-[ 1 ] [ -1 >polar drop ] unit-test
+[ 1.0 0.0 ] [ 1 >polar ] unit-test
+[ 1.0 ] [ -1 >polar drop ] unit-test
 [ t ] [ -1 >polar nip 3.14 3.15 between? ] unit-test
 
 ! I broke something
index cef0676d1228f0e793d44f651e1195022547870b..ff5c0feb7804c25ceb885254d4149dc2cbebdaa5 100755 (executable)
@@ -17,6 +17,14 @@ M: complex absq >rect [ sq ] bi@ + ;
     [ [ real-part ] bi@ ] 2keep
     [ imaginary-part ] bi@ ; inline
 
+M: complex hashcode*
+    nip >rect [ hashcode ] bi@ bitxor ;
+
+M: complex equal?
+    over complex? [
+        2>rect = [ = ] [ 2drop f ] if
+    ] [ 2drop f ] if ;
+
 M: complex number=
     2>rect number= [ number= ] [ 2drop f ] if ;
 
@@ -36,8 +44,6 @@ M: complex abs absq >float fsqrt ;
 
 M: complex sqrt >polar swap fsqrt swap 2.0 / polar> ;
 
-M: complex hashcode* nip >rect >fixnum swap >fixnum bitxor ;
-
 IN: syntax
 
 : C{ \ } [ first2 rect> ] parse-literal ; parsing
index c02325810528a60e98ac7a6592c2a394e9bb9846..bbfd8f41be4014c206528725beca1b2a99bb5240 100755 (executable)
@@ -106,7 +106,7 @@ HELP: (rect>)
 
 HELP: rect>
 { $values { "x" real } { "y" real } { "z" number } }
-{ $description "Creates a complex number from real and imaginary components." } ;
+{ $description "Creates a complex number from real and imaginary components. If " { $snippet "z" } " is an integer zero, this will simply output " { $snippet "x" } "." } ;
 
 HELP: >rect
 { $values { "z" number } { "x" real } { "y" real } }
index f2d26e330db5eca836ceea5f12da4ca569c9c8a1..d5bdac761fd7b9b678d019c227d2926522c97617 100755 (executable)
@@ -12,10 +12,11 @@ IN: math.functions.tests
 [ 0.25 ] [ 2.0 -2.0 fpow ] unit-test
 
 [ 4.0 ] [ 16 sqrt ] unit-test
-[ C{ 0 4.0 } ] [ -16 sqrt ] unit-test
+[ 2.0 ] [ 4.0 0.5 ^ ] unit-test
+[ C{ 0.0 4.0 } ] [ -16 sqrt ] unit-test
 
-[ 4.0 ] [ 2 2 ^ ] unit-test
-[ 0.25 ] [ 2 -2 ^ ] unit-test
+[ 4 ] [ 2 2 ^ ] unit-test
+[ 1/4 ] [ 2 -2 ^ ] unit-test
 [ t ] [ 2 0.5 ^ 2 ^ 2 2.00001 between? ] unit-test
 [ t ] [ e pi i* ^ real-part -1.0 = ] unit-test
 [ t ] [ e pi i* ^ imaginary-part -0.00001 0.00001 between? ] unit-test
@@ -27,6 +28,8 @@ IN: math.functions.tests
 [ 0 ] [ 0 3.0 ^ ] unit-test
 [ 0 ] [ 0 3 ^ ] unit-test
 
+[ 0.0 ] [ 1 log ] unit-test
+
 [ 1.0 ] [ 0 cosh ] unit-test
 [ 0.0 ] [ 1 acosh ] unit-test
             
index 4d71b25174e40be25c0c093d7619c6aaa7c5185d..8516292e9d19467586cb12d4a8ec9de1ddc9d115 100755 (executable)
@@ -7,7 +7,7 @@ IN: math.functions
 <PRIVATE
 
 : (rect>) ( x y -- z )
-    dup zero? [ drop ] [ <complex> ] if ; inline
+    dup 0 = [ drop ] [ <complex> ] if ; inline
 
 PRIVATE>
 
@@ -24,29 +24,57 @@ M: real sqrt
     >float dup 0.0 < [ neg fsqrt 0.0 swap rect> ] [ fsqrt ] if ;
 
 : each-bit ( n quot: ( ? -- ) -- )
-    over 0 number= pick -1 number= or [
+    over 0 = pick -1 = or [
         2drop
     ] [
         2dup >r >r >r odd? r> call r> 2/ r> each-bit
     ] if ; inline recursive
 
-GENERIC: (^) ( x y -- z ) foldable
-
 : ^n ( z w -- z^w )
     1 swap [
         [ dupd * ] when >r sq r>
     ] each-bit nip ; inline
 
-M: integer (^)
-    dup 0 < [ neg ^n recip ] [ ^n ] if ;
+: integer^ ( x y -- z )
+    dup 0 > [ ^n ] [ neg ^n recip ] if ; inline
+
+: >rect ( z -- x y )
+    [ real-part ] [ imaginary-part ] bi ; inline
+
+: >float-rect ( z -- x y )
+    >rect [ >float ] bi@ ; inline
+
+: >polar ( z -- abs arg )
+    >float-rect [ [ sq ] bi@ + fsqrt ] [ swap fatan2 ] 2bi ;
+    inline
+
+: cis ( arg -- z ) dup fcos swap fsin rect> ; inline
+
+: polar> ( abs arg -- z ) cis * ; inline
+
+: ^mag ( w abs arg -- magnitude )
+    >r >r >float-rect swap r> swap fpow r> rot * fexp /f ;
+    inline
+
+: ^theta ( w abs arg -- theta )
+    >r >r >float-rect r> flog * swap r> * + ; inline
+
+: ^complex ( x y -- z )
+    swap >polar [ ^mag ] [ ^theta ] 3bi polar> ; inline
+
+: real^? ( x y -- ? )
+    2dup [ real? ] both? [ drop 0 >= ] [ 2drop f ] if ; inline
+
+: 0^ ( x -- z )
+    dup zero? [ drop 0./0. ] [ 0 < 1./0. 0 ? ] if ; inline
 
 : ^ ( x y -- z )
-    over zero? [
-        dup zero?
-        [ 2drop 0.0 0.0 / ] [ 0 < [ drop 1.0 0.0 / ] when ] if
-    ] [
-        (^)
-    ] if ; inline
+    {
+        { [ over zero? ] [ nip 0^ ] }
+        { [ dup integer? ] [ integer^ ] }
+        { [ 2dup real^? ] [ fpow ] }
+        [ ^complex ]
+    } cond ;
 
 : (^mod) ( n x y -- z )
     1 swap [
@@ -98,42 +126,27 @@ M: real absq sq ;
         [ ~abs ]
     } cond ;
 
-: >rect ( z -- x y ) dup real-part swap imaginary-part ; inline
-
 : conjugate ( z -- z* ) >rect neg rect> ; inline
 
-: >float-rect ( z -- x y )
-    >rect swap >float swap >float ; inline
-
 : arg ( z -- arg ) >float-rect swap fatan2 ; inline
 
-: >polar ( z -- abs arg )
-    >float-rect [ [ sq ] bi@ + fsqrt ] 2keep swap fatan2 ;
-    inline
-
-: cis ( arg -- z ) dup fcos swap fsin rect> ; inline
-
-: polar> ( abs arg -- z ) cis * ; inline
-
-: ^mag ( w abs arg -- magnitude )
-    >r >r >float-rect swap r> swap fpow r> rot * fexp /f ;
-    inline
-
-: ^theta ( w abs arg -- theta )
-    >r >r >float-rect r> flog * swap r> * + ; inline
-
-M: number (^)
-    swap >polar 3dup ^theta >r ^mag r> polar> ;
-
 : [-1,1]? ( x -- ? )
     dup complex? [ drop f ] [ abs 1 <= ] if ; inline
 
 : >=1? ( x -- ? )
     dup complex? [ drop f ] [ 1 >= ] if ; inline
 
-: exp ( x -- y ) >rect swap fexp swap polar> ; inline
+GENERIC: exp ( x -- y )
+
+M: real exp fexp ;
+
+M: complex exp >rect swap fexp swap polar> ;
+
+GENERIC: log ( x -- y )
+
+M: real log dup 0.0 >= [ flog ] [ 0.0 rect> log ] if ;
 
-: log ( x -- y ) >polar swap flog swap rect> ; inline
+M: complex log >polar swap flog swap rect> ;
 
 : cos ( x -- y )
     dup complex? [
index 806b0961ca7d6c6e1487631a1c31ac9291fa1952..7d8d4967371771fb5e79dcd63a1a6ea802ee9bf8 100755 (executable)
@@ -60,11 +60,11 @@ IN: math.intervals.tests
 ] unit-test
 
 [ t ] [
-    1 2 [a,b] -0.5 0.5 [a,b] interval* -1 1 [a,b] =
+    1 2 [a,b] -0.5 0.5 [a,b] interval* -1.0 1.0 [a,b] =
 ] unit-test
 
 [ t ] [
-    1 2 [a,b] -0.5 0.5 (a,b] interval* -1 1 (a,b] =
+    1 2 [a,b] -0.5 0.5 (a,b] interval* -1.0 1.0 (a,b] =
 ] unit-test
 
 [ t ] [
@@ -131,7 +131,7 @@ IN: math.intervals.tests
 
 "math.ratios.private" vocab [
     [ t ] [
-        -1 1 (a,b) 0.5 1 (a,b) interval/ -2 2 (a,b) =
+        -1 1 (a,b) 0.5 1 (a,b) interval/ -2.0 2.0 (a,b) =
     ] unit-test
 ] when
 
index 28801fa2e98c7e0c863da704def1c792193f6d31..c01e7377b2fcc118109eda1af6df6affcf240f04 100755 (executable)
@@ -81,8 +81,8 @@ unit-test
 [ -1/2 ] [ 1/2 1- ] unit-test
 [ 3/2 ] [ 1/2 1+ ] unit-test
 
-[ 1 ] [ 0.5 1/2 + ] unit-test
-[ 1 ] [ 1/2 0.5 + ] unit-test
+[ 1.0 ] [ 0.5 1/2 + ] unit-test
+[ 1.0 ] [ 1/2 0.5 + ] unit-test
 
 [ 1/268435456 ] [ -1 -268435456 >fixnum / ] unit-test
 [ 268435456 ] [ -268435456 >fixnum -1 / ] unit-test
index 6569ee9540d6c2859c055efeb1e9c9101ee93214..5dde4fbb99213d593c1b2ab1ad2718367e24f680 100755 (executable)
@@ -30,6 +30,14 @@ M: integer /
         2dup gcd nip tuck /i >r /i r> fraction>
     ] if ;
 
+M: ratio hashcode*
+    nip >fraction [ hashcode ] bi@ bitxor ;
+
+M: ratio equal?
+    over ratio? [
+        2>fraction = [ = ] [ 2drop f ] if
+    ] [ 2drop f ] if ;
+
 M: ratio number=
     2>fraction number= [ number= ] [ 2drop f ] if ;
 
index 2c584b7378843345a9895acc015a45f0ddc0b25b..3f8e3078b633be1e33ec33165f0c274e09a083a1 100755 (executable)
@@ -701,3 +701,11 @@ DEFER: error-y
 [ ] [
     "IN: sequences TUPLE: reversed { seq read-only } ;" eval
 ] unit-test
+
+TUPLE: bogus-hashcode-1 x ;
+
+TUPLE: bogus-hashcode-2 x ;
+
+M: bogus-hashcode-1 hashcode* 2drop 0 >bignum ;
+
+[ ] [ T{ bogus-hashcode-2 T{ bogus-hashcode-1 } } hashcode drop ] unit-test
index e5f3ac83940e4cf2e4ab0daa419766162991db61..52d73a9a4c0ad664f14ac5cbd7a5df6f06068956 100644 (file)
@@ -81,7 +81,7 @@ M: parallelogram perimiter
 M: circle perimiter 2 * pi * ;
 
 [ 14 ] [ 4 3 <rectangle> perimiter ] unit-test
-[ 30 ] [ 10 4 3 <parallelogram> perimiter ] unit-test
+[ 30.0 ] [ 10 4 3 <parallelogram> perimiter ] unit-test
 
 GENERIC: big-mix-test ( obj -- obj' )
 
index 32684b92dcfbc6c7727de0186439ae1542071bd5..abf3747244a541569eac26f81d424a231016f412 100755 (executable)
@@ -28,7 +28,6 @@ unit-test
 
 [ t ] [ 12 hashcode 12 hashcode = ] unit-test
 [ t ] [ 12 >bignum hashcode 12 hashcode = ] unit-test
-[ t ] [ 12.0 hashcode 12 >bignum hashcode = ] unit-test
 
 ! Test various odd keys to see if they work.
 
index 7a575c0d7a724f676c305d827dfe6f190a2fe657..af4038c575dcda68568e27b1b0f180104f894536 100755 (executable)
@@ -251,13 +251,15 @@ ARTICLE: "conditionals" "Conditionals and logic"
 { $see-also "booleans" "bitwise-arithmetic" both? either? } ;
 
 ARTICLE: "equality" "Equality"
-"There are two distinct notions of ``sameness'' when it comes to objects. You can test if two references point to the same object (" { $emphasis "identity comparison" } "), or you can test if two objects are equal in a domain-specific sense, usually by being instances of the same class, and having equal slot values (" { $emphasis "value comparison" } "). Both notions of equality are equality relations in the mathematical sense."
+"There are two distinct notions of ``sameness'' when it comes to objects."
 $nl
-"Identity comparison:"
+"You can test if two references point to the same object (" { $emphasis "identity comparison" } "). This is rarely used; it is mostly useful with large, mutable objects where the object identity matters but the value is transient:"
 { $subsection eq? }
-"Value comparison:"
+"You can test if two objects are equal in a domain-specific sense, usually by being instances of the same class, and having equal slot values (" { $emphasis "value comparison" } "):"
 { $subsection = }
-"Custom value comparison methods:"
+"A third form of equality is provided by " { $link number= } ". It compares numeric value while disregarding types."
+$nl
+"Custom value comparison methods for use with " { $link = } " can be defined on a generic word:"
 { $subsection equal? }
 "Utility class:"
 { $subsection identity-tuple }
@@ -367,6 +369,13 @@ HELP: =
 { $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
 { $description
     "Tests if two objects are equal. If " { $snippet "obj1" } " and " { $snippet "obj2" } " point to the same object, outputs " { $link t } ". Otherwise, calls the " { $link equal? } " generic word."
+}
+{ $examples
+    { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
+    { $example "USING: kernel prettyprint ;" "5 005 = ." "t" }
+    { $example "USING: kernel prettyprint ;" "5 5.0 = ." "f" }
+    { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } \"a\" \"b\" 2array = ." "t" }
+    { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } [ \"a\" \"b\" ] = ." "f" }
 } ;
 
 HELP: equal?
@@ -381,8 +390,13 @@ HELP: equal?
         { { $snippet "a = b" } " implies " { $snippet "b = a" } }
         { { $snippet "a = b" } " and " { $snippet "b = c" } " implies " { $snippet "a = c" } }
     }
-    $nl
     "If a class defines a custom equality comparison test, it should also define a compatible method for the " { $link hashcode* } " generic word."
+}
+{ $examples
+    "An example demonstrating why this word should only be used to define methods on, and never called directly:"
+    { $example "USING: kernel prettyprint ;" "5 5 equal? ." "f" }
+    "Using " { $link = } " gives the expected behavior:"
+    { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
 } ;
 
 HELP: identity-tuple
index 095392ed819217c9cf26837dadec21efb74e981b..bd3f951b021ece159dbbc35c621d71764379c022 100755 (executable)
@@ -5,10 +5,17 @@ IN: math.floats.tests
 [ t ] [ 3.1415 number? ] unit-test
 [ f ] [ 12 float? ] unit-test
 
-[ t ] [ 1 1.0 = ] unit-test
-[ t ] [ 1 >bignum 1.0 = ] unit-test
-[ t ] [ 1.0 1 = ] unit-test
-[ t ] [ 1.0 1 >bignum = ] unit-test
+[ f ] [ 1 1.0 = ] unit-test
+[ t ] [ 1 1.0 number= ] unit-test
+
+[ f ] [ 1 >bignum 1.0 = ] unit-test
+[ t ] [ 1 >bignum 1.0 number= ] unit-test
+
+[ f ] [ 1.0 1 = ] unit-test
+[ t ] [ 1.0 1 number= ] unit-test
+
+[ f ] [ 1.0 1 >bignum = ] unit-test
+[ t ] [ 1.0 1 >bignum number= ] unit-test
 
 [ f ] [ 1 1.3 = ] unit-test
 [ f ] [ 1 >bignum 1.3 = ] unit-test
@@ -45,13 +52,10 @@ unit-test
 [ 2.0 ] [ 1.0 1+ ] unit-test
 [ 0.0 ] [ 1.0 1- ] unit-test
 
-! [ t ] [ -0.0 -0.0 = ] unit-test
-! [ f ] [ 0.0 -0.0 = ] unit-test
-
 [ t ] [ 0.0 zero? ] unit-test
 [ t ] [ -0.0 zero? ] unit-test
 
-! [ t ] [ 0.0/0.0 0.0/0.0 = ] unit-test
+! [ f ] [ 0.0/0.0 0.0/0.0 number= ] unit-test
 
 [ 0 ] [ 1/0. >bignum ] unit-test
 
index 5cd6f067a9b5a0c16a23ac4b182de9a75735f94e..9dcff9eb90397a34324bbf69cc29eb08a5586bc6 100755 (executable)
@@ -10,11 +10,14 @@ M: float >fixnum float>fixnum ;
 M: float >bignum float>bignum ;
 M: float >float ;
 
+M: float hashcode* nip float>bits ;
+M: float equal? over float? [ float= ] [ 2drop f ] if ;
+M: float number= float= ;
+
 M: float < float< ;
 M: float <= float<= ;
 M: float > float> ;
 M: float >= float>= ;
-M: float number= float= ;
 
 M: float + float+ ;
 M: float - float- ;
index 1e27d5f16c5255a148e84842ee631359f0140ad7..74a93d39bd306e50b70f6087f95716fa64ea1c90 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2004, 2007 Slava Pestov.
+! Copyright (C) 2004, 2008 Slava Pestov.
 ! Copyright (C) 2008, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel kernel.private sequences
@@ -12,6 +12,8 @@ M: fixnum >fixnum ;
 M: fixnum >bignum fixnum>bignum ;
 M: fixnum >integer ;
 
+M: fixnum hashcode* nip ;
+M: fixnum equal? over bignum? [ >bignum bignum= ] [ 2drop f ] if ;
 M: fixnum number= eq? ;
 
 M: fixnum < fixnum< ;
@@ -47,7 +49,15 @@ M: fixnum (log2) 0 swap (fixnum-log2) ;
 M: bignum >fixnum bignum>fixnum ;
 M: bignum >bignum ;
 
+M: bignum hashcode* nip >fixnum ;
+
+M: bignum equal?
+    over bignum? [ bignum= ] [
+        swap dup fixnum? [ >bignum bignum= ] [ 2drop f ] if
+    ] if ;
+
 M: bignum number= bignum= ;
+
 M: bignum < bignum< ;
 M: bignum <= bignum<= ;
 M: bignum > bignum> ;
index 697f3d81be25b72b14e440064910725350fc2ecf..07e2de2f8fc5f40bc32779948097d8352dd52f11 100755 (executable)
@@ -26,7 +26,9 @@ $nl
 { $subsection < }
 { $subsection <= }
 { $subsection > }
-{ $subsection >= } ;
+{ $subsection >= }
+"Numbers can be compared for equality using " { $link = } ", or a less precise test which disregards types:"
+{ $subsection number= } ;
 
 ARTICLE: "modular-arithmetic" "Modular arithmetic"
 { $subsection mod }
@@ -60,8 +62,12 @@ ABOUT: "arithmetic"
 
 HELP: number=
 { $values { "x" number } { "y" number } { "?" "a boolean" } }
-{ $description "Tests if two numbers have the same numerical value. If either input is not a number, outputs " { $link f } "." }
-{ $notes "Do not call this word directly. Calling " { $link = } " has the same effect and is more concise." } ;
+{ $description "Tests if two numbers have the same numeric value." }
+{ $notes "This word differs from " { $link = } " in that it disregards differences in type when comparing numbers." }
+{ $examples
+    { $example "USING: math prettyprint ;" "3.0 3 number= ." "t" }
+    { $example "USING: math prettyprint ;" "3.0 3 = ." "f" }
+} ;
 
 HELP: <
 { $values { "x" real } { "y" real } { "?" "a boolean" } }
@@ -286,7 +292,10 @@ HELP: zero?
 HELP: times
 { $values { "n" integer } { "quot" quotation } }
 { $description "Calls the quotation " { $snippet "n" } " times." }
-{ $notes "If you need to pass the current index to the quotation, use " { $link each } "." } ;
+{ $notes "If you need to pass the current index to the quotation, use " { $link each } "." }
+{ $examples
+    { $example "USING: io math ;" "3 [ \"Hi\" print ] times" "Hi\nHi\nHi\n" }
+} ;
 
 HELP: fp-nan?
 { $values { "x" real } { "?" "a boolean" } }
@@ -294,11 +303,16 @@ HELP: fp-nan?
 
 HELP: real-part
 { $values { "z" number } { "x" real } }
-{ $description "Outputs the real part of a complex number. This acts as the identity on real numbers." } ;
+{ $description "Outputs the real part of a complex number. This acts as the identity on real numbers." }
+{ $examples { $example "C{ 1 2 } real-part ." "1" } } ;
 
 HELP: imaginary-part
 { $values { "z" number } { "y" real } }
-{ $description "Outputs the imaginary part of a complex number. This outputs zero for real numbers." } ;
+{ $description "Outputs the imaginary part of a complex number. This outputs zero for real numbers." }
+{ $examples
+    { $example "C{ 1 2 } imaginary-part ." "2" }
+    { $example "3 imaginary-part ." "0" }
+} ;
 
 HELP: real
 { $class-description "The class of real numbers, which is a disjoint union of rationals and floats." } ;
index 4efca0ef2fb9d61e1c3718f49b71b19bce7c3a37..024a32087eaf53a91007749c5d000a87d48c8f55 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2003, 2007 Slava Pestov.
+! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math.private ;
 IN: math
@@ -82,10 +82,6 @@ UNION: real rational float ;
 
 UNION: number real complex ;
 
-M: number equal? number= ;
-
-M: real hashcode* nip >fixnum ;
-
 GENERIC: fp-nan? ( x -- ? )
 
 M: object fp-nan?
index 82dfbbd629b19d7ff5563cd7a81bb9c2c08360bd..4b7b8a3151fdc0f26fd85fc44f5d521da3be0f0b 100755 (executable)
@@ -69,7 +69,7 @@ unit-test
 [ f ] [ [ { 2 } { } { } ] all-equal? ] unit-test
 [ t ] [ [ ] all-equal? ] unit-test
 [ t ] [ [ 1234 ] all-equal? ] unit-test
-[ t ] [ [ 1.0 1 1 ] all-equal? ] unit-test
+[ f ] [ [ 1.0 1 1 ] all-equal? ] unit-test
 [ t ] [ { 1 2 3 4 } [ < ] monotonic? ] unit-test
 [ f ] [ { 1 2 3 4 } [ > ] monotonic? ] unit-test
 [ [ 2 3 4 ] ] [ [ 1 2 3 ] 1 [ + ] curry map ] unit-test
@@ -251,3 +251,9 @@ unit-test
 [ { "a" "b" "c" "d" } ] [ { "a" "b" "c" "d" } { 0 1 2 3 } nths ] unit-test
 [ { "d" "c" "b" "a" } ] [ { "a" "b" "c" "d" } { 3 2 1 0 } nths ] unit-test
 [ { "d" "a" "b" "c" } ] [ { "a" "b" "c" "d" } { 3 0 1 2 } nths ] unit-test
+
+TUPLE: bogus-hashcode ;
+
+M: bogus-hashcode hashcode* 2drop 0 >bignum ;
+
+[ 0 ] [ { T{ bogus-hashcode } } hashcode ] unit-test
index f7a078fe4d23bcd9a3192e384c2cd4253cd32895..73c9289415837ed9e955303996dd4a6d75a1b856 100755 (executable)
@@ -499,15 +499,13 @@ M: sequence <=>
     [ mismatch not ] [ 2drop f ] if ; inline
 
 : sequence-hashcode-step ( oldhash newpart -- newhash )
-    swap [
+    >fixnum swap [
         dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast
         fixnum+fast fixnum+fast
     ] keep fixnum-bitxor ; inline
 
 : sequence-hashcode ( n seq -- x )
-    0 -rot [
-        hashcode* >fixnum sequence-hashcode-step
-    ] with each ; inline
+    0 -rot [ hashcode* sequence-hashcode-step ] with each ; inline
 
 M: reversed equal? over reversed? [ sequence= ] [ 2drop f ] if ;