Browse Source

add IsEven() function for TBigInteger

Ugochukwu Mmaduekwe 6 years ago
parent
commit
84724237d7
2 changed files with 45 additions and 0 deletions
  1. 39 0
      CryptoLib.Tests/src/Math/BigIntegerTests.pas
  2. 6 0
      CryptoLib/src/Math/ClpBigInteger.pas

+ 39 - 0
CryptoLib.Tests/src/Math/BigIntegerTests.pas

@@ -58,6 +58,7 @@ type
     FRandom: ISecureRandom;
 
     function val(n: Int64): TBigInteger;
+    function IsEvenUsingMod(const n: TBigInteger): Boolean;
     function mersenne(e: Int32): TBigInteger;
     procedure CheckEqualsBigInteger(const a, b: TBigInteger;
       const msg: String = '');
@@ -102,6 +103,7 @@ type
     procedure TestSignValue();
     procedure TestSubtract();
     procedure TestTestBit();
+    procedure TestIsEven();
     procedure TestToByteArray();
     procedure TestToByteArrayUnsigned();
     procedure TestToString();
@@ -124,6 +126,11 @@ begin
   CheckEquals(True, a.Equals(b), msg);
 end;
 
+function TTestBigInteger.IsEvenUsingMod(const n: TBigInteger): Boolean;
+begin
+  result := n.&Mod(TBigInteger.Two).Equals(TBigInteger.Zero);
+end;
+
 function TTestBigInteger.mersenne(e: Int32): TBigInteger;
 begin
   result := Ftwo.Pow(e).Subtract(Fone);
@@ -677,6 +684,38 @@ begin
   // TODO Tests for large numbers
 end;
 
+procedure TTestBigInteger.TestIsEven;
+var
+  RandomBigInteger: TBigInteger;
+  idx: Int32;
+begin
+  CheckTrue(TBigInteger.ValueOf(2).IsEven);
+  CheckTrue(TBigInteger.ValueOf(4).IsEven);
+  CheckTrue(TBigInteger.ValueOf(6).IsEven);
+  CheckTrue(TBigInteger.ValueOf(8).IsEven);
+  CheckTrue(TBigInteger.ValueOf(10).IsEven);
+  CheckTrue(TBigInteger.ValueOf(12).IsEven);
+
+  CheckFalse(TBigInteger.ValueOf(1).IsEven);
+  CheckFalse(TBigInteger.ValueOf(3).IsEven);
+  CheckFalse(TBigInteger.ValueOf(5).IsEven);
+  CheckFalse(TBigInteger.ValueOf(7).IsEven);
+  CheckFalse(TBigInteger.ValueOf(9).IsEven);
+  CheckFalse(TBigInteger.ValueOf(11).IsEven);
+
+  idx := 0;
+
+  while idx <= 1000 do
+  begin
+    RandomBigInteger := TBigInteger.Create(RandomRange(1, 256), FRandom);
+    CheckEquals(RandomBigInteger.IsEven(), IsEvenUsingMod(RandomBigInteger),
+      Format('IsEven Comparison failed with "%s"',
+      [RandomBigInteger.ToString]));
+
+    System.Inc(idx);
+  end;
+end;
+
 procedure TTestBigInteger.TestIsProbablePrime;
 var
   p, c, e: Int32;

+ 6 - 0
CryptoLib/src/Math/ClpBigInteger.pas

@@ -424,6 +424,7 @@ type
     function SetBit(n: Int32): TBigInteger;
     function ClearBit(n: Int32): TBigInteger;
     function FlipBit(n: Int32): TBigInteger;
+    function IsEven(): Boolean; inline;
 
     function GetLowestSetBit(): Int32;
 
@@ -1960,6 +1961,11 @@ begin
   Result := &Xor(One.ShiftLeft(n));
 end;
 
+function TBigInteger.IsEven(): Boolean;
+begin
+  Result := not(TestBit(0));
+end;
+
 function TBigInteger.Gcd(const value: TBigInteger): TBigInteger;
 var
   r, u, v: TBigInteger;