aboutsummaryrefslogtreecommitdiff
path: root/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs')
-rw-r--r--runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs425
1 files changed, 425 insertions, 0 deletions
diff --git a/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs b/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
new file mode 100644
index 0000000..68c61bc
--- /dev/null
+++ b/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
@@ -0,0 +1,425 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+
+using System;
+
+using Contracts = System.Diagnostics.Debug;
+using Contract = System.Diagnostics.Debug;
+//using System.Runtime.InteropServices;
+
+// ReSharper disable once CheckNamespace
+namespace Numerics
+{
+
+/*
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct DoubleUlong
+ {
+ [FieldOffset(0)]
+ internal double dbl;
+ [FieldOffset(0)]
+ internal ulong uu;
+ }
+*/
+
+
+ internal static class NumericsHelpers
+ {
+ private const int KcbitUint = 32;
+
+ /*internal static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite)
+ {
+ //Contract.Ensures(Contract.ValueAtReturn(out sign) == +1 || Contract.ValueAtReturn(out sign) == -1);
+
+ DoubleUlong du;
+ du.uu = 0;
+ du.dbl = dbl;
+
+ sign = 1 - ((int)(du.uu >> 62) & 2);
+ man = du.uu & 0x000FFFFFFFFFFFFF;
+ exp = (int)(du.uu >> 52) & 0x7FF;
+ if (exp == 0)
+ {
+ // Denormalized number.
+ fFinite = true;
+ if (man != 0)
+ exp = -1074;
+ }
+ else if (exp == 0x7FF)
+ {
+ // NaN or Inifite.
+ fFinite = false;
+ exp = int.MaxValue;
+ }
+ else
+ {
+ fFinite = true;
+ man |= 0x0010000000000000;
+ exp -= 1075;
+ }
+ }
+
+ internal static double GetDoubleFromParts(int sign, int exp, ulong man)
+ {
+ DoubleUlong du;
+ du.dbl = 0;
+
+ if (man == 0)
+ du.uu = 0;
+ else
+ {
+ // Normalize so that 0x0010 0000 0000 0000 is the highest bit set.
+ int cbitShift = CbitHighZero(man) - 11;
+ if (cbitShift < 0)
+ man >>= -cbitShift;
+ else
+ man <<= cbitShift;
+ exp -= cbitShift;
+ Contract.Assert((man & 0xFFF0000000000000) == 0x0010000000000000);
+
+ // Move the point to just behind the leading 1: 0x001.0 0000 0000 0000
+ // (52 bits) and skew the exponent (by 0x3FF == 1023).
+ exp += 1075;
+
+ if (exp >= 0x7FF)
+ {
+ // Infinity.
+ du.uu = 0x7FF0000000000000;
+ }
+ else if (exp <= 0)
+ {
+ // Denormalized.
+ exp--;
+ if (exp < -52)
+ {
+ // Underflow to zero.
+ du.uu = 0;
+ }
+ else
+ {
+ du.uu = man >> -exp;
+ Contract.Assert(du.uu != 0);
+ }
+ }
+ else
+ {
+ // Mask off the implicit high bit.
+ du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52);
+ }
+ }
+
+ if (sign < 0)
+ du.uu |= 0x8000000000000000;
+
+ return du.dbl;
+ }
+ */
+
+
+ // Do an in-place twos complement of d and also return the result.
+ // "Dangerous" because it causes a mutation and needs to be used
+ // with care for immutable types
+ internal static void DangerousMakeTwosComplement(uint[] d)
+ {
+ // first do complement and +1 as long as carry is needed
+ int i = 0;
+ uint v = 0;
+ for (; i < d.Length; i++)
+ {
+ v = ~d[i] + 1;
+ d[i] = v;
+ if (v != 0) { i++; break; }
+ }
+ if (v != 0)
+ {
+ // now ones complement is sufficient
+ for (; i < d.Length; i++)
+ {
+ d[i] = ~d[i];
+ }
+ }
+ else
+ {
+ //??? this is weird
+ d = resize(d, d.Length + 1);
+ d[d.Length - 1] = 1;
+ }
+ }
+
+ // ReSharper disable once InconsistentNaming
+ private static uint[] resize(uint[] v, int len)
+ {
+ if (v.Length == len) return v;
+ uint[] ret = new uint[len];
+ int n = Math.Min(v.Length, len);
+ for (int i = 0; i < n; i++)
+ {
+ ret[i] = v[i];
+ }
+ return ret;
+ }
+
+ internal static void Swap<T>(ref T a, ref T b)
+ {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ // ReSharper disable once InconsistentNaming
+/*
+ internal static uint GCD(uint u1, uint u2)
+ {
+ const int cvMax = 32;
+ if (u1 < u2)
+ goto LOther;
+ LTop:
+ Contract.Assert(u2 <= u1);
+ if (u2 == 0)
+ return u1;
+ for (int cv = cvMax; ; )
+ {
+ u1 -= u2;
+ if (u1 < u2)
+ break;
+ if (--cv == 0)
+ {
+ u1 %= u2;
+ break;
+ }
+ }
+ LOther:
+ Contract.Assert(u1 < u2);
+ if (u1 == 0)
+ return u2;
+ for (int cv = cvMax; ; )
+ {
+ u2 -= u1;
+ if (u2 < u1)
+ break;
+ if (--cv == 0)
+ {
+ u2 %= u1;
+ break;
+ }
+ }
+ goto LTop;
+ }
+*/
+
+ // ReSharper disable once InconsistentNaming
+/*
+ internal static ulong GCD(ulong uu1, ulong uu2)
+ {
+ const int cvMax = 32;
+ if (uu1 < uu2)
+ goto LOther;
+ LTop:
+ Contract.Assert(uu2 <= uu1);
+ if (uu1 <= uint.MaxValue)
+ goto LSmall;
+ if (uu2 == 0)
+ return uu1;
+ for (int cv = cvMax; ; )
+ {
+ uu1 -= uu2;
+ if (uu1 < uu2)
+ break;
+ if (--cv == 0)
+ {
+ uu1 %= uu2;
+ break;
+ }
+ }
+ LOther:
+ Contract.Assert(uu1 < uu2);
+ if (uu2 <= uint.MaxValue)
+ goto LSmall;
+ if (uu1 == 0)
+ return uu2;
+ for (int cv = cvMax; ; )
+ {
+ uu2 -= uu1;
+ if (uu2 < uu1)
+ break;
+ if (--cv == 0)
+ {
+ uu2 %= uu1;
+ break;
+ }
+ }
+ goto LTop;
+
+ LSmall:
+ uint u1 = (uint)uu1;
+ uint u2 = (uint)uu2;
+ if (u1 < u2)
+ goto LOtherSmall;
+ LTopSmall:
+ Contract.Assert(u2 <= u1);
+ if (u2 == 0)
+ return u1;
+ for (int cv = cvMax; ; )
+ {
+ u1 -= u2;
+ if (u1 < u2)
+ break;
+ if (--cv == 0)
+ {
+ u1 %= u2;
+ break;
+ }
+ }
+ LOtherSmall:
+ Contract.Assert(u1 < u2);
+ if (u1 == 0)
+ return u2;
+ for (int cv = cvMax; ; )
+ {
+ u2 -= u1;
+ if (u2 < u1)
+ break;
+ if (--cv == 0)
+ {
+ u2 %= u1;
+ break;
+ }
+ }
+ goto LTopSmall;
+ }
+*/
+
+ internal static ulong MakeUlong(uint uHi, uint uLo)
+ {
+ return ((ulong)uHi << KcbitUint) | uLo;
+ }
+
+ internal static uint GetLo(ulong uu)
+ {
+ return (uint)uu;
+ }
+
+ internal static uint GetHi(ulong uu)
+ {
+ return (uint)(uu >> KcbitUint);
+ }
+
+/*
+ internal static uint Abs(int a)
+ {
+ uint mask = (uint)(a >> 31);
+ return ((uint)a ^ mask) - mask;
+ }
+*/
+
+ // internal static ulong Abs(long a) {
+ // ulong mask = (ulong)(a >> 63);
+ // return ((ulong)a ^ mask) - mask;
+ // }
+
+ private static uint CombineHash(uint u1, uint u2)
+ {
+ return ((u1 << 7) | (u1 >> 25)) ^ u2;
+ }
+
+ internal static int CombineHash(int n1, int n2)
+ {
+ return (int)CombineHash((uint)n1, (uint)n2);
+ }
+ internal static int CbitHighZero(uint u)
+ {
+ if (u == 0)
+ return 32;
+
+ int cbit = 0;
+ if ((u & 0xFFFF0000) == 0)
+ {
+ cbit += 16;
+ u <<= 16;
+ }
+ if ((u & 0xFF000000) == 0)
+ {
+ cbit += 8;
+ u <<= 8;
+ }
+ if ((u & 0xF0000000) == 0)
+ {
+ cbit += 4;
+ u <<= 4;
+ }
+ if ((u & 0xC0000000) == 0)
+ {
+ cbit += 2;
+ u <<= 2;
+ }
+ if ((u & 0x80000000) == 0)
+ cbit += 1;
+ return cbit;
+ }
+
+ /*internal static int CbitLowZero(uint u)
+ {
+ if (u == 0)
+ return 32;
+
+ int cbit = 0;
+ if ((u & 0x0000FFFF) == 0)
+ {
+ cbit += 16;
+ u >>= 16;
+ }
+ if ((u & 0x000000FF) == 0)
+ {
+ cbit += 8;
+ u >>= 8;
+ }
+ if ((u & 0x0000000F) == 0)
+ {
+ cbit += 4;
+ u >>= 4;
+ }
+ if ((u & 0x00000003) == 0)
+ {
+ cbit += 2;
+ u >>= 2;
+ }
+ if ((u & 0x00000001) == 0)
+ cbit += 1;
+ return cbit;
+ }
+
+ internal static int CbitHighZero(ulong uu)
+ {
+ if ((uu & 0xFFFFFFFF00000000) == 0)
+ return 32 + CbitHighZero((uint)uu);
+ return CbitHighZero((uint)(uu >> 32));
+ }*/
+
+ // internal static int CbitLowZero(ulong uu) {
+ // if ((uint)uu == 0)
+ // return 32 + CbitLowZero((uint)(uu >> 32));
+ // return CbitLowZero((uint)uu);
+ // }
+ //
+ // internal static int Cbit(uint u) {
+ // u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
+ // u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
+ // u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
+ // u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
+ // return (int)((ushort)u + (ushort)(u >> 16));
+ // }
+ //
+ // static int Cbit(ulong uu) {
+ // uu = (uu & 0x5555555555555555) + ((uu >> 1) & 0x5555555555555555);
+ // uu = (uu & 0x3333333333333333) + ((uu >> 2) & 0x3333333333333333);
+ // uu = (uu & 0x0F0F0F0F0F0F0F0F) + ((uu >> 4) & 0x0F0F0F0F0F0F0F0F);
+ // uu = (uu & 0x00FF00FF00FF00FF) + ((uu >> 8) & 0x00FF00FF00FF00FF);
+ // uu = (uu & 0x0000FFFF0000FFFF) + ((uu >> 16) & 0x0000FFFF0000FFFF);
+ // return (int)((uint)uu + (uint)(uu >> 32));
+ // }
+ }
+}
+