private UInt128 EvaluateInternal(UInt128 n, UInt128 x0, UInt128 xmax) { this.n = n; x0 = T1(x0 + 1); xmax = T1(xmax); if (x0 > xmax) { return(0); } var ymin = YFloor(xmax); var xmin = UInt128.Max(x0, UInt128.Min(T1(C1 * UInt128.CeilingCbrt(2 * n)), xmax)); #if DIAG Console.WriteLine("n = {0}, xmin = {1}, xmax = {2}", n, xmin, xmax); #endif var s = (UInt128)0; var a2 = (ulong)1; var x2 = xmax; var y2 = ymin; var c2 = a2 * x2 + y2; while (true) { var a1 = a2 + 1; var x4 = YTan(a1); var y4 = YFloor(x4); var c4 = a1 * x4 + y4; var x5 = x4 + 1; var y5 = YFloor(x5); var c5 = a1 * x5 + y5; if (x4 <= xmin) { break; } s += Triangle(c4 - c2 - x0) - Triangle(c4 - c2 - x5) + Triangle(c5 - c2 - x5); if (threads == 0) { s += ProcessRegion(0, (ulong)(a1 * x2 + y2 - c5), (ulong)(a2 * x5 + y5 - c2), a1, 1, c5, a2, 1, c2); while (stack.Count > 0) { var r = stack.Pop(); s += ProcessRegion(0, r.w, r.h, r.a1, r.b1, r.c1, r.a2, r.b2, r.c2); } } else { Enqueue(new Region((ulong)(a1 * x2 + y2 - c5), (ulong)(a2 * x5 + y5 - c2), a1, 1, c5, a2, 1, c2)); } a2 = a1; x2 = x4; y2 = y4; c2 = c4; } s += (xmax - x0 + 1) * ymin + Triangle(xmax - x0); var rest = x2 - x0; s -= y2 * rest + a2 * Triangle(rest); xmanual = x2; return(s); }
private void SetValue(Node <T> node, UInt128 start, UInt128 length, UInt128 ip_from, UInt128 ip_to, T value) { if (ip_from > ip_to) { throw new ArgumentException("Invalid range", nameof(ip_from)); } if (node != null) { UInt128 l_start = start; UInt128 l_end = l_start + length - 1; if (l_start <= ip_from && l_end >= ip_from) { if (l_start == ip_from && l_end <= ip_to) { node.LValue = value; node.LPtr = null; } else { if (node.LValue != null) { node.LPtr = new Node <T> { LValue = node.LValue, LPtr = null, RValue = node.LValue, RPtr = null }; node.LValue = default; } SetValue(node.LPtr, l_start, length >> 1, ip_from, UInt128.Min(l_end, ip_to), value); } } UInt128 r_start = start + length; UInt128 r_end = r_start + length - 1; if (r_start <= ip_to && r_end >= ip_to) { if (r_start >= ip_from && r_end == ip_to) { node.RValue = value; node.RPtr = null; } else { if (node.RValue != null) { node.RPtr = new Node <T> { LValue = node.RValue, LPtr = null, RValue = node.RValue, RPtr = null }; node.RValue = default; } SetValue(node.RPtr, r_start, length >> 1, UInt128.Max(r_start, ip_from), ip_to, value); } } } else { throw new IPFilterException("Can't find node. IPFilter seems to be corrupted"); } }
public UInt128 ProcessRegion(int thread, ulong w, ulong h, ulong a1, ulong b1, UInt128 c1, ulong a2, ulong b2, UInt128 c2) { #if DIAG Console.WriteLine("ProcessRegion: w = {0}, h = {1}, a1/b1 = {2}/{3}, a2/b2 = {4}/{5}, c1 = {6}, c2 = {7}", w, h, a1, b1, a2, b2, c1, c2); #endif #if RECORD_SIZES amax = UInt128.Max(UInt128.Max(amax, a1), a2); bmax = UInt128.Max(UInt128.Max(bmax, b1), b2); cmax = UInt128.Max(UInt128.Max(bmax, c1), c2); #endif var s = (UInt128)0; while (true) { if (h > 0 && H(w, 1, a1, b1, c1, a2, b2, c2) <= n) { s += w; ++c2; --h; } Debug.Assert(h == 0 || H(w, 0, a1, b1, c1, a2, b2, c2) <= n && H(w, 1, a1, b1, c1, a2, b2, c2) > n); if (w > 0 && H(1, h, a1, b1, c1, a2, b2, c2) <= n) { s += h; ++c1; --w; } Debug.Assert(w == 0 || H(0, h, a1, b1, c1, a2, b2, c2) <= n && H(1, h, a1, b1, c1, a2, b2, c2) > n); var a3 = a1 + a2; var b3 = b1 + b2; var ab1 = a1 + b1; var a3b3 = a3 * b3; var abba = a1 * b2 + b1 * a2; var ab2 = 2 * a1 * b1; var u4 = UTan(ab1, abba, ab2, a3b3, c1); if (u4 <= 0 || u4 > long.MaxValue) { return(Processed(s + ProcessRegionManual(thread, w, h, a1, b1, c1, a2, b2, c2))); } var u5 = u4 + 1; ulong v4, v5; VFloor2(u4, a1, b1, c1, c2, abba, ab2, out v4, out v5); Debug.Assert(v4 == VFloor(u4, a1, b1, c1, a2, b2, c2)); Debug.Assert(v5 == VFloor(u5, a1, b1, c1, a2, b2, c2)); Debug.Assert(H(u4, v4, a1, b1, c1, a2, b2, c2) <= n && H(u4, v4 + 1, a1, b1, c1, a2, b2, c2) > n); Debug.Assert(H(u5, v5, a1, b1, c1, a2, b2, c2) <= n && H(u5, v5 + 1, a1, b1, c1, a2, b2, c2) > n); var v6 = u4 + v4; var u7 = u5 + v5; if (u4 <= C2 || v5 <= C2 || v6 >= h || u7 >= w) { return(Processed(s + ProcessRegionManual(thread, w, h, a1, b1, c1, a2, b2, c2))); } if (v6 != u7) { s += Triangle(v6 - 1) - Triangle(v6 - u5) + Triangle(u7 - u5); } else { s += Triangle(v6 - 1); } #if DIAG Console.WriteLine("ProcessRegion: s = {0}", s); #endif Enqueue(new Region(u4, h - v6, a1, b1, c1, a3, b3, c1 + c2 + v6)); w -= u7; h = v5; a1 = a3; b1 = b3; c1 += c2 + u7; } }
// [DataRow(uint.MaxValue, uint.MaxValue)] // [DataRow(ulong.MaxValue, ulong.MaxValue)] public void UInt128Test(ulong factorMax, ulong modulusMax) { var random = new MersenneTwister(0).Create <ulong>(); for (int i = 0; i < 10000; i++) { var n = random.Next(modulusMax - 1) + 1; var a = random.Next(factorMax) % n; var b = random.Next(factorMax) % n; var c = random.Next(factorMax) % n; var d = random.Next(factorMax) % n; var s = (int)(b % 32); var value = (UInt128)0; Assert.AreEqual((BigInteger)a << s, (UInt128)a << s); Assert.AreEqual((BigInteger)a >> s, (UInt128)a >> s); Assert.AreEqual((BigInteger)a & b, (UInt128)a & b); Assert.AreEqual((BigInteger)a & b, a & (UInt128)b); Assert.AreEqual((BigInteger)a & b, (UInt128)a & (UInt128)b); Assert.AreEqual((BigInteger)a | b, (UInt128)a | b); Assert.AreEqual((BigInteger)a | b, a | (UInt128)b); Assert.AreEqual((BigInteger)a | b, (UInt128)a | (UInt128)b); Assert.AreEqual((BigInteger)a ^ b, (UInt128)a ^ b); Assert.AreEqual((BigInteger)a ^ b, a ^ (UInt128)b); Assert.AreEqual((BigInteger)a ^ b, (UInt128)a ^ (UInt128)b); if (a <= long.MaxValue) { Assert.AreEqual(~(BigInteger)a, (long)~(UInt128)a); } Assert.AreEqual((BigInteger)a + b, (UInt128)a + b); Assert.AreEqual((BigInteger)a + b, a + (UInt128)b); Assert.AreEqual((BigInteger)a + b, (UInt128)a + (UInt128)b); Assert.AreEqual(((BigInteger)a * n + (BigInteger)b * n) % ((BigInteger)1 << 128), (UInt128)a * n + (UInt128)b * n); if (a >= b) { Assert.AreEqual((BigInteger)a - b, (UInt128)a - b); Assert.AreEqual((BigInteger)a - b, a - (UInt128)b); Assert.AreEqual((BigInteger)a - b, (UInt128)a - (UInt128)b); Assert.AreEqual((BigInteger)a * n - (BigInteger)b * n, (UInt128)a * n - (UInt128)b * n); } Assert.AreEqual(+(BigInteger)a, +(Int128)a); value = a; Assert.AreEqual((BigInteger)a + 1, ++value); value = a; Assert.AreEqual((BigInteger)a, value++); value = (UInt128)a * b; Assert.AreEqual((BigInteger)a * b + 1, ++value); value = (UInt128)a * b; Assert.AreEqual((BigInteger)a * b, value++); if (a > 0) { value = a; Assert.AreEqual((BigInteger)a - 1, --value); value = a; Assert.AreEqual((BigInteger)a, value--); } if (a > 0 && b > 0) { value = (UInt128)a * b; Assert.AreEqual((BigInteger)a * b - 1, --value); value = (UInt128)a * b; Assert.AreEqual((BigInteger)a * b, value--); } if (n <= uint.MaxValue) { Assert.AreEqual((BigInteger)a * n, (UInt128)a * (uint)n); Assert.AreEqual((BigInteger)b * n, (UInt128)b * (uint)n); Assert.AreEqual((BigInteger)a * b * n % ((BigInteger)1 << 128), (UInt128)a * b * (uint)n); Assert.AreEqual((BigInteger)n * a, (uint)n * (UInt128)a); Assert.AreEqual((BigInteger)n * b, (uint)n * (UInt128)b); Assert.AreEqual((BigInteger)n * a * b % ((BigInteger)1 << 128), (uint)n * ((UInt128)a * (UInt128)b)); } Assert.AreEqual((BigInteger)a * b, a * (UInt128)b); Assert.AreEqual((BigInteger)a * b, (UInt128)a * b); Assert.AreEqual((BigInteger)a * b, a * (UInt128)b); Assert.AreEqual((BigInteger)a * b, (UInt128)a * (UInt128)b); if (b > 0) { Assert.AreEqual((BigInteger)a % b, (UInt128)a % b); Assert.AreEqual((BigInteger)a % b, a % (UInt128)b); Assert.AreEqual((BigInteger)a % b, (UInt128)a % (UInt128)b); } Assert.AreEqual((BigInteger)a * b % n, (UInt128)a * b % n); Assert.AreEqual((BigInteger)a * b % n, a * (UInt128)b % n); Assert.AreEqual((BigInteger)a * b % n, (UInt128)a * (UInt128)b % (UInt128)n); if (c > 0 && d > 0) { Assert.AreEqual((BigInteger)a * b / ((BigInteger)c * d), (UInt128)a * (UInt128)b / ((UInt128)c * (UInt128)d)); Assert.AreEqual((BigInteger)a * b % ((BigInteger)c * d), (UInt128)a * (UInt128)b % ((UInt128)c * (UInt128)d)); } if (b > 0) { Assert.AreEqual((BigInteger)a / b, (UInt128)a / b); Assert.AreEqual((BigInteger)a / b, a / (UInt128)b); Assert.AreEqual((BigInteger)a / b, (UInt128)a / (UInt128)b); } Assert.AreEqual((BigInteger)a * b / n, (UInt128)a * b / n); Assert.AreEqual((BigInteger)a * b / n, a * (UInt128)b / n); Assert.AreEqual((BigInteger)a * b / n, (UInt128)a * (UInt128)b / (UInt128)n); Assert.AreEqual((BigInteger)a < b, (UInt128)a < b); Assert.AreEqual((BigInteger)a < b, a < (UInt128)b); Assert.AreEqual((BigInteger)a < b, (UInt128)a < (UInt128)b); Assert.AreEqual((BigInteger)a <= b, (UInt128)a <= b); Assert.AreEqual((BigInteger)a <= b, a <= (UInt128)b); Assert.AreEqual((BigInteger)a <= b, (UInt128)a <= (UInt128)b); Assert.AreEqual((BigInteger)a > b, (UInt128)a > b); Assert.AreEqual((BigInteger)a > b, a > (UInt128)b); Assert.AreEqual((BigInteger)a > b, (UInt128)a > (UInt128)b); Assert.AreEqual((BigInteger)a >= b, (UInt128)a >= b); Assert.AreEqual((BigInteger)a >= b, a >= (UInt128)b); Assert.AreEqual((BigInteger)a >= b, (UInt128)a >= (UInt128)b); Assert.AreEqual((BigInteger)a == b, (UInt128)a == b); Assert.AreEqual((BigInteger)a == b, a == (UInt128)b); Assert.AreEqual((BigInteger)a == b, (UInt128)a == (UInt128)b); Assert.AreEqual((BigInteger)a != b, (UInt128)a != b); Assert.AreEqual((BigInteger)a != b, a != (UInt128)b); Assert.AreEqual((BigInteger)a != b, (UInt128)a != (UInt128)b); Assert.AreEqual((BigInteger)a * a, UInt128.Square(a)); Assert.AreEqual(BigInteger.Abs(a), UInt128.Abs(a)); Assert.AreEqual(BigInteger.Abs((BigInteger)a * b), UInt128.Abs((UInt128)a * b)); Assert.AreEqual(BigInteger.Min(a, b), UInt128.Min(a, b)); Assert.AreEqual(BigInteger.Min((BigInteger)a * n, (BigInteger)b * n), UInt128.Min((UInt128)a * n, (UInt128)b * n)); Assert.AreEqual(BigInteger.Max(a, b), UInt128.Max(a, b)); Assert.AreEqual(BigInteger.Max((BigInteger)a * n, (BigInteger)b * n), UInt128.Max((UInt128)a * n, (UInt128)b * n)); for (var j = 0; j < 2; j++) { var m = UInt128.Abs(j == 0 ? (UInt128)a * (UInt128)b : (UInt128)n * (UInt128)n); var floorsqrt = UInt128.FloorSqrt(m); Assert.IsTrue((BigInteger)floorsqrt * floorsqrt <= m && (BigInteger)(floorsqrt + 1) * (floorsqrt + 1) > m); var ceilingsqrt = UInt128.CeilingSqrt(m); Assert.IsTrue((BigInteger)(ceilingsqrt - 1) * (ceilingsqrt - 1) < m && (BigInteger)ceilingsqrt * ceilingsqrt >= m); } for (var j = 0; j < 2; j++) { var m = j == 0 ? (UInt128)a * (UInt128)b : (UInt128)BigInteger.Pow((BigInteger)Math.Floor(Math.Pow((double)((BigInteger)a * b), (double)1 / 3)), 3); var floorcbrt = UInt128.FloorCbrt(m); Assert.IsTrue((BigInteger)floorcbrt * floorcbrt * floorcbrt <= m && (BigInteger)(floorcbrt + 1) * (floorcbrt + 1) * (floorcbrt + 1) > m); var ceilingcbrt = UInt128.CeilingCbrt(m); Assert.IsTrue((BigInteger)(ceilingcbrt - 1) * (ceilingcbrt - 1) * (ceilingcbrt - 1) < m && (BigInteger)ceilingcbrt * ceilingcbrt * ceilingcbrt >= m); } Assert.AreEqual(BigInteger.GreatestCommonDivisor((BigInteger)a, (BigInteger)b), UInt128.GreatestCommonDivisor((UInt128)a, (UInt128)b)); Assert.AreEqual(BigInteger.GreatestCommonDivisor((BigInteger)a * b, (BigInteger)c * d), UInt128.GreatestCommonDivisor((UInt128)a * b, (UInt128)c * d)); Assert.AreEqual(0, 0); } }
public static UInt128 Max(UInt128 a, UInt128 b) { return(UInt128.Max(a, b)); }