public static Span <long> Fwt(BitOp op, Span <long> values, bool inverses) { return(op switch { BitOp.Or => FwtOr(values, inverses), BitOp.And => FwtAnd(values, inverses), BitOp.Xor => FwtXor(values, inverses), _ => null, });
/// <summary> /// A framework for calling bitwise operation instructions. /// </summary> /// <param name="op">The op.</param> /// <param name="memory">The memory.</param> /// <param name="operation">The operation.</param> /// <exception cref="ArgumentNullException"><paramref name="operation"/> is null</exception> internal static int BitOpFunc(Opcode op, GbMemory memory, BitOp operation) { if (operation == null) { throw new ArgumentNullException(nameof(operation)); } if (op.Src != 6) { memory.R.SetR8(op.Src, operation(memory, memory.R.GetR8(op.Src))); return(1); } memory.WriteCycleHl(operation(memory, memory.ReadCycleHl())); return(3); }
public override void Visit(BitOp node) { ulong left = thread.Pop().Read().GetAsInt().Value; ulong right = 0; if (node.Operator != BitOp.Op.Not) { right = thread.Pop().Read().GetAsInt().Value; } switch (node.Operator) { case BitOp.Op.And: PushInteger(left & right); break; case BitOp.Op.Or: PushInteger(left | right); break; case BitOp.Op.NAnd: PushInteger(~(left & right)); break; case BitOp.Op.NOr: PushInteger(~(left | right)); break; case BitOp.Op.Not: PushInteger(~left); break; case BitOp.Op.XOr: PushInteger(left ^ right); break; } }
public void GetBitsForThree() { Assert.AreEqual("0011", BitOp.GetBits(3, 4)); }
public void GetBitForNegThreeAtPositionThree() { Assert.AreEqual(true, BitOp.GetBitAt(2, -3)); // ...100, bit 2 is false }
public void SubtractTwoPositives() { Assert.AreEqual(-9, BitOp.Subtract(2, 11)); }
public void GetBitForThreeAtPositionZero() { Assert.AreEqual(true, BitOp.GetBitAt(0, 3)); // 011, bit 0 is true }
public void GetBitsForFifteen() { Assert.AreEqual("01111", BitOp.GetBits(15, 5)); }
public void GetBitsForNegEleven() { Assert.AreEqual("10100", BitOp.GetBits(-11, 5)); }
public void MultiplyNegativeAndAPositive() { Assert.AreEqual(-7, BitOp.Multiply(7, -1)); }
public void DividePositives() { Assert.AreEqual(4, BitOp.Divide(8, 2)); }
public void MultiplyNegatives() { Assert.AreEqual(15, BitOp.Multiply(-5, -3)); }
public void GetBitForThreeAtPositionOne() { Assert.AreEqual(true, BitOp.GetBitAt(1, 3)); // 011, bit 1 is true }
public void MultiplyPositives() { Assert.AreEqual(32, BitOp.Multiply(4, 8)); }
public void SubtractPositiveLeftNegativeRight() { Assert.AreEqual(8, BitOp.Subtract(7, -1)); }
public void SubtractNegLeftPositiveRight() { Assert.AreEqual(-13, BitOp.Subtract(-5, 8)); }
public void GetBitsForBigNumber() { Assert.AreEqual("00001010000010110000110000001101", BitOp.GetBits(168496141, 32)); }
public void DivideNegatives() { Assert.AreEqual(5, BitOp.Divide(-15, -3)); }
public void GetBitsForEleven() { Assert.AreEqual("01011", BitOp.GetBits(11, 5)); }
public void DivideNegativeAndAPositive() { Assert.AreEqual(-7, BitOp.Divide(7, -1)); }
public void GetBitsForNegFive() { Assert.AreEqual("11010", BitOp.GetBits(-5, 5)); }
public void DivideHasRemainder() { Assert.AreEqual(3, BitOp.Divide(15, 4)); }
public void AddTwoPositivies() { Assert.AreEqual(14, BitOp.Add(2, 12)); }
public static object BitOperation(object x, object y, BitOp op) { Debug.Assert(!(x is PhpReference) && !(y is PhpReference)); PhpBytes bx, by; if ((bx = PhpVariable.AsBytes(x)) == null || (by = PhpVariable.AsBytes(y)) == null) { // at least one of the operands is not string of characters nor string of bytes: long lx = Convert.ObjectToLongInteger(x); long ly = Convert.ObjectToLongInteger(y); long result; switch (op) { case BitOp.And: result = lx & ly; break; case BitOp.Or: result = lx | ly; break; case BitOp.Xor: result = lx ^ ly; break; default: throw new ArgumentOutOfRangeException("op"); } // int to long overflow check int il = unchecked((int)result); if (il == result) return il; // we need long return result; } else { byte[] result; int length = (op == BitOp.Or) ? Math.Max(bx.Length, by.Length) : Math.Min(bx.Length, by.Length); // chooses the resulting array allocating a new one only if necessary; // if x or y has been converted from string to bytes and has the max. length it can be used for // storing a resulting array: if (!ReferenceEquals(bx, x) && bx.Length == length) result = bx.Data;// bx is temporary PhpBytes instance, its internal data can be reused else if (!ReferenceEquals(by, y) && by.Data.Length == length) result = by.Data;// by is temporary PhpBytes instance, its internal data can be reused else result = new byte[length]; return new PhpBytes(BitOperation(result, bx.ReadonlyData, by.ReadonlyData, op)); } }
public void AddLeftNegRightPos() { Assert.AreEqual(9, BitOp.Add(-3, 12)); }
public void AddRightPosLeftNeg() { Assert.AreEqual(-4, BitOp.Add(4, -8)); }
public void GetBitForThreeAtPositionThree() { Assert.AreEqual(false, BitOp.GetBitAt(3, 3)); // 011, bit 3 is false }
public void AddTwoNegatives() { Assert.AreEqual(-16, BitOp.Add(-9, -7)); }
/// <summary> /// Performs specified binary operation on arrays of bytes. /// </summary> /// <param name="result">An array where to store the result. Data previously stored here will be overwritten.</param> /// <param name="x">The first operand.</param> /// <param name="y">The second operand</param> /// <param name="op">The operation to perform.</param> /// <returns>The reference to the the <paramref name="result"/> array.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="op"/> has invalid value.</exception> private static byte[] BitOperation(byte[]/*!*/ result, byte[]/*!*/ x, byte[]/*!*/ y, BitOp op) { int min_length = Math.Min(x.Length, y.Length); Debug.Assert(result != null && x != null && y != null && result.Length >= min_length); switch (op) { case BitOp.And: for (int i = 0; i < min_length; i++) result[i] = unchecked((byte)(x[i] & y[i])); // remaining bytes are ignored // break; case BitOp.Or: for (int i = 0; i < min_length; i++) result[i] = unchecked((byte)(x[i] | y[i])); // copies remaining bytes from longer array: if (x.Length > min_length) { if (x != result) Buffer.BlockCopy(x, min_length, result, min_length, result.Length - min_length); } else { if (y != result) Buffer.BlockCopy(y, min_length, result, min_length, result.Length - min_length); } break; case BitOp.Xor: for (int i = 0; i < min_length; i++) result[i] = unchecked((byte)(x[i] ^ y[i])); // remaining bytes are ignored // break; default: throw new ArgumentOutOfRangeException("op"); } return result; }
public void GetBitForNegThreeAtPositionOne() { Assert.AreEqual(false, BitOp.GetBitAt(1, -3)); // ...100, bit 1 is false }