Added bitslice operations for bitops (#14016)
* added bit operations based on bit slices, clarified documentation, made non-mutating versions of mask ops * Added since annotations, some runnable examples * Added mask()/masked() functions, changed internal workings of mask ops to use new bit* funcs * Changelog updated for new bitops improvements * Reorganization, added runnable examples * Documentation adjustments * Add incltrl for since annotation * Fix masked() impl * Fix mask() return type * Don't call toUnsigned on already unsigned types * Remove improper `var T` for flipMasked() * Fix return types for flipMasked() * Slight syntactic cleanup for *masked ops * Added tests for bitslice operations, new mask() operation, non-mutating mask ops * Fix setmasked() var T issue * More comprehensive tests * Fix runnable example for bitsliced() * Fix runnable example for mask()
This commit is contained in:
parent
48e7775ad1
commit
b8e6ea7547
3 changed files with 280 additions and 22 deletions
|
|
@ -61,6 +61,10 @@
|
||||||
- `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble.
|
- `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble.
|
||||||
- `dollars.$` now works for unsigned ints with `nim js`
|
- `dollars.$` now works for unsigned ints with `nim js`
|
||||||
|
|
||||||
|
- Improvements to the `bitops` module, including bitslices, non-mutating versions
|
||||||
|
of the original masking functions, `mask`/`masked`, and varargs support for
|
||||||
|
`bitand`, `bitor`, and `bitxor`.
|
||||||
|
|
||||||
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
|
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
|
||||||
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency
|
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency
|
||||||
with regular proc definitions (although you cannot use semicolons).
|
with regular proc definitions (although you cannot use semicolons).
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
## may return undefined and/or platform dependent value if given invalid input.
|
## may return undefined and/or platform dependent value if given invalid input.
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
import std/private/since
|
||||||
|
|
||||||
proc bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI", noSideEffect.}
|
proc bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI", noSideEffect.}
|
||||||
## Computes the `bitwise complement` of the integer `x`.
|
## Computes the `bitwise complement` of the integer `x`.
|
||||||
|
|
@ -85,37 +86,220 @@ template forwardImpl(impl, arg) {.dirty.} =
|
||||||
|
|
||||||
when defined(nimHasalignOf):
|
when defined(nimHasalignOf):
|
||||||
type BitsRange*[T] = range[0..sizeof(T)*8-1]
|
type BitsRange*[T] = range[0..sizeof(T)*8-1]
|
||||||
## Returns a range with all bit positions for type ``T``.
|
## A range with all bit positions for type ``T``
|
||||||
|
|
||||||
proc setMask*[T: SomeInteger](v: var T, mask: T) {.inline.} =
|
func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Returns an extracted (and shifted) slice of bits from ``v``.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert 0b10111.bitsliced(2 .. 4) == 0b101
|
||||||
|
doAssert 0b11100.bitsliced(0 .. 2) == 0b100
|
||||||
|
doAssert 0b11100.bitsliced(0 ..< 3) == 0b100
|
||||||
|
|
||||||
|
let
|
||||||
|
upmost = sizeof(T) * 8 - 1
|
||||||
|
uv = when v is SomeUnsignedInt: v else: v.toUnsigned
|
||||||
|
(uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
|
||||||
|
|
||||||
|
proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v`` into an extracted (and shifted) slice of bits from ``v``.
|
||||||
|
runnableExamples:
|
||||||
|
var x = 0b101110
|
||||||
|
x.bitslice(2 .. 4)
|
||||||
|
doAssert x == 0b011
|
||||||
|
|
||||||
|
let
|
||||||
|
upmost = sizeof(T) * 8 - 1
|
||||||
|
uv = when v is SomeUnsignedInt: v else: v.toUnsigned
|
||||||
|
v = (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
|
||||||
|
|
||||||
|
func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Creates a bitmask based on a slice of bits.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert toMask[int32](1 .. 3) == 0b1110'i32
|
||||||
|
doAssert toMask[int32](0 .. 3) == 0b1111'i32
|
||||||
|
|
||||||
|
let
|
||||||
|
upmost = sizeof(T) * 8 - 1
|
||||||
|
bitmask = when T is SomeUnsignedInt:
|
||||||
|
bitnot(0.T)
|
||||||
|
else:
|
||||||
|
bitnot(0.T).toUnsigned
|
||||||
|
(bitmask shl (upmost - slice.b + slice.a) shr (upmost - slice.b)).T
|
||||||
|
|
||||||
|
proc masked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
|
||||||
|
## Returns ``v``, with only the ``1`` bits from ``mask`` matching those of
|
||||||
|
## ``v`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.masked(0b0000_1010'u8) == 0b0000_0010'u8
|
||||||
|
|
||||||
|
bitand(v, mask)
|
||||||
|
|
||||||
|
func masked*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v``, with only the ``1`` bits in the range of ``slice``
|
||||||
|
## matching those of ``v`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_1011'u8
|
||||||
|
doAssert v.masked(1 .. 3) == 0b0000_1010'u8
|
||||||
|
|
||||||
|
bitand(v, toMask[T](slice))
|
||||||
|
|
||||||
|
proc mask*[T: SomeInteger](v: var T; mask: T) {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v``, with only the ``1`` bits from ``mask`` matching those of
|
||||||
|
## ``v`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
v.mask(0b0000_1010'u8)
|
||||||
|
doAssert v == 0b0000_1010'u8
|
||||||
|
|
||||||
|
v = bitand(v, mask)
|
||||||
|
|
||||||
|
proc mask*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v``, with only the ``1`` bits in the range of ``slice``
|
||||||
|
## matching those of ``v`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_1011'u8
|
||||||
|
v.mask(1 .. 3)
|
||||||
|
doAssert v == 0b0000_1010'u8
|
||||||
|
|
||||||
|
v = bitand(v, toMask[T](slice))
|
||||||
|
|
||||||
|
func setMasked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
|
||||||
## Returns ``v``, with all the ``1`` bits from ``mask`` set to 1.
|
## Returns ``v``, with all the ``1`` bits from ``mask`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.setMasked(0b0000_1010'u8) == 0b0000_1011'u8
|
||||||
|
|
||||||
|
bitor(v, mask)
|
||||||
|
|
||||||
|
func setMasked*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Returns ``v``, with all the ``1`` bits in the range of ``slice`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.setMasked(2 .. 3) == 0b0000_1111'u8
|
||||||
|
|
||||||
|
bitor(v, toMask[T](slice))
|
||||||
|
|
||||||
|
proc setMask*[T: SomeInteger](v: var T; mask: T) {.inline.} =
|
||||||
|
## Mutates ``v``, with all the ``1`` bits from ``mask`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitor` operation.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.setMask(0b0000_1010'u8)
|
v.setMask(0b0000_1010'u8)
|
||||||
doAssert v == 0b0000_1011'u8
|
doAssert v == 0b0000_1011'u8
|
||||||
|
|
||||||
v = v or mask
|
v = bitor(v, mask)
|
||||||
|
|
||||||
proc clearMask*[T: SomeInteger](v: var T, mask: T) {.inline.} =
|
proc setMask*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v``, with all the ``1`` bits in the range of ``slice`` set to 1.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
v.setMask(2 .. 3)
|
||||||
|
doAssert v == 0b0000_1111'u8
|
||||||
|
|
||||||
|
v = bitor(v, toMask[T](slice))
|
||||||
|
|
||||||
|
func clearMasked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
|
||||||
## Returns ``v``, with all the ``1`` bits from ``mask`` set to 0.
|
## Returns ``v``, with all the ``1`` bits from ``mask`` set to 0.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation with an *inverted mask.*
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.clearMasked(0b0000_1010'u8) == 0b0000_0001'u8
|
||||||
|
|
||||||
|
bitand(v, bitnot(mask))
|
||||||
|
|
||||||
|
func clearMasked*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Returns ``v``, with all the ``1`` bits in the range of ``slice`` set to 0.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation with an *inverted mask.*
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.clearMasked(1 .. 3) == 0b0000_0001'u8
|
||||||
|
|
||||||
|
bitand(v, bitnot(toMask[T](slice)))
|
||||||
|
|
||||||
|
proc clearMask*[T: SomeInteger](v: var T; mask: T) {.inline.} =
|
||||||
|
## Mutates ``v``, with all the ``1`` bits from ``mask`` set to 0.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation with an *inverted mask.*
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.clearMask(0b0000_1010'u8)
|
v.clearMask(0b0000_1010'u8)
|
||||||
doAssert v == 0b0000_0001'u8
|
doAssert v == 0b0000_0001'u8
|
||||||
|
|
||||||
v = v and not mask
|
v = bitand(v, bitnot(mask))
|
||||||
|
|
||||||
proc flipMask*[T: SomeInteger](v: var T, mask: T) {.inline.} =
|
proc clearMask*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||||
|
## Mutates ``v``, with all the ``1`` bits in the range of ``slice`` set to 0.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitand` operation with an *inverted mask.*
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
v.clearMask(1 .. 3)
|
||||||
|
doAssert v == 0b0000_0001'u8
|
||||||
|
|
||||||
|
v = bitand(v, bitnot(toMask[T](slice)))
|
||||||
|
|
||||||
|
func flipMasked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
|
||||||
## Returns ``v``, with all the ``1`` bits from ``mask`` flipped.
|
## Returns ``v``, with all the ``1`` bits from ``mask`` flipped.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitxor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.flipMasked(0b0000_1010'u8) == 0b0000_1001'u8
|
||||||
|
|
||||||
|
bitxor(v, mask)
|
||||||
|
|
||||||
|
func flipMasked*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||||
|
## Returns ``v``, with all the ``1`` bits in the range of ``slice`` flipped.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitxor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
doAssert v.flipMasked(1 .. 3) == 0b0000_1001'u8
|
||||||
|
|
||||||
|
bitxor(v, toMask[T](slice))
|
||||||
|
|
||||||
|
proc flipMask*[T: SomeInteger](v: var T; mask: T) {.inline.} =
|
||||||
|
## Mutates ``v``, with all the ``1`` bits from ``mask`` flipped.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitxor` operation.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.flipMask(0b0000_1010'u8)
|
v.flipMask(0b0000_1010'u8)
|
||||||
doAssert v == 0b0000_1001'u8
|
doAssert v == 0b0000_1001'u8
|
||||||
|
|
||||||
v = v xor mask
|
v = bitxor(v, mask)
|
||||||
|
|
||||||
proc setBit*[T: SomeInteger](v: var T, bit: BitsRange[T]) {.inline.} =
|
proc flipMask*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||||
## Returns ``v``, with the bit at position ``bit`` set to 1.
|
## Mutates ``v``, with all the ``1`` bits in the range of ``slice`` flipped.
|
||||||
|
##
|
||||||
|
## Effectively maps to a `bitxor` operation.
|
||||||
|
runnableExamples:
|
||||||
|
var v = 0b0000_0011'u8
|
||||||
|
v.flipMask(1 .. 3)
|
||||||
|
doAssert v == 0b0000_1001'u8
|
||||||
|
|
||||||
|
v = bitxor(v, toMask[T](slice))
|
||||||
|
|
||||||
|
proc setBit*[T: SomeInteger](v: var T; bit: BitsRange[T]) {.inline.} =
|
||||||
|
## Mutates ``v``, with the bit at position ``bit`` set to 1
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.setBit(5'u8)
|
v.setBit(5'u8)
|
||||||
|
|
@ -123,8 +307,8 @@ when defined(nimHasalignOf):
|
||||||
|
|
||||||
v.setMask(1.T shl bit)
|
v.setMask(1.T shl bit)
|
||||||
|
|
||||||
proc clearBit*[T: SomeInteger](v: var T, bit: BitsRange[T]) {.inline.} =
|
proc clearBit*[T: SomeInteger](v: var T; bit: BitsRange[T]) {.inline.} =
|
||||||
## Returns ``v``, with the bit at position ``bit`` set to 0.
|
## Mutates ``v``, with the bit at position ``bit`` set to 0
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.clearBit(1'u8)
|
v.clearBit(1'u8)
|
||||||
|
|
@ -132,8 +316,8 @@ when defined(nimHasalignOf):
|
||||||
|
|
||||||
v.clearMask(1.T shl bit)
|
v.clearMask(1.T shl bit)
|
||||||
|
|
||||||
proc flipBit*[T: SomeInteger](v: var T, bit: BitsRange[T]) {.inline.} =
|
proc flipBit*[T: SomeInteger](v: var T; bit: BitsRange[T]) {.inline.} =
|
||||||
## Returns ``v``, with the bit at position ``bit`` flipped.
|
## Mutates ``v``, with the bit at position ``bit`` flipped
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.flipBit(1'u8)
|
v.flipBit(1'u8)
|
||||||
|
|
@ -145,8 +329,8 @@ when defined(nimHasalignOf):
|
||||||
|
|
||||||
v.flipMask(1.T shl bit)
|
v.flipMask(1.T shl bit)
|
||||||
|
|
||||||
macro setBits*(v: var typed, bits: varargs[typed]): untyped =
|
macro setBits*(v: typed; bits: varargs[typed]): untyped =
|
||||||
## Returns ``v``, with the bits at positions ``bits`` set to 1.
|
## Mutates ``v``, with the bits at positions ``bits`` set to 1
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_0011'u8
|
var v = 0b0000_0011'u8
|
||||||
v.setBits(3, 5, 7)
|
v.setBits(3, 5, 7)
|
||||||
|
|
@ -157,8 +341,8 @@ when defined(nimHasalignOf):
|
||||||
for bit in bits:
|
for bit in bits:
|
||||||
result.add newCall("setBit", v, bit)
|
result.add newCall("setBit", v, bit)
|
||||||
|
|
||||||
macro clearBits*(v: var typed, bits: varargs[typed]): untyped =
|
macro clearBits*(v: typed; bits: varargs[typed]): untyped =
|
||||||
## Returns ``v``, with the bits at positions ``bits`` set to 0.
|
## Mutates ``v``, with the bits at positions ``bits`` set to 0
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b1111_1111'u8
|
var v = 0b1111_1111'u8
|
||||||
v.clearBits(1, 3, 5, 7)
|
v.clearBits(1, 3, 5, 7)
|
||||||
|
|
@ -169,8 +353,8 @@ when defined(nimHasalignOf):
|
||||||
for bit in bits:
|
for bit in bits:
|
||||||
result.add newCall("clearBit", v, bit)
|
result.add newCall("clearBit", v, bit)
|
||||||
|
|
||||||
macro flipBits*(v: var typed, bits: varargs[typed]): untyped =
|
macro flipBits*(v: typed; bits: varargs[typed]): untyped =
|
||||||
## Returns ``v``, with the bits at positions ``bits`` set to 0.
|
## Mutates ``v``, with the bits at positions ``bits`` set to 0
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_1111'u8
|
var v = 0b0000_1111'u8
|
||||||
v.flipBits(1, 3, 5, 7)
|
v.flipBits(1, 3, 5, 7)
|
||||||
|
|
@ -181,8 +365,9 @@ when defined(nimHasalignOf):
|
||||||
for bit in bits:
|
for bit in bits:
|
||||||
result.add newCall("flipBit", v, bit)
|
result.add newCall("flipBit", v, bit)
|
||||||
|
|
||||||
proc testBit*[T: SomeInteger](v: T, bit: BitsRange[T]): bool {.inline.} =
|
|
||||||
## Returns true if the bit in ``v`` at positions ``bit`` is set to 1.
|
proc testBit*[T: SomeInteger](v: T; bit: BitsRange[T]): bool {.inline.} =
|
||||||
|
## Returns true if the bit in ``v`` at positions ``bit`` is set to 1
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var v = 0b0000_1111'u8
|
var v = 0b0000_1111'u8
|
||||||
doAssert v.testBit(0)
|
doAssert v.testBit(0)
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ proc main1() =
|
||||||
doAssert( U64A.rotateRightBits(64) == U64A)
|
doAssert( U64A.rotateRightBits(64) == U64A)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
# mask operations
|
# basic mask operations (mutating)
|
||||||
var v: uint8
|
var v: uint8
|
||||||
v.setMask(0b1100_0000)
|
v.setMask(0b1100_0000)
|
||||||
v.setMask(0b0000_1100)
|
v.setMask(0b0000_1100)
|
||||||
|
|
@ -182,6 +182,75 @@ proc main1() =
|
||||||
doAssert(v == 0b0001_0001)
|
doAssert(v == 0b0001_0001)
|
||||||
v.clearMask(0b0001_0001)
|
v.clearMask(0b0001_0001)
|
||||||
doAssert(v == 0b0000_0000)
|
doAssert(v == 0b0000_0000)
|
||||||
|
v.setMask(0b0001_1110)
|
||||||
|
doAssert(v == 0b0001_1110)
|
||||||
|
v.mask(0b0101_0100)
|
||||||
|
doAssert(v == 0b0001_0100)
|
||||||
|
block:
|
||||||
|
# basic mask operations (non-mutating)
|
||||||
|
let v = 0b1100_0000'u8
|
||||||
|
doAssert(v.masked(0b0000_1100) == 0b0000_0000)
|
||||||
|
doAssert(v.masked(0b1000_1100) == 0b1000_0000)
|
||||||
|
doAssert(v.setMasked(0b0000_1100) == 0b1100_1100)
|
||||||
|
doAssert(v.setMasked(0b1000_1110) == 0b1100_1110)
|
||||||
|
doAssert(v.flipMasked(0b1100_1000) == 0b0000_1000)
|
||||||
|
doAssert(v.flipMasked(0b0000_1100) == 0b1100_1100)
|
||||||
|
let t = 0b1100_0110'u8
|
||||||
|
doAssert(t.clearMasked(0b0100_1100) == 0b1000_0010)
|
||||||
|
doAssert(t.clearMasked(0b1100_0000) == 0b0000_0110)
|
||||||
|
block:
|
||||||
|
# basic bitslice opeartions
|
||||||
|
let a = 0b1111_1011'u8
|
||||||
|
doAssert(a.bitsliced(0 .. 3) == 0b1011)
|
||||||
|
doAssert(a.bitsliced(2 .. 3) == 0b10)
|
||||||
|
doAssert(a.bitsliced(4 .. 7) == 0b1111)
|
||||||
|
|
||||||
|
# same thing, but with exclusive ranges.
|
||||||
|
doAssert(a.bitsliced(0 ..< 4) == 0b1011)
|
||||||
|
doAssert(a.bitsliced(2 ..< 4) == 0b10)
|
||||||
|
doAssert(a.bitsliced(4 ..< 8) == 0b1111)
|
||||||
|
|
||||||
|
# mutating
|
||||||
|
var b = 0b1111_1011'u8
|
||||||
|
b.bitslice(1 .. 3)
|
||||||
|
doAssert(b == 0b101)
|
||||||
|
|
||||||
|
# loop test:
|
||||||
|
let c = 0b1111_1111'u8
|
||||||
|
for i in 0 .. 7:
|
||||||
|
doAssert(c.bitsliced(i .. 7) == c shr i)
|
||||||
|
block:
|
||||||
|
# bitslice versions of mask operations (mutating)
|
||||||
|
var a = 0b1100_1100'u8
|
||||||
|
let b = toMask[uint8](2 .. 3)
|
||||||
|
a.mask(b)
|
||||||
|
doAssert(a == 0b0000_1100)
|
||||||
|
a.setMask(4 .. 7)
|
||||||
|
doAssert(a == 0b1111_1100)
|
||||||
|
a.flipMask(1 .. 3)
|
||||||
|
doAssert(a == 0b1111_0010)
|
||||||
|
a.flipMask(2 .. 4)
|
||||||
|
doAssert(a == 0b1110_1110)
|
||||||
|
a.clearMask(2 .. 4)
|
||||||
|
doAssert(a == 0b1110_0010)
|
||||||
|
a.mask(0 .. 3)
|
||||||
|
doAssert(a == 0b0000_0010)
|
||||||
|
|
||||||
|
# composition of mask from slices:
|
||||||
|
let c = bitor(toMask[uint8](2 .. 3), toMask[uint8](5 .. 7))
|
||||||
|
doAssert(c == 0b1110_1100'u8)
|
||||||
|
block:
|
||||||
|
# bitslice versions of mask operations (non-mutating)
|
||||||
|
let a = 0b1100_1100'u8
|
||||||
|
doAssert(a.masked(toMask[uint8](2 .. 3)) == 0b0000_1100)
|
||||||
|
doAssert(a.masked(2 .. 3) == 0b0000_1100)
|
||||||
|
doAssert(a.setMasked(0 .. 3) == 0b1100_1111)
|
||||||
|
doAssert(a.setMasked(3 .. 4) == 0b1101_1100)
|
||||||
|
doAssert(a.flipMasked(0 .. 3) == 0b1100_0011)
|
||||||
|
doAssert(a.flipMasked(0 .. 7) == 0b0011_0011)
|
||||||
|
doAssert(a.flipMasked(2 .. 3) == 0b1100_0000)
|
||||||
|
doAssert(a.clearMasked(2 .. 3) == 0b1100_0000)
|
||||||
|
doAssert(a.clearMasked(3 .. 6) == 0b1000_0100)
|
||||||
block:
|
block:
|
||||||
# single bit operations
|
# single bit operations
|
||||||
var v: uint8
|
var v: uint8
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue