bitwise docs, fix some bugs in bitwise words
parent
439acef7a1
commit
7aeeb2c9ce
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
<PRIVATE
|
||||
|
@ -51,7 +52,7 @@ M: integer (bitfield-quot) ( spec -- quot )
|
|||
[ swapd shift bitor ] curry ;
|
||||
|
||||
M: pair (bitfield-quot) ( spec -- quot )
|
||||
first2 over word? [ >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
|
||||
|
|
Loading…
Reference in New Issue