diff --git a/readme.md b/readme.md index 96e4874..65de26b 100644 --- a/readme.md +++ b/readme.md @@ -59,7 +59,7 @@ or ## Table of Contents - [bits](#bits) - - operations ([and](#bitsand), [nand](#bitsnand), [nor](#bitsnor), [not](#bitsnot), [or](#bitsor), [xnor](#bitsxnor), [xor](#bitsxor)) + - operations ([and](#bitsand), [circularShiftLeft](#bitscircularshiftleft), [circularShiftRight](#bitscircularshiftright), [nand](#bitsnand), [nor](#bitsnor), [not](#bitsnot), [or](#bitsor), [xnor](#bitsxnor), [xor](#bitsxor)) - reduce operations ([reduceAnd](#bitsreduceand), [reduceNand](#bitsreducenand), [reduceNor](#bitsreducenor), [reduceOr](#bitsreduceor), [reduceXnor](#bitsreducexnor), [reduceXor](#bitsreducexor)) - [toString](#bitstostring) - [buffer](#buffer) @@ -104,6 +104,32 @@ bitwise.bits.and([1, 0, 0, 0, 1, 1, 0, 1], [0, 1, 1, 0, 0, 1, 0, 0]) // [0, 0, 0, 0, 0, 1, 0, 0] ``` +### bits.circularShiftLeft + +```ts +(bits: Array<0|1>, amount: number): Array<0|1> +``` + +Applies the bitwise `ROL` operation, expects two arrays of the same size and a shift amount and returns a new one. + +```js +bitwise.bits.circularShiftLeft([0, 0, 0, 1, 1, 1, 1, 1], 1) +// [0, 0, 1, 1, 1, 1, 1, 0] +``` + +### bits.circularShiftRight + +```ts +(bits: Array<0|1>, amount: number): Array<0|1> +``` + +Applies the bitwise `ROR` operation, expects two arrays of the same size and a shift amount and returns a new one. + +```js +bitwise.bits.circularShiftRight([0, 0, 0, 1, 1, 1, 1, 1], 1) +// [1, 0, 0, 0, 1, 1, 1, 1] +``` + ### bits.nand ```ts diff --git a/source/bits/circular-shift-left.test.ts b/source/bits/circular-shift-left.test.ts new file mode 100644 index 0000000..b51ada3 --- /dev/null +++ b/source/bits/circular-shift-left.test.ts @@ -0,0 +1,54 @@ +import { Bits } from '../types' +import circularShiftLeft from './circular-shift-left' + +test('circularShiftLeft with amount 1', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [0, 0, 0, 1, 1, 0, 1, 1], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [0, 0, 1, 1, 1, 1, 1, 0], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftLeft(input, 1)).toEqual(expectedResult) +}) + +test('circularShiftLeft with amount 2', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [0, 0, 1, 1, 0, 1, 1, 0], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [0, 1, 1, 1, 1, 1, 0, 0], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftLeft(input, 2)).toEqual(expectedResult) +}) + +test('circularShiftLeft with amount 3', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [0, 1, 1, 0, 1, 1, 0, 0], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 0, 0, 0], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftLeft(input, 3)).toEqual(expectedResult) +}) + +test('circularShiftLeft throws when amount too large', () => { + expect(() => circularShiftLeft([0, 1], 3)).toThrow() +}) diff --git a/source/bits/circular-shift-left.ts b/source/bits/circular-shift-left.ts new file mode 100644 index 0000000..9a0db9d --- /dev/null +++ b/source/bits/circular-shift-left.ts @@ -0,0 +1,25 @@ +import { Bits } from '../types' + +/** + * Circular Shift Left + * + * @example + * circularShiftLeft([1,0,1,1,0,1]) => [0,1,1,0,1,1] + * + * @see {@link https://en.wikipedia.org/wiki/Circular_shift} + * + * @param {Array} bits input data + * @param {number} amount how far should it be shifted + * @return {Array} [ROL bits] + */ +export default (bits: Bits, amount: number): Bits => { + const result: Bits = [] + + if (amount > bits.length) + throw new Error('shift amount can’t be larger than bits array length') + + for (let i = 0; i < bits.length; i++) + result[(bits.length + i - amount) % bits.length] = bits[i] + + return result +} diff --git a/source/bits/circular-shift-right.test.ts b/source/bits/circular-shift-right.test.ts new file mode 100644 index 0000000..e75ce29 --- /dev/null +++ b/source/bits/circular-shift-right.test.ts @@ -0,0 +1,54 @@ +import { Bits } from '../types' +import circularShiftRight from './circular-shift-right' + +test('circularShiftRight with amount 1', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [1, 1, 0, 0, 0, 1, 1, 0], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [1, 0, 0, 0, 1, 1, 1, 1], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftRight(input, 1)).toEqual(expectedResult) +}) + +test('circularShiftRight with amount 2', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [0, 1, 1, 0, 0, 0, 1, 1], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [1, 1, 0, 0, 0, 1, 1, 1], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftRight(input, 2)).toEqual(expectedResult) +}) + +test('circularShiftRight with amount 3', () => { + const testCases: Array<[Bits, Bits]> = [ + [ + [1, 0, 0, 0, 1, 1, 0, 1], + [1, 0, 1, 1, 0, 0, 0, 1], + ], + [ + [0, 0, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 0, 0, 0, 1, 1], + ], + ] + + for (const [input, expectedResult] of testCases) + expect(circularShiftRight(input, 3)).toEqual(expectedResult) +}) + +test('circularShiftRight throws when amount too large', () => { + expect(() => circularShiftRight([0, 1], 3)).toThrow() +}) diff --git a/source/bits/circular-shift-right.ts b/source/bits/circular-shift-right.ts new file mode 100644 index 0000000..e2da7ad --- /dev/null +++ b/source/bits/circular-shift-right.ts @@ -0,0 +1,25 @@ +import { Bits } from '../types' + +/** + * Circular Shift Right + * + * @example + * circularShiftRight([1,0,1,1,0,1]) => [1,1,0,1,1,0] + * + * @see {@link https://en.wikipedia.org/wiki/Circular_shift} + * + * @param {Array} bits input data + * @param {number} amount how far should it be shifted + * @return {Array} [ROR bits] + */ +export default (bits: Bits, amount: number): Bits => { + const result: Bits = [] + + if (amount > bits.length) + throw new Error('shift amount can’t be larger than bits array length') + + for (let i = 0; i < bits.length; i++) + result[(i + amount) % bits.length] = bits[i] + + return result +} diff --git a/source/bits/index.ts b/source/bits/index.ts index d1eb53a..e68e1af 100644 --- a/source/bits/index.ts +++ b/source/bits/index.ts @@ -1,4 +1,6 @@ import and from './and' +import circularShiftLeft from './circular-shift-left' +import circularShiftRight from './circular-shift-right' import nand from './nand' import nor from './nor' import not from './not' @@ -16,6 +18,8 @@ import xor from './xor' export { and, + circularShiftLeft, + circularShiftRight, nand, nor, not, @@ -34,6 +38,8 @@ export { export default { and, + circularShiftLeft, + circularShiftRight, nand, nor, not,