public void FillData_Test()
        {
            // Arrange

            var returnValue1 = new LargeInteger(7);
            var returnValue2 = new LargeInteger(14);

            PropertyInfo propertyInfo1 = typeof(ClassWithStringAutoPrimaryKey).GetProperty("Key");
            PropertyInfo propertyInfo2 = typeof(ClassWithIntAutoPrimaryKey).GetProperty("Key");

            var data1 = new Data<LargeInteger>(null);
            var data2 = new Data<LargeInteger>(null);
            var dictionary = new Dictionary<PropertyInfo, Data<LargeInteger>>
            {
                {propertyInfo1, data1},
                {propertyInfo2, data2},
            };

            WriterDelegate writer1 = writerPi => (decoderPi, input) => returnValue1;
            WriterDelegate writer2 = writerPi => (decoderPi, input) => returnValue2;

            this.writersMock.Setup(m => m[typeof(string)]).Returns(writer1);
            this.writersMock.Setup(m => m[typeof(int)]).Returns(writer2);

            this.writersMock.Setup(m => m.Execute()).Returns(new object[2]);

            // Act

            this.generator.FillData(dictionary);

            // Assert

            Assert.AreEqual(returnValue1 + 1, data1.Item);
            Assert.AreEqual(returnValue2 + 1, data2.Item);
        }
        public void Cast_ToULong_Test()
        {
            var largeInteger = new LargeInteger(LargeIntegerTests.MaxValue);

            var result = (ulong)largeInteger;

            Assert.AreEqual(LargeIntegerTests.MaxValue, result);
        }
        public void Addition_Test()
        {
            var left = new LargeInteger(LargeIntegerTests.MaxValue);
            var right = new LargeInteger(257);

            LargeInteger result = left + right;

            Assert.AreEqual(LargeIntegerTests.MaxValue + 257, (ulong)result);
        }
        public void Decrement_Test()
        {
            var largeInteger = new LargeInteger(LargeIntegerTests.MaxValue);

            for (int i = (int)LargeIntegerTests.MaxValue - 1; i >= 0; i--)
            {
                largeInteger--;
                Assert.AreEqual((ulong)i, (ulong)largeInteger);
            }
        }
        public void Decode_Test()
        {
            var expected = new LargeInteger(5204);

            var generator = new LetterEncoder();

            LargeInteger result = generator.Decode("HSE");

            Assert.AreEqual(expected, result);
        }
        public object GetValue(PropertyInfo propertyInfo, LargeInteger initialCount)
        {
            StandardPropertyValueAccumulator.Logger.Debug(
                $"Entering GetValue. propertyInfo: {propertyInfo}, initialCount: {initialCount}");

            this.countDictionary.AddOrUpdate(propertyInfo, pi => initialCount, (pi, value) => ++value);
            object result = this.PrivateGetValue(propertyInfo);

            StandardPropertyValueAccumulator.Logger.Debug("Exiting GetValue");
            return result;
        }
        private static LargeInteger Ensure(ref LargeInteger largeInteger, object o)
        {
            if (largeInteger.data == null)
            {
                largeInteger.data = LargeInteger.GetInitialData();
            }
            else if (!largeInteger.data.Any())
            {
                largeInteger.data.Add(0);
            }

            return largeInteger;
        }
        public virtual LargeInteger Decode(string value)
        {
            LetterEncoder.Logger.Debug($"Entering Encode. value: {value}");

            LargeInteger result = 0;

            for (int i = 0; i < value.Length; i++)
            {
                var ascii = (ulong)value[value.Length - 1 - i];

                result += new LargeInteger(26).Pow((ulong)i) * (ascii - 65);
            }

            LetterEncoder.Logger.Debug($"Exiting Encode. result: {result}");
            return result;
        }
        public virtual string Encode(LargeInteger number, int maxStringLength)
        {
            LetterEncoder.Logger.Debug($"Entering Encode. number: {number}, maxStringLength: {maxStringLength}");

            var sb = new StringBuilder();

            int digitCount = 0;

            LargeInteger whole = number;
            while (digitCount++ < maxStringLength)
            {
                LargeInteger remainder = whole%26;
                whole /= 26;

                if (remainder == 0 && whole == 0)
                {
                    if (digitCount == 1)
                    {
                        sb.Insert(0, "A");
                    }

                    break;
                }

                var ascii = (char)(remainder + 65);
                sb.Insert(0, ascii);
            }

            if (digitCount > maxStringLength)
            {
                throw new OverflowException(string.Format(Messages.StringGeneratorOverflow, number, maxStringLength));
            }

            string result = sb.ToString();

            LetterEncoder.Logger.Debug($"Exiting Encode. result : {result}");
            return result;
        }
        public void Initializer_Test()
        {
            ulong value = LargeIntegerTests.MaxValue;

            var result = new LargeInteger(value);

            result--;

            Assert.AreEqual(value - 1, (ulong)result);
        }
        public void Increment_Test()
        {
            var largeInteger = new LargeInteger();

            for (ulong i = 1; i <= LargeIntegerTests.MaxValue; i++)
            {
                largeInteger++;
                Assert.AreEqual(i, (ulong)largeInteger);
            }
        }
        public void Exponent_Test()
        {
            LargeInteger exponent = new LargeInteger(ulong.MaxValue).Pow(3);
            LargeInteger actual = exponent / new LargeInteger(ulong.MaxValue);
            LargeInteger a = new LargeInteger(ulong.MaxValue)*new LargeInteger(ulong.MaxValue);
            actual /= new LargeInteger(ulong.MaxValue);

            LargeInteger expected = new LargeInteger(ulong.MaxValue);

            Assert.AreEqual(expected, actual);
        }
        public void Division_Test2()
        {
            LargeInteger a = new LargeInteger(ulong.MaxValue);
            LargeInteger b = a * (new LargeInteger(ulong.MaxValue) * 9000);

            LargeInteger c = b / (a * 9000);

            Assert.AreEqual(ulong.MaxValue, (ulong)c);
        }
        private static void Encode(ulong value, LargeInteger largeInteger)
        {
            var lower = (uint)(value & 0xffffffff);
            var upper = (uint) (value >> 32);

            largeInteger.data.Add(lower);

            if (upper > 0)
            {
                largeInteger.data.Add(upper);
            }
        }
        public void ToString_Test()
        {
            LargeInteger largeInteger = new LargeInteger(uint.MaxValue) * uint.MaxValue * uint.MaxValue;

            string result = largeInteger.ToString();
            const string expected = "79228162458924105385300197375";

            Assert.AreEqual(expected, result);
        }
        public void Multiplication_Test()
        {
            LargeInteger a = new LargeInteger(ulong.MaxValue);
            LargeInteger b = a * new LargeInteger(ulong.MaxValue);

            LargeInteger c = b / a;

            Assert.AreEqual(ulong.MaxValue, (ulong)c);
        }
        public void String_Test()
        {
            // Arrange

            PropertyInfo propertyInfo = typeof(ClassWithStringAutoPrimaryKey).GetProperty("Key");
            const string value = "X";
            var expected = new LargeInteger(7);

            const string command = "XXXX";
            this.commandGeneratorMock.Setup(m => m.WriteString(propertyInfo)).Returns(command);

            this.encoderMock.Setup(m => m.Decode(value)).Returns(expected);

            // Act

            WriterDelegate stringWriter = this.writerDictionary[value.GetType()];
            DecoderDelegate stringDecoder = stringWriter(propertyInfo);
            LargeInteger result = stringDecoder(propertyInfo, value);

            // Assert

            Assert.AreEqual(expected, result);
            this.commandGeneratorMock.Verify(m => m.WriteString(propertyInfo), Times.Once);
            this.primitivesMock.Verify(m => m.AddSqlCommand(command));
        }
        private static ulong Decode(LargeInteger largeInteger)
        {
            if (largeInteger.data.Count > 2)
            {
                throw new OverflowException();
            }

            ulong result = LargeInteger.GetULong(largeInteger.data);

            return result;
        }
        public void LessThan_Test()
        {
            var lessThan = new LargeInteger(LargeIntegerTests.MaxValue- LargeIntegerTests.MaxValue/2);
            var greaterThan = new LargeInteger(LargeIntegerTests.MaxValue);

            Assert.IsTrue(lessThan < greaterThan);
        }
 private LargeInteger Ensure(ref LargeInteger largeInteger)
 {
     this.Ensure();
     return LargeInteger.Ensure(ref largeInteger, null);
 }
        public void Modulus_Test()
        {
            var largeInteger = new LargeInteger(LargeIntegerTests.MaxValue);

            LargeInteger result = largeInteger%23;

            Assert.AreEqual(LargeIntegerTests.MaxValue % 23, (ulong)result);
        }
        public void DefaultInitialValue_Test()
        {
            var largeInteger = new LargeInteger();

            Assert.AreEqual(0uL, (ulong)largeInteger);
        }
        public void Subtraction_Test()
        {
            var left = new LargeInteger(LargeIntegerTests.MaxValue);
            var right = new LargeInteger(LargeIntegerTests.MaxValue / 2);

            LargeInteger result = left - right;

            Assert.AreEqual(LargeIntegerTests.MaxValue - LargeIntegerTests.MaxValue / 2, (ulong)result);
        }
        private static int CompareSameLength(LargeInteger left, LargeInteger right)
        {
            int i;
            for (i = left.data.Count - 1; i >= 0; i--)
            {
                if (left.data[i] != right.data[i])
                {
                    break;
                }
            }

            if (i == -1)
            {
                return 0;
            }

            return left.data[i] < right.data[i] ? -1 : 1;
        }
        public void Division_OneElementDenominator_Test()
        {
            const ulong expected = (ulong)(ulong.MaxValue * (3m / 4));

            LargeInteger largeInteger = new LargeInteger(ulong.MaxValue) * 3;
            LargeInteger result = largeInteger / 4;

            Assert.AreEqual(expected, (ulong)result);
        }
        public LargeInteger Pow(ulong power)
        {
            LargeInteger.Logger.Debug($"Entering Pow. this: {this}, power: {power}");

            this.Ensure();

            if (this == 0 && power == 0)
            {
                throw new DivideByZeroException("LargeInteger: divide by zero");
            }

            var result = new LargeInteger(1);

            for (var i = 0uL; i < power; i++)
            {
                result *= this;
            }

            LargeInteger.Logger.Debug($"Exiting Pow. result: {result.PrintLargeInteger()}");
            return result;
        }
        public void Division_OneElementNumerator_Test()
        {
            const ulong expected = (ulong)(48648);

            LargeInteger largeInteger = new LargeInteger(48648 * 75);
            LargeInteger result = largeInteger / 75;

            Assert.AreEqual(expected, (ulong)result);
        }
        public void Division_Test()
        {
            LargeInteger numerator = new LargeInteger(ulong.MaxValue) * 35 * 14;
            LargeInteger denominator = new LargeInteger(ulong.MaxValue) * 35;

            LargeInteger quotient = numerator / denominator;

            Assert.AreEqual((ulong)14, (ulong)quotient);
        }
        public void Division_LargeDenominator_Test()
        {
            LargeInteger a = new LargeInteger(ulong.MaxValue).Pow(7);
            LargeInteger b = new LargeInteger(ulong.MaxValue).Pow(5);

            LargeInteger result = a/b;
            Assert.AreEqual(new LargeInteger(ulong.MaxValue).Pow(2), result);
        }
 private LargeInteger Clone()
 {
     var result = new LargeInteger {data = this.data.GetRange(0, this.data.Count) };
     return result;
 }