diff --git a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj index 2ee01fff..7c2b2c93 100644 --- a/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj +++ b/build.vc11/mpir.net/mpir.net-tests/mpir.net-tests.csproj @@ -112,6 +112,9 @@ HugeFloatTests\ExpressionTests.cs + + HugeFloatTests\IO.cs + HugeIntTests\Arithmetic.cs diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs index 7ddb3587..308afe8e 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs @@ -142,7 +142,6 @@ namespace MPIR.Tests.HugeFloatTests Assert.AreEqual(75, exp); c *= Math.Pow(2, exp); - //Assert.AreEqual(-123.45e20, c); Assert.IsTrue(a + 10000000000 >= c); Assert.IsTrue(a - 10000000000 <= c); } diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/IO.cs b/mpir.net/mpir.net-tests/HugeFloatTests/IO.cs index 536b0992..f595ee82 100644 --- a/mpir.net/mpir.net-tests/HugeFloatTests/IO.cs +++ b/mpir.net/mpir.net-tests/HugeFloatTests/IO.cs @@ -23,63 +23,50 @@ using System.Text; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace MPIR.Tests.HugeRationalTests +namespace MPIR.Tests.HugeFloatTests { [TestClass] public class IO { [TestMethod] - public void RationalInputOutputRaw() + public void FloatInputOutputStr() { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) - { - a.Value = a ^ 100; - a.Write(ms); - ms.Position = 0; - b.Read(ms); - Assert.AreEqual(a, b); - Assert.AreEqual(ms.Length, ms.Position); - } - } - - [TestMethod] - public void RationalInputOutputStr() - { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) + using (var a = new HugeFloat("10123456789ABCDEF012345.6789ABCDE", 16)) + using (var b = HugeFloat.Allocate(12800)) using (var ms = new MemoryStream()) { + a.Reallocate(12800); a.Value = a ^ 100; using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer); + a.Write(writer, 10, 0, false, false); ms.Position = 0; using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader); + b.Read(reader, 10, false); Assert.AreEqual(a, b); Assert.AreEqual(ms.Length, ms.Position); + Assert.AreEqual((char)0xFEFF + a.ToString(10), Encoding.UTF8.GetString(ms.ToArray())); } } [TestMethod] - public void RationalInputOutputStrHex() + public void FloatInputOutputStrHex() { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) + using(var a = new HugeFloat("10123456789ABCDEF012345.6789ABCDE", 16)) + using (var b = HugeFloat.Allocate(12800)) using (var ms = new MemoryStream()) { + a.Reallocate(12800); a.Value = a ^ 100; using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer, 16); + a.Write(writer, 16, 0, false, false); ms.Position = 0; using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader, 16); + b.Read(reader, 16, false); Assert.AreEqual(a, b); Assert.AreEqual(ms.Length, ms.Position); @@ -88,111 +75,67 @@ namespace MPIR.Tests.HugeRationalTests } [TestMethod] - public void RationalInputOutputStrHexPrefix() + public void FloatInputOutputStrHexLower() { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) + using(var a = new HugeFloat("10123456789ABCDEF012345.6789ABCDE", 16)) + using(var b = HugeFloat.Allocate(12800)) + using(var ms = new MemoryStream()) { + a.Reallocate(12800); a.Value = a ^ 100; - using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - { - writer.Write("0x"); - a.Numerator.Write(writer, 16); - writer.Write("/0"); - a.Denominator.Write(writer, 8); - } + using(var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) + a.Write(writer, 16, 0, true, false); ms.Position = 0; - using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader); + using(var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) + b.Read(reader, 16, false); Assert.AreEqual(a, b); Assert.AreEqual(ms.Length, ms.Position); + Assert.AreEqual((char)0xFEFF + a.ToString(16, true), Encoding.UTF8.GetString(ms.ToArray())); } } [TestMethod] - public void RationalInputOutputStrHexLower() + public void FloatInputOutputStrHexExpDecimal() { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) + using(var a = new HugeFloat("10123456789ABCDEF012345.6789ABCDE", 16)) + using(var b = HugeFloat.Allocate(12800)) + using(var ms = new MemoryStream()) { + a.Reallocate(12800); a.Value = a ^ 100; - using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer, 16, true); + using(var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) + a.Write(writer, 16, 0, false, true); ms.Position = 0; - using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader, 16); + using(var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) + b.Read(reader, 16, true); Assert.AreEqual(a, b); Assert.AreEqual(ms.Length, ms.Position); + Assert.AreEqual((char)0xFEFF + a.ToString(16, false, true), Encoding.UTF8.GetString(ms.ToArray())); } } [TestMethod] - public void RationalInputOutputStrOctal() + public void FloatInputOutputStr62() { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) + using(var a = new HugeFloat("10123456789ABCDEF012345.6789ABCDE", 16)) + using(var b = HugeFloat.Allocate(12800)) + using(var ms = new MemoryStream()) { + a.Reallocate(12800); a.Value = a ^ 100; - using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer, 8); + using(var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) + a.Write(writer, 62, 0, false, false); ms.Position = 0; - using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader, 8); - - Assert.AreEqual(a, b); - Assert.AreEqual(ms.Length, ms.Position); - Assert.AreEqual((char)0xFEFF + a.ToString(8), Encoding.UTF8.GetString(ms.ToArray())); - } - } - - [TestMethod] - public void RationalInputOutputStrBinary() - { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) - { - a.Value = a ^ 100; - using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer, 2); - - ms.Position = 0; - - using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader, 2); - - Assert.AreEqual(a, b); - Assert.AreEqual(ms.Length, ms.Position); - Assert.AreEqual((char)0xFEFF + a.ToString(2), Encoding.UTF8.GetString(ms.ToArray())); - } - } - - [TestMethod] - public void RationalInputOutputStr62() - { - using (var a = new HugeRational("0x10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/361720912810755408215708460645842859722715865206816237944587")) - using (var b = new HugeRational()) - using (var ms = new MemoryStream()) - { - a.Value = a ^ 100; - using (var writer = new StreamWriter(ms, Encoding.UTF8, 1024, true)) - a.Write(writer, 62); - - ms.Position = 0; - - using (var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) - b.Read(reader, 62); + using(var reader = new StreamReader(ms, Encoding.UTF8, false, 1024, true)) + b.Read(reader, 62, false); Assert.AreEqual(a, b); Assert.AreEqual(ms.Length, ms.Position); diff --git a/mpir.net/mpir.net/HugeFloat.cpp b/mpir.net/mpir.net/HugeFloat.cpp index 4f6e67ea..24a30cef 100644 --- a/mpir.net/mpir.net/HugeFloat.cpp +++ b/mpir.net/mpir.net/HugeFloat.cpp @@ -330,26 +330,14 @@ namespace MPIR #pragma region IO - #define chunkSize 1024 - - size_t MPTYPE::Write(Stream^ stream) + size_t MPTYPE::Write(TextWriter^ writer, int base, int maxDigits, bool lowercase, bool exponentInDecimal) { - throw gcnew NotImplementedException(); - } - - size_t MPTYPE::Read(Stream^ stream) - { - throw gcnew NotImplementedException(); - } - - size_t MPTYPE::Write(TextWriter^ writer, int base, bool lowercase) - { - auto str = ToString(base, lowercase); + auto str = ToString(base, lowercase, maxDigits, exponentInDecimal); writer->Write(str); return str->Length; } - size_t MPTYPE::Read(TextReader^ reader, int base) + size_t MPTYPE::Read(TextReader^ reader, int base, bool exponentInDecimal) { throw gcnew NotImplementedException(); } diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h index b639ccdb..d4878917 100644 --- a/mpir.net/mpir.net/HugeFloat.h +++ b/mpir.net/mpir.net/HugeFloat.h @@ -1136,204 +1136,108 @@ namespace MPIR _allocatedPrecision = precision; } -///// -///// Returns the number of digits the number would take if written in the specified base. -///// The sign of the number is ignored, just the absolute value is used. -///// The result will be either exact or at most 2 characters too big. -///// If is a power of 2, the result will always be exact. -///// If the number is 0, the result is always 3. -///// This function can be used to estimate the space required when converting to a string. -///// The right amount of allocation is normally two more than the value returned, -///// one extra for a minus sign and one for the null-terminator. -///// A slash between numerator and denominator is accounted for. -///// Numeric base for the would-be string conversion, in the range from 2 to 62. -///// The number of digits the number would take written in the specified base, possibly 1 or 2 too big, not counting a leading minus. -//mp_size_t ApproximateSizeInBase(int base) { return mpz_sizeinbase(&_value->_mp_num, base) + mpz_sizeinbase(&_value->_mp_den, base) + 1; } - #pragma endregion #pragma region IO - /// - /// Outputs the float to the in raw binary format. - /// The number's numerator and denominator are written in sequence, each in a portable format, - /// with 4 bytes of size information, and that many bytes of limbs. - /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). - /// The output can be read with Read(Stream). - /// The output cannot be read by MP(inp_raw) from GMP 1, because of changes necessary - /// for compatibility between 32-bit and 64-bit machines. - /// - /// Stream to output the number to - /// the number of bytes written, or 0 if an error occurs. - size_t Write(Stream^ stream); - - /// - /// Reads the float value from the in raw binary format, as it would have been written by Write(Stream). - /// The number's numerator and denominator are read in sequence, each in a portable format, - /// with 4 bytes of size information, and that many bytes of limbs. - /// Both the size and the limbs are written in decreasing significance order (i.e., in big-endian). - /// This routine can read the output from MP(out_raw) also from GMP 1, in spite of changes - /// necessary for compatibility between 32-bit and 64-bit machines. - /// - /// Stream to input the number from - /// the number of bytes read, or 0 if an error occurs. - size_t Read(Stream^ stream); - /// /// Outputs the float to the as a string of digits in decimal. - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid decimal digit. - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// /// Text writer to output the number to /// the number of characters written - size_t Write(TextWriter^ writer) { return Write(writer, 0, false); } + size_t Write(TextWriter^ writer) { return Write(writer, 10, 0, false, true); } /// /// Outputs the float to the as a string of digits in base . - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid digit in base . - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// For hexadecimal, binary, or octal, no leading base indication is written. - /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. - /// + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent in the same base. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// /// Text writer to output the number to /// The base to use for the output. /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. /// the number of characters written - size_t Write(TextWriter^ writer, int base) { return Write(writer, base, false); } + size_t Write(TextWriter^ writer, int base) { return Write(writer, base, 0, false, true); } /// /// Outputs the float to the as a string of digits in base . - /// When writing multiple numbers that are to be read back with the Read(TextReader) method, - /// it is useful to separate the numbers with a character that is not a valid digit in base . - /// This is because the Read method stops reading when it encounters a character that cannot represent a digit. - /// For hexadecimal, binary, or octal, no leading base indication is written. - /// Therefore, for bases other than 10, use the Read(reader, base) overload rather than Read(reader) to read the number back. - /// + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// + /// Text writer to output the number to + /// Indicates if lowercase or uppercase letters should be used for the output. + /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// The base to use for the output. + /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// the number of characters written + size_t Write(TextWriter^ writer, int base, bool lowercase) { return Write(writer, base, 0, lowercase, true); } + + /// + /// Outputs the float to the as a string of digits in base . + /// The mantissa is prefixed with an '0.', and is followed by '@' and an integer exponent. + /// When writing multiple numbers that are to be read back with the Read(TextReader) method, + /// it is useful to separate the numbers with a character that is not valid for this format. + /// This is because the Read method stops reading when it encounters an invalid character. + /// /// Text writer to output the number to /// The base to use for the output. /// The base can be from 2 to 62; Bases up to 36 use uppercase or lowercase letters based on the argument. /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. /// Indicates if lowercase or uppercase letters should be used for the output. /// This argument is ignored for bases larger than 36, where both uppercase and lowercase letters are used. + /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. + /// Maximum number of digits for the mantissa. + /// No more digits than are accurately representable by the number's precision will be printed. + /// Use zero to select that accurate maximum. /// the number of characters written - size_t Write(TextWriter^ writer, int base, bool lowercase); + size_t Write(TextWriter^ writer, int base, int maxDigits, bool lowercase, bool exponentInDecimal); /// /// Inputs the number as a possibly white-space preceeded string. - /// The base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. - /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. - /// This method reads the output of a Write(TextWriter) when decimal base is used. - /// For hexadecimal, binary, or octal, because Write(TextWriter) doesn't write leading base indication characters, - /// using this overload of Read will fail to recognize the correct base. + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa and exponent are always in decimal, no leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter) when decimal base is used. + /// /// Text reader to input the number from /// the number of characters read - size_t Read(TextReader^ reader) { return Read(reader, 0); } + size_t Read(TextReader^ reader) { return Read(reader, 0, true); } /// - /// Inputs the number as a possibly white-space preceeded string in base from the . - /// Reading terminates at end-of-stream, or up to but not including a character that is not a valid digit. - /// This method reads the output of a Write(TextWriter) method. + /// Inputs the number as a possibly white-space preceeded string. + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa is always in the specified base, the exponent is always in decimal. No leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter) when decimal base is used. + /// + /// Text reader to input the number from + /// The base to use for the mantissa. + /// The base can be from 2 to 62; uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// For bases larger than 36, the argument is ignored and uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// the number of characters read + size_t Read(TextReader^ reader, int base) { return Read(reader, base, true); } + + /// + /// The string is in the form 'Mantissa@Exponent' or, if the base is 10 or less, alternatively 'MeN'. + /// The mantissa is always in the specified base, the exponent is either in the same base or in decimal. No leading base characters are allowed. + /// Reading terminates at end-of-stream, or up to but not including a character that is not valid for this format. + /// This method reads the output of a Write(TextWriter, ...) method with the same base. /// /// Text reader to input the number from /// The base to use for the input. /// The base can be from 2 to 62; For bases up to 36 case is ignored. - /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. - /// If 0, the base of the number is determined from the leading characters: 0x or 0X for hexadecimal, 0b or 0B for binary, 0 for octal, decimal otherwise. - /// Note that the leading base characters are not written by the Write method. + /// For bases larger than 36, uppercase letters represent digits 10-35 while lowercase letters represent digits 36-61. + /// Whether the exponent should always be written in decimal, or use the same base as the mantissa. /// the number of characters read - size_t Read(TextReader^ reader, int base); - -///// -///// Imports the number from arbitrary words of binary data. -///// No sign information is taken from the data, the imported number will be positive or zero. -///// -///// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. -///// Array of binary "limbs" to import from. -///// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. -///// Number of "limbs" to import -///// Number of bytes per "limb." -///// Specifies the order of the "limbs." -///// Specifies the byte order within each "limb." -///// The number of most-significant bits to ignore in each "limb." -//generic where T : value class void Import(array^ data, size_t limbCount, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) -//{ -// if(limbCount == 0) -// { -// MP(set_ui)(_value, 0); -// return; -// } - -// PIN(data); -// MP(import)(_value, limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, pinned_data); -//} - -///// -///// Exports the absolute value of the number to arbitrary words of binary data. -///// The sign of op is ignored. -///// -///// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. -///// Array of binary "limbs" to export to. -///// Elements don't necessarily need to be of the size; the data is interpreted as a flat byte array. -///// The total size of the array in bytes must be sufficient for the export. -///// Number of bytes per "limb." -///// Specifies the order of the "limbs." -///// Specifies the byte order within each "limb." -///// The number of most-significant bits to reserve, and set to zero, in each "limb." -///// The number of limbs exported. -///// If the number is non-zero, then the most significant word produced will be non-zero. -///// If the number is zero, then the count returned will be zero and nothing written to the data. -//generic where T : value class size_t Export(array^ data, int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) -//{ -// PIN(data); -// size_t limbCount; -// MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); -// return limbCount; -//} - -// /// -// /// Exports the absolute value of the number to arbitrary words of binary data. An array of type T is allocated for the export. -// /// The sign of op is ignored. -// /// -// /// Type of element in the data array. This must be a value type, but does not need to represent a single limb. Data is interpreted as a flat byte array. -// /// Number of bytes per "limb." -// /// Specifies the order of the "limbs." -// /// Specifies the byte order within each "limb." -// /// The number of most-significant bits to reserve, and set to zero, in each "limb." -// /// An array of type T containing the exported limb data. -// /// If the number is non-zero, then the most significant word produced will be non-zero. -// /// If the number is zero, then a zero-length array is returned. -// generic where T : value class array^ Export(int bytesPerLimb, LimbOrder limbOrder, Endianness endianness, int nails) -// { -// if(this->Sign() == 0) -// return gcnew array(0); - -// auto bitsPerLimb = 8 * bytesPerLimb - nails; -// auto limbCount = (MP(sizeinbase)(_value, 2) - 1) / bitsPerLimb + 1; -// auto arrayCount = (limbCount * bytesPerLimb - 1) / sizeof(T) + 1; -// auto data = gcnew array(arrayCount); - -// PIN(data); -// MP(export)(pinned_data, &limbCount, (int)limbOrder, bytesPerLimb, (int)endianness, nails, _value); -// return data; -// } - -//internal: -// size_t ReadNoWhite(TextReader^ reader, int base, size_t nread); - -//public: - -// /// -// /// Returns the specified limb of the number. -// /// The least significant limb is zero. -// /// The sign of the number is ignored. -// /// -// /// The index of the limb to return. -// /// The least significant limb is zero. -// /// If the index is outside the range 0 to Size()-1, zero is returned. -// /// The specified limb, or zero if is outside of the valid range. -// size_t GetLimb(mp_size_t index) { return MP(getlimbn)(_value, index); } + size_t Read(TextReader^ reader, int base, bool exponentInDecimal); #pragma endregion