diff --git a/basis/math/bitwise/bitwise-docs.factor b/basis/math/bitwise/bitwise-docs.factor index 247523369b..4f2606bda0 100644 --- a/basis/math/bitwise/bitwise-docs.factor +++ b/basis/math/bitwise/bitwise-docs.factor @@ -1,12 +1,8 @@ -USING: help.markup help.syntax math ; +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax math sequences ; IN: math.bitwise -ARTICLE: "math-bitfields" "Constructing bit fields" -"Some applications, such as binary communication protocols and assemblers, need to construct integers from elaborate bit field specifications. Hand-coding this using " { $link shift } " and " { $link bitor } " results in repetitive code. A higher-level facility exists to factor out this repetition:" -{ $subsection bitfield } ; - -ABOUT: "math-bitfields" - HELP: bitfield { $values { "values..." "a series of objects" } { "bitspec" "an array" } { "n" integer } } { $description "Constructs an integer from a series of values on the stack together with a bit field specifier, which is an array whose elements have one of the following shapes:" @@ -42,9 +38,307 @@ HELP: bits { $example "USING: math.bitwise prettyprint ;" "HEX: 123abcdef 16 bits .h" "cdef" } ; HELP: bitroll -{ $values { "x" "an integer (input)" } { "s" "an integer (shift)" } { "w" "an integer (wrap)" } { "y" integer } } +{ $values { "x" integer } { "s" "a shift integer" } { "w" "a wrap integer" } { "y" integer } +} { $description "Roll n by s bits to the left, wrapping around after w bits." } { $examples { $example "USING: math.bitwise prettyprint ;" "1 -1 32 bitroll .b" "10000000000000000000000000000000" } { $example "USING: math.bitwise prettyprint ;" "HEX: ffff0000 8 32 bitroll .h" "ff0000ff" } } ; + +HELP: bit-clear? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Returns " { $link t } " if the nth bit is set to zero." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: ff 8 bit-clear? ." + "t" + } + { $example "" "USING: math.bitwise prettyprint ;" + "HEX: ff 7 bit-clear? ." + "f" + } +} ; + +{ bit? bit-clear? set-bit clear-bit } related-words + +HELP: bit-count +{ $values + { "x" integer } + { "n" integer } +} +{ $description "Returns the number of set bits as an integer." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: f0 bit-count ." + "4" + } + { $example "USING: math.bitwise prettyprint ;" + "-7 bit-count ." + "2" + } +} ; + +HELP: bitroll-32 +{ $values + { "n" integer } { "s" integer } + { "n'" integer } +} +{ $description "Rolls the number " { $snippet "n" } " by " { $snippet "s" } " bits to the left, wrapping around after 32 bits." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 10 bitroll-32 .h" + "400" + } + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 -10 bitroll-32 .h" + "400000" + } +} ; + +HELP: bitroll-64 +{ $values + { "n" integer } { "s" "a shift integer" } + { "n'" integer } +} +{ $description "Rolls the number " { $snippet "n" } " by " { $snippet "s" } " bits to the left, wrapping around after 64 bits." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 10 bitroll-64 .h" + "400" + } + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 -10 bitroll-64 .h" + "40000000000000" + } +} ; + +{ bitroll bitroll-32 bitroll-64 } related-words + +HELP: clear-bit +{ $values + { "x" integer } { "n" integer } + { "y" integer } +} +{ $description "Sets the nth bit of " { $snippet "x" } " to zero." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff 7 clear-bit .h" + "7f" + } +} ; + +HELP: flags +{ $values + { "values" sequence } +} +{ $description "Constructs a constant flag value from a sequence of integers or words that output integers. The resulting constant is computed at compile-time, which makes this word as efficient as using a literal integer." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "IN: scratchpad" + ": MY-CONSTANT HEX: 1 ; inline" + "{ HEX: 20 MY-CONSTANT BIN: 100 } flags .h" + "25" + } +} ; + +HELP: mask +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "After the operation, only the bits that were set in both the mask and the original number are set." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "BIN: 11111111 BIN: 101 mask .b" + "101" + } +} ; + +HELP: mask-bit +{ $values + { "m" integer } { "n" integer } + { "m'" integer } +} +{ $description "Turns off all bits besides the nth bit." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff 2 mask-bit .b" + "100" + } +} ; + +HELP: mask? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Returns true if all of the bits in the mask " { $snippet "n" } " are set in the integer input " { $snippet "x" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: f mask? ." + "t" + } + + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: f0 HEX: 1 mask? ." + "f" + } +} ; + +HELP: on-bits +{ $values + { "n" integer } + { "m" integer } +} +{ $description "Returns an integer with " { $snippet "n" } " bits set." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "6 on-bits .h" + "3f" + } + { $example "USING: math.bitwise kernel prettyprint ;" + "64 on-bits .h" + "ffffffffffffffff" + } +} +; + +HELP: set-bit +{ $values + { "x" integer } { "n" integer } + { "y" integer } +} +{ $description "Sets the nth bit of " { $snippet "x" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "0 5 set-bit .h" + "20" + } +} ; + +HELP: shift-mod +{ $values + { "n" integer } { "s" integer } { "w" integer } + { "n" integer } +} +{ $description "" } ; + +HELP: unmask +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Clears the bits in " { $snippet "x" } " if they are set in the mask " { $snippet "n" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: 0f unmask .h" + "f0" + } +} ; + +HELP: unmask? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Tests whether unmasking the bits in " { $snippet "x" } " would return an integer greater than zero." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: 0f unmask? ." + "t" + } +} ; + +HELP: w* +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Multiplies two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ffffffff HEX: 2 w* ." + "4294967294" + } +} ; + +HELP: w+ +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Adds two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ffffffff HEX: 2 w+ ." + "1" + } +} ; + +HELP: w- +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Subtracts two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: 0 HEX: ff w- ." + "4294967041" + } +} ; + +HELP: wrap +{ $values + { "m" integer } { "n" integer } + { "m'" integer } +} +{ $description "Wraps an integer " { $snippet "m" } " by modding it by " { $snippet "n" } ". This word is uses bitwise arithmetic and does not actually call the modulus word, and as such can only mod by powers of two." } +{ $examples "Equivalent to modding by 8:" + { $example + "USING: math.bitwise prettyprint ;" + "HEX: ffff 8 wrap .h" + "7" + } +} ; + +ARTICLE: "math-bitfields" "Constructing bit fields" +"Some applications, such as binary communication protocols and assemblers, need to construct integers from elaborate bit field specifications. Hand-coding this using " { $link shift } " and " { $link bitor } " results in repetitive code. A higher-level facility exists to factor out this repetition:" +{ $subsection bitfield } ; + +ARTICLE: "math.bitwise" "Bitwise arithmetic" +"The " { $vocab-link "math.bitwise" } " vocabulary can implements bitwise arithmetic words that are useful for efficiency, low-level programming, and interfacing with C libraries." $nl +"Setting and clearing bits:" +{ $subsection set-bit } +{ $subsection clear-bit } +"Testing if bits are set or clear:" +{ $subsection bit? } +{ $subsection bit-clear? } +"Operations with bitmasks:" +{ $subsection mask } +{ $subsection unmask } +{ $subsection mask? } +{ $subsection unmask? } +"Generating an integer with n set bits:" +{ $subsection on-bits } +"Counting the number of set bits:" +{ $subsection bit-count } +"More efficient modding by powers of two:" +{ $subsection wrap } +"Bit-rolling:" +{ $subsection bitroll } +{ $subsection bitroll-32 } +{ $subsection bitroll-64 } +"32-bit arithmetic:" +{ $subsection w+ } +{ $subsection w- } +{ $subsection w* } +"Bitfields:" +{ $subsection flags } +{ $subsection "math-bitfields" } ; + +ABOUT: "math.bitwise" diff --git a/basis/math/bitwise/bitwise-tests.factor b/basis/math/bitwise/bitwise-tests.factor index 8b13cb23b3..4422992956 100644 --- a/basis/math/bitwise/bitwise-tests.factor +++ b/basis/math/bitwise/bitwise-tests.factor @@ -27,3 +27,5 @@ IN: math.bitwise.tests [ 3 ] [ foo ] unit-test [ 3 ] [ { a b } flags ] unit-test \ foo must-infer + +[ 1 ] [ { 1 } flags ] unit-test diff --git a/basis/math/bitwise/bitwise.factor b/basis/math/bitwise/bitwise.factor index 871f40e74c..ad1907fcb0 100644 --- a/basis/math/bitwise/bitwise.factor +++ b/basis/math/bitwise/bitwise.factor @@ -1,4 +1,4 @@ -! Copyright (C) 2007, 2008 Slava Pestov. +! Copyright (C) 2007, 2008 Slava Pestov, Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: arrays kernel math math.functions sequences sequences.private words namespaces macros hints @@ -8,28 +8,29 @@ IN: math.bitwise ! utilities : clear-bit ( x n -- y ) 2^ bitnot bitand ; inline : set-bit ( x n -- y ) 2^ bitor ; inline -: bit-clear? ( x n -- ? ) 2^ bitand zero? ; inline +: bit-clear? ( x n -- ? ) 2^ bitand 0 = ; inline : unmask ( x n -- ? ) bitnot bitand ; inline : unmask? ( x n -- ? ) unmask 0 > ; inline : mask ( x n -- ? ) bitand ; inline : mask? ( x n -- ? ) mask 0 > ; inline : wrap ( m n -- m' ) 1- bitand ; inline : bits ( m n -- m' ) 2^ wrap ; inline -: mask-bit ( m n -- m' ) 1- 2^ mask ; inline +: mask-bit ( m n -- m' ) 2^ mask ; inline +: on-bits ( n -- m ) 2^ 1- ; inline : shift-mod ( n s w -- n ) - >r shift r> 2^ wrap ; inline + [ shift ] dip 2^ wrap ; inline : bitroll ( x s w -- y ) - [ wrap ] keep - [ shift-mod ] - [ [ - ] keep shift-mod ] 3bi bitor ; inline + [ wrap ] keep + [ shift-mod ] + [ [ - ] keep shift-mod ] 3bi bitor ; inline -: bitroll-32 ( n s -- n' ) 32 bitroll ; +: bitroll-32 ( n s -- n' ) 32 bitroll ; inline HINTS: bitroll-32 bignum fixnum ; -: bitroll-64 ( n s -- n' ) 64 bitroll ; +: bitroll-64 ( n s -- n' ) 64 bitroll ; inline HINTS: bitroll-64 bignum fixnum ; @@ -40,7 +41,7 @@ HINTS: bitroll-64 bignum fixnum ; ! flags MACRO: flags ( values -- ) - [ 0 ] [ [ execute bitor ] curry compose ] reduce ; + [ 0 ] [ [ dup word? [ execute ] when bitor ] curry compose ] reduce ; ! bitfield r swapd execute r> ] [ ] ? + first2 over word? [ [ swapd execute ] dip ] [ ] ? [ shift bitor ] append 2curry ; PRIVATE> @@ -91,4 +92,4 @@ M: bignum (bit-count) PRIVATE> : bit-count ( x -- n ) - dup 0 >= [ (bit-count) ] [ bitnot (bit-count) ] if ; inline + dup 0 < [ bitnot ] when (bit-count) ; inline