bitops
Этот модуль реализует ряд методов низкого уровня для работы с битами.
По умолчанию этот модуль использует встроенные функции компилятора, где это возможно, для повышения производительности на поддерживаемых компиляторах: GCC, LLVM_GCC, CLANG, VCC, ICC.
Модуль переключится на чистые процедуры Nim, если бэкенд не поддерживается. Вы также можете использовать флаг noIntrinsicsBitOpts для отключения встроенных функций компилятора.
Этот модуль также совместим с другими бэкендами: Javascript, Nimscript а также с compiletime VM.
В результате использования оптимизированных функций/встроенных функций, некоторые функции могут возвращать неопределенные результаты, если входные данные некорректны. Вы можете использовать флаг noUndefinedBitOpts для принудительного обеспечения предсказуемого поведения для всех входных данных, что приведет к небольшой потере производительности.
В настоящее время только fastLog2, firstSetBit, `countLeadingZeroBits, countTrailingZeroBits могут возвращать неопределенные и/или зависящие от платформы значения, если на вход поданы некорректные данные.
Импорты
- macros, since
Типы
BitsRange[T] = range[0 .. sizeof(T) * 8 - 1]
- Диапазон со всеми позициями битов для типа
TИсходный код Изменить
Процедуры
proc bitnot[T: SomeInteger](x: T): T {...}{.magic: "BitnotI", noSideEffect.}- Вычисляет
bitwise complementцелого числаx. Исходный код Редактировать proc bitslice[T: SomeInteger](v: var T; slice: Slice[int]) {...}{.inline.}- Изменяет
vна извлечённый (и сдвинутый) фрагмент бит изv.Пример:
var x = 0b101110 x.bitslice(2 .. 4) doAssert x == 0b011
Исходный код Редактировать proc masked[T: SomeInteger](v, mask: T): T {...}{.inline.}-
Возвращает
v, с установленными в 1 только1битами изmask, совпадающими с битамиv.Эффективно соответствует операции
bitand.Пример:
var v = 0b0000_0011'u8 doAssert v.masked(0b0000_1010'u8) == 0b0000_0010'u8
Исходный код Редактировать proc mask[T: SomeInteger](v: var T; mask: T) {...}{.inline.}-
Изменяет
v, с установленными в 1 только1битами изmask, совпадающими с битамиv.Эффективно соответствует операции
bitand.Пример:
var v = 0b0000_0011'u8 v.mask(0b0000_1010'u8) doAssert v == 0b0000_0010'u8
Исходный код Редактировать proc mask[T: SomeInteger](v: var T; slice: Slice[int]) {...}{.inline.}-
Изменяет
v, с установленными в 1 только1битами в диапазонеslice, совпадающими с битамиv.Эффективно соответствует операции
bitand.Пример:
var v = 0b0000_1011'u8 v.mask(1 .. 3) doAssert v == 0b0000_1010'u8
Исходный код Редактировать proc setMask[T: SomeInteger](v: var T; mask: T) {...}{.inline.}-
Изменяет
v, с установленными в 1 всеми1битами изmask.Эффективно соответствует операции
bitor.Пример:
var v = 0b0000_0011'u8 v.setMask(0b0000_1010'u8) doAssert v == 0b0000_1011'u8
Исходный код Редактировать proc setMask[T: SomeInteger](v: var T; slice: Slice[int]) {...}{.inline.}-
Изменяет
v, с установленными в 1 всеми1битами в диапазонеslice.Эффективно соответствует операции
bitor.Пример:
var v = 0b0000_0011'u8 v.setMask(2 .. 3) doAssert v == 0b0000_1111'u8
Исходный код Редактировать proc clearMask[T: SomeInteger](v: var T; mask: T) {...}{.inline.}-
Изменяет
v, с установленными в 0 всеми1битами изmask.Эффективно соответствует операции
bitandс инвертированной маской.Пример:
var v = 0b0000_0011'u8 v.clearMask(0b0000_1010'u8) doAssert v == 0b0000_0001'u8
Исходный код Редактировать proc clearMask[T: SomeInteger](v: var T; slice: Slice[int]) {...}{.inline.}-
Изменяет
v, с установленными в 0 всеми1битами в диапазонеslice.Эффективно соответствует операции
bitandс инвертированной маской.Пример:
var v = 0b0000_0011'u8 v.clearMask(1 .. 3) doAssert v == 0b0000_0001'u8
Исходный код Редактировать proc flipMask[T: SomeInteger](v: var T; mask: T) {...}{.inline.}-
Изменяет
v, с инвертированными всеми1битами изmask.Эффективно соответствует операции
bitxor.Пример:
var v = 0b0000_0011'u8 v.flipMask(0b0000_1010'u8) doAssert v == 0b0000_1001'u8
Исходный код Редактировать proc flipMask[T: SomeInteger](v: var T; slice: Slice[int]) {...}{.inline.}-
Изменяет
v, с инвертированными всеми1битами в диапазонеslice.Эффективно соответствует операции
bitxor.Пример:
var v = 0b0000_0011'u8 v.flipMask(1 .. 3) doAssert v == 0b0000_1101'u8
Исходный код Редактировать proc setBit[T: SomeInteger](v: var T; bit: BitsRange[T]) {...}{.inline.}- Изменяет
v, с установленным в 1 битом на позицииbitПример:
var v = 0b0000_0011'u8 v.setBit(5'u8) doAssert v == 0b0010_0011'u8
Исходный код Редактировать proc clearBit[T: SomeInteger](v: var T; bit: BitsRange[T]) {...}{.inline.}- Изменяет
v, с установленным в 0 битом на позицииbitПример:
var v = 0b0000_0011'u8 v.clearBit(1'u8) doAssert v == 0b0000_0001'u8
Исходный код Редактировать proc flipBit[T: SomeInteger](v: var T; bit: BitsRange[T]) {...}{.inline.}- Изменяет
v, с инвертированным битом на позицииbitПример:
var v = 0b0000_0011'u8 v.flipBit(1'u8) doAssert v == 0b0000_0001'u8 v = 0b0000_0011'u8 v.flipBit(2'u8) doAssert v == 0b0000_0111'u8
Исходный код Редактировать proc testBit[T: SomeInteger](v: T; bit: BitsRange[T]): bool {...}{.inline.}- Возвращает true, если бит в
vна позицияхbitравен 1Пример:
var v = 0b0000_1111'u8 doAssert v.testBit(0) doAssert not v.testBit(7)
Исходный код Редактировать proc countSetBits(x: SomeInteger): int {...}{.inline, noSideEffect.}- Считает установленные биты в целое число. (также называется весом Хэмминга.)
Пример:
doAssert countSetBits(0b0000_0011'u8) == 2 doAssert countSetBits(0b1010_1010'u8) == 4
Исходный код Редактировать proc popcount(x: SomeInteger): int {...}{.inline, noSideEffect.}- Псевдоним для countSetBits. (Вес Хэмминга.) Исходный код Редактировать
proc parityBits(x: SomeInteger): int {...}{.inline, noSideEffect.}- Вычисляет чётность бит в целом числе. Если количество 1-бит нечётное, чётность равна 1, иначе 0.
Пример:
doAssert parityBits(0b0000_0000'u8) == 0 doAssert parityBits(0b0101_0001'u8) == 1 doAssert parityBits(0b0110_1001'u8) == 0 doAssert parityBits(0b0111_1111'u8) == 1
Исходный код Редактировать proc firstSetBit(x: SomeInteger): int {...}{.inline, noSideEffect.}- Возвращает индекс (с учётом нумерации с 1) наименее значимого установленного бита x. Если
xравно нулю, когдаnoUndefinedBitOptsустановлено, результат равен 0, иначе результат неопределён.Пример:
doAssert firstSetBit(0b0000_0001'u8) == 1 doAssert firstSetBit(0b0000_0010'u8) == 2 doAssert firstSetBit(0b0000_0100'u8) == 3 doAssert firstSetBit(0b0000_1000'u8) == 4 doAssert firstSetBit(0b0000_1111'u8) == 1
Исходный код Редактировать proc fastLog2(x: SomeInteger): int {...}{.inline, noSideEffect.}- Быстро находит логарифм по основанию 2 целого числа. Если
xравно нулю, когдаnoUndefinedBitOptsустановлено, результат равен -1, иначе результат неопределён.Пример:
doAssert fastLog2(0b0000_0001'u8) == 0 doAssert fastLog2(0b0000_0010'u8) == 1 doAssert fastLog2(0b0000_0100'u8) == 2 doAssert fastLog2(0b0000_1000'u8) == 3 doAssert fastLog2(0b0000_1111'u8) == 3
Исходный код Редактировать proc countLeadingZeroBits(x: SomeInteger): int {...}{.inline, noSideEffect.}-
Возвращает количество ведущих нулевых бит в целом числе. Если
xравно нулю, когдаnoUndefinedBitOptsустановлено, результат равен 0, иначе результат неопределён.См. также:
Пример:
doAssert countLeadingZeroBits(0b0000_0001'u8) == 7 doAssert countLeadingZeroBits(0b0000_0010'u8) == 6 doAssert countLeadingZeroBits(0b0000_0100'u8) == 5 doAssert countLeadingZeroBits(0b0000_1000'u8) == 4 doAssert countLeadingZeroBits(0b0000_1111'u8) == 4
Исходный код Редактировать proc countTrailingZeroBits(x: SomeInteger): int {...}{.inline, noSideEffect.}-
Возвращает количество концевых нулей в целом числе. Если
xравно нулю, когдаnoUndefinedBitOptsустановлено, результат равен 0, иначе результат неопределён.См. также:
Пример:
doAssert countTrailingZeroBits(0b0000_0001'u8) == 0 doAssert countTrailingZeroBits(0b0000_0010'u8) == 1 doAssert countTrailingZeroBits(0b0000_0100'u8) == 2 doAssert countTrailingZeroBits(0b0000_1000'u8) == 3 doAssert countTrailingZeroBits(0b0000_1111'u8) == 0
Исходный код Редактировать proc rotateLeftBits(value: uint8; amount: range[0 .. 8]): uint8 {...}{.inline, noSideEffect, raises: [], tags: [].}- Циклический сдвиг влево бит в значении 8 бит.
Пример:
doAssert rotateLeftBits(0b0000_0001'u8, 1) == 0b0000_0010'u8 doAssert rotateLeftBits(0b0000_0001'u8, 2) == 0b0000_0100'u8 doAssert rotateLeftBits(0b0100_0001'u8, 1) == 0b1000_0010'u8 doAssert rotateLeftBits(0b0100_0001'u8, 2) == 0b0000_0101'u8
Исходный код Редактировать proc rotateLeftBits(value: uint16; amount: range[0 .. 16]): uint16 {...}{.inline, noSideEffect, raises: [], tags: [].}-
Циклический сдвиг влево бит в значении 16 бит.
См. также:
Исходный код Редактировать proc rotateLeftBits(value: uint32; amount: range[0 .. 32]): uint32 {...}{.inline, noSideEffect, raises: [], tags: [].}
-
Побитовое циклическое сдвиг влево на 32 бита.
См. также:
Источник Изменить proc rotateLeftBits(value: uint64; amount: range[0 .. 64]): uint64 {...}{.inline, noSideEffect, raises: [], tags: [].}-
Побитовое циклическое сдвиг влево на 64 бита.
См. также:
Источник Изменить proc rotateRightBits(value: uint8; amount: range[0 .. 8]): uint8 {...}{.inline, noSideEffect, raises: [], tags: [].}- Побитовое циклическое сдвиг вправо на 8 бит.
Пример:
doAssert rotateRightBits(0b0000_0001'u8, 1) == 0b1000_0000'u8 doAssert rotateRightBits(0b0000_0001'u8, 2) == 0b0100_0000'u8 doAssert rotateRightBits(0b0100_0001'u8, 1) == 0b1010_0000'u8 doAssert rotateRightBits(0b0100_0001'u8, 2) == 0b0101_0000'u8
Источник Изменить proc rotateRightBits(value: uint16; amount: range[0 .. 16]): uint16 {...}{.inline, noSideEffect, raises: [], tags: [].}-
Побитовое циклическое сдвиг вправо на 16 бит.
См. также:
Источник Изменить proc rotateRightBits(value: uint32; amount: range[0 .. 32]): uint32 {...}{.inline, noSideEffect, raises: [], tags: [].}-
Побитовое циклическое сдвиг вправо на 32 бита.
См. также:
Источник Изменить proc rotateRightBits(value: uint64; amount: range[0 .. 64]): uint64 {...}{.inline, noSideEffect, raises: [], tags: [].}-
Побитовое циклическое сдвиг вправо на 64 бита.
См. также:
Источник Изменить proc reverseBits[T: SomeUnsignedInt](x: T): T {...}{.noSideEffect.}- Возвращает инвертированный битовый порядок x.
Пример:
doAssert reverseBits(0b10100100'u8) == 0b00100101'u8 doAssert reverseBits(0xdd'u8) == 0xbb'u8 doAssert reverseBits(0xddbb'u16) == 0xddbb'u16 doAssert reverseBits(0xdeadbeef'u32) == 0xf77db57b'u32
Источник Изменить
Функции
func bitsliced[T: SomeInteger](v: T; slice: Slice[int]): T {...}{.inline.}- Возвращает извлеченный (и сдвинутый) фрагмент битов из
v.Пример:
doAssert 0b10111.bitsliced(2 .. 4) == 0b101 doAssert 0b11100.bitsliced(0 .. 2) == 0b100 doAssert 0b11100.bitsliced(0 ..< 3) == 0b100
Источник Изменить func toMask[T: SomeInteger](slice: Slice[int]): T {...}{.inline.}- Создает битовую маску на основе фрагмента битов.
Пример:
doAssert toMask[int32](1 .. 3) == 0b1110'i32 doAssert toMask[int32](0 .. 3) == 0b1111'i32
Источник Изменить func masked[T: SomeInteger](v: T; slice: Slice[int]): T {...}{.inline.}-
Изменяет
v, используя только биты1в диапазонеslice, сопоставляя их сvи устанавливая в 1.Эффективно отображается как операция
bitand.Пример:
var v = 0b0000_1011'u8 doAssert v.masked(1 .. 3) == 0b0000_1010'u8
Источник Изменить func setMasked[T: SomeInteger](v, mask: T): T {...}{.inline.}-
Возвращает
v, устанавливая все биты1изmaskв 1.Эффективно отображается как операция
bitor.Пример:
var v = 0b0000_0011'u8 doAssert v.setMasked(0b0000_1010'u8) == 0b0000_1011'u8
Источник Изменить func setMasked[T: SomeInteger](v: T; slice: Slice[int]): T {...}{.inline.}-
Возвращает
v, устанавливая все биты1в диапазонеsliceв 1.Эффективно отображается как операция
bitor.Пример:
var v = 0b0000_0011'u8 doAssert v.setMasked(2 .. 3) == 0b0000_1111'u8
Источник Изменить func clearMasked[T: SomeInteger](v, mask: T): T {...}{.inline.}-
Возвращает
v, сбрасывая все биты1изmaskв 0.Эффективно отображается как операция
bitandс инвертированной маской.Пример:
var v = 0b0000_0011'u8 doAssert v.clearMasked(0b0000_1010'u8) == 0b0000_0001'u8
Источник Изменить func clearMasked[T: SomeInteger](v: T; slice: Slice[int]): T {...}{.inline.}-
Возвращает
v, сбрасывая все биты1в диапазонеsliceв 0.Эффективно отображается как операция
bitandс инвертированной маской.Пример:
var v = 0b0000_0011'u8 doAssert v.clearMasked(1 .. 3) == 0b0000_0001'u8
Источник Изменить func flipMasked[T: SomeInteger](v, mask: T): T {...}{.inline.}-
Возвращает
v, инвертируя все биты из1изmask.Эффективно отображается как операция
bitxor.Пример:
var v = 0b0000_0011'u8 doAssert v.flipMasked(0b0000_1010'u8) == 0b0000_1001'u8
Источник Изменить func flipMasked[T: SomeInteger](v: T; slice: Slice[int]): T {...}{.inline.}-
Возвращает
v, инвертируя все биты1в диапазонеslice.Эффективно отображается как операция
bitxor.Пример:
var v = 0b0000_0011'u8 doAssert v.flipMasked(1 .. 3) == 0b0000_1101'u8
Источник Изменить
Макросы
macro bitand[T: SomeInteger](x, y: T; z: varargs[T]): T
- Вычисляет
bitwise andвсех аргументов коллективно. Источник Изменить macro bitor[T: SomeInteger](x, y: T; z: varargs[T]): T
- Вычисляет
bitwise orвсех аргументов коллективно. Источник Изменить macro bitxor[T: SomeInteger](x, y: T; z: varargs[T]): T
- Вычисляет
bitwise xorвсех аргументов коллективно. Источник Изменить macro setBits(v: typed; bits: varargs[typed]): untyped
- Изменяет
v, устанавливая биты в позицияхbitsв 1.Пример:
var v = 0b0000_0011'u8 v.setBits(3, 5, 7) doAssert v == 0b1010_1011'u8
Источник Изменить macro clearBits(v: typed; bits: varargs[typed]): untyped
- Изменяет
v, устанавливая биты в позицияхbitsв 0.Пример:
var v = 0b1111_1111'u8 v.clearBits(1, 3, 5, 7) doAssert v == 0b0101_0101'u8
Источник Изменить macro flipBits(v: typed; bits: varargs[typed]): untyped
- Изменяет
v, устанавливая биты в позицияхbitsв 0.Пример:
var v = 0b0000_1111'u8 v.flipBits(1, 3, 5, 7) doAssert v == 0b1010_0101'u8
Источник Изменить
© 2006–2021 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/bitops.html