diff --git a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs
index 45ec6fa8..21006d0e 100644
--- a/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs
+++ b/mpir.net/mpir.net-tests/HugeFloatTests/Conversions.cs
@@ -83,6 +83,22 @@ namespace MPIR.Tests.HugeFloatTests
}
}
+ [TestMethod]
+ public void FloatToAndFromDouble2()
+ {
+ using (var a = new HugeFloat())
+ {
+ a.SetTo(-123.25);
+
+ long exp;
+ double c = a.ToDouble(out exp);
+ Assert.IsTrue(c.Equals(-0.962890625));
+ Assert.AreEqual(7L, exp);
+ Assert.IsTrue(a.Equals(-123.25));
+ Assert.AreEqual("-0.12325@3", a.ToString());
+ }
+ }
+
[TestMethod]
public void FloatToAndFromFloat()
{
@@ -97,6 +113,73 @@ namespace MPIR.Tests.HugeFloatTests
}
}
+ [TestMethod]
+ public void FloatToAndFromUlong()
+ {
+ using (var a = new HugeFloat())
+ {
+ ulong b = 0xF84739ABCDEF4876;
+ a.SetTo(b);
+
+ a.Value = -a;
+ ulong c = a.ToUlong();
+ Assert.AreEqual(b, c);
+ }
+ }
+
+ [TestMethod]
+ public void FloatToAndFromLong()
+ {
+ using (var a = new HugeFloat())
+ {
+ long b = -0x784739ABCDEF4876;
+ a.SetTo(b);
+
+ long c = a.ToLong();
+ Assert.AreEqual(b, c);
+ }
+ }
+
+ [TestMethod]
+ public void FloatToUlong2()
+ {
+ using (var a = new HugeFloat())
+ using (var small = new HugeFloat(0.0001))
+ {
+ ulong b = ulong.MaxValue;
+ a.SetTo(b);
+ a.Value = a + 1 - small;
+ var c = a.ToUlong();
+
+ Assert.AreEqual(b, c);
+
+ a.Value = -1 + small;
+ c = a.ToUlong();
+ Assert.AreEqual(0UL, c);
+ }
+ }
+
+ [TestMethod]
+ public void FloatToLong2()
+ {
+ using (var a = new HugeFloat())
+ using (var small = new HugeFloat(0.0001))
+ {
+ long b = long.MaxValue;
+ a.SetTo(b);
+ a.Value = a + 1 - small;
+ var c = a.ToLong();
+
+ Assert.AreEqual(b, c);
+
+ b = long.MinValue;
+ a.SetTo(b);
+ a.Value -= 1 - small;
+ c = a.ToLong();
+ Assert.AreEqual(b, c);
+ }
+ }
+
[TestMethod]
public void FloatFromString()
{
@@ -136,6 +219,126 @@ namespace MPIR.Tests.HugeFloatTests
}
}
+ [TestMethod]
+ public void FloatFitsUlong()
+ {
+ using (var a = new HugeFloat(ulong.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsUlong());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsUlong());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsUlong());
+ a.SetTo(0);
+ Assert.IsTrue(a.FitsUlong());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsUlong());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsUlong());
+ }
+ }
+
+ [TestMethod]
+ public void FloatFitsLong()
+ {
+ using (var a = new HugeFloat(long.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsLong());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsLong());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsLong());
+ a.SetTo(long.MinValue);
+ Assert.IsTrue(a.FitsLong());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsLong());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsLong());
+ }
+ }
+
+ [TestMethod]
+ public void FloatFitsUint()
+ {
+ using (var a = new HugeFloat(uint.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsUint());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsUint());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsUint());
+ a.SetTo(0);
+ Assert.IsTrue(a.FitsUint());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsUint());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsUint());
+ }
+ }
+
+ [TestMethod]
+ public void FloatFitsInt()
+ {
+ using (var a = new HugeFloat(int.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsInt());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsInt());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsInt());
+ a.SetTo(int.MinValue);
+ Assert.IsTrue(a.FitsInt());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsInt());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsInt());
+ }
+ }
+
+ [TestMethod]
+ public void FloatFitsUshort()
+ {
+ using (var a = new HugeFloat(ushort.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsUshort());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsUshort());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsUshort());
+ a.SetTo(0);
+ Assert.IsTrue(a.FitsUshort());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsUshort());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsUshort());
+ }
+ }
+
+ [TestMethod]
+ public void FloatFitsShort()
+ {
+ using (var a = new HugeFloat(short.MaxValue))
+ using (var small = new HugeFloat(0.0001))
+ {
+ Assert.IsTrue(a.FitsShort());
+ a.Value = a + 1;
+ Assert.IsFalse(a.FitsShort());
+ a.Value = a - small;
+ Assert.IsTrue(a.FitsShort());
+ a.SetTo(short.MinValue);
+ Assert.IsTrue(a.FitsShort());
+ a.Value = a - 1;
+ Assert.IsFalse(a.FitsShort());
+ a.Value = a + small;
+ Assert.IsTrue(a.FitsShort());
+ }
+ }
+
//private void AssertBetween(int min, int max, long actual)
//{
// Assert.IsTrue(actual >= min && actual <= max, "Expected {0} to {1}, actual {2}", min, max, actual);
diff --git a/mpir.net/mpir.net/HugeFloat.h b/mpir.net/mpir.net/HugeFloat.h
index 2c40e2c4..9e18af18 100644
--- a/mpir.net/mpir.net/HugeFloat.h
+++ b/mpir.net/mpir.net/HugeFloat.h
@@ -891,21 +891,21 @@ namespace MPIR
/// A string representation of the number in the specified base.
String^ ToString(int base, bool lowercase) { return ToString(base, lowercase, 0); }
-/////
-///// Returns the absolute value of the number as a ulong.
-///// If the number is too big, then just the least significant bits that do fit are returned.
-///// The sign of the number is ignored, only the absolute value is used.
-/////
-///// The absolute value as a ulong, possibly truncated to the least significant bits only.
-//mpir_ui ToUlong() { return MP(get_ui)(_value); }
+ ///
+ /// Returns the absolute value of the number as a ulong, truncating any fractional part.
+ /// If the number is too big, the result is undefined. Call FitsUlong() to check if the number will fit.
+ /// The sign of the number is ignored, only the absolute value is used.
+ ///
+ /// The absolute value as a ulong, with any fractional part truncated.
+ mpir_ui ToUlong() { return MP(get_ui)(_value); }
-/////
-///// Returns the value of the number as a long.
-///// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number.
-///// When truncation occurs, the result is propobly not very useful. Call FitsLong() to check if the number will fit.
-/////
-///// The value as a ulong, possibly truncated to the least significant bits only.
-//mpir_si ToLong() { return MP(get_si)(_value); }
+ ///
+ /// Returns the value of the number as a long.
+ /// If the number is too big, the result is undefined. Call FitsLong() to check if the number will fit.
+ ///
+ ///
+ /// The value as a long, possibly truncated to the least significant bits only.
+ mpir_si ToLong() { return MP(get_si)(_value); }
///
/// Returns the value of the number as a double, truncating if necessary (rounding towards zero).
@@ -914,19 +914,20 @@ namespace MPIR
/// The value as a double, possibly truncated.
double ToDouble() { return MP(get_d)(_value); }
-/////
-///// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately.
-///// The return is the mantissa, its absolute value will be in the range [0.5 - 1).
///// If the source value is zero, both mantissa and exponent are returned as 0.
-/////
-///// variable to store the exponent in.
-///// The mantissa of the value as a double, possibly truncated.
-//double ToDouble([Out] mpir_si% exp)
-//{
-// mpir_si x;
-// auto result = MP(get_d_2exp)(&x, _value);
-// exp = x;
-// return result;
-//}
+ ///
+ /// Returns the value of the number as a double, truncating if necessary (rounding towards zero), and returning the exponent separately.
+ /// The return is the mantissa, its absolute value will be in the range [0.5 - 1).
/// The exponent is binary, i.e. mantissa * 2^exp is the value of the source number.
+ /// If the source value is zero, both mantissa and exponent are returned as 0.
+ ///
+ /// variable to store the exponent in.
+ /// The mantissa of the value as a double, possibly truncated.
+ double ToDouble([Out] mpir_si% exp)
+ {
+ mpir_si x;
+ auto result = MP(get_d_2exp)(&x, _value);
+ exp = x;
+ return result;
+ }
#pragma endregion
@@ -1045,19 +1046,41 @@ namespace MPIR
#pragma region Size checks
-/////
-///// 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; }
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the ulong range.
+ ///
+ /// true if the value will fit in a ulong
+ bool FitsUlong() { return MP(fits_ui_p)(_value) != 0; }
+
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the long range.
+ ///
+ /// true if the value will fit in a long
+ bool FitsLong() { return MP(fits_si_p)(_value) != 0; }
+
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the uint range.
+ ///
+ /// true if the value will fit in a uint
+ bool FitsUint() { return MP(fits_uint_p)(_value) != 0; }
+
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the int range.
+ ///
+ /// true if the value will fit in a int
+ bool FitsInt() { return MP(fits_sint_p)(_value) != 0; }
+
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the ushort range.
+ ///
+ /// true if the value will fit in a ushort
+ bool FitsUshort() { return MP(fits_ushort_p)(_value) != 0; }
+
+ ///
+ /// Returns true if the value of the float, when truncated to an integer, is in the short range.
+ ///
+ /// true if the value will fit in a short
+ bool FitsShort() { return MP(fits_sshort_p)(_value) != 0; }
#pragma endregion
diff --git a/mpir.net/mpir.net/HugeInt.h b/mpir.net/mpir.net/HugeInt.h
index bab4cb8b..f54d9f9b 100644
--- a/mpir.net/mpir.net/HugeInt.h
+++ b/mpir.net/mpir.net/HugeInt.h
@@ -1541,7 +1541,7 @@ namespace MPIR
/// If the number is too big, then just the least significant bits that do fit are returned, with the same sign as the number.
/// When truncation occurs, the result is propobly not very useful. Call FitsLong() to check if the number will fit.
///
- /// The value as a ulong, possibly truncated to the least significant bits only.
+ /// The value as a long, possibly truncated to the least significant bits only.
mpir_si ToLong() { return MP(get_si)(_value); }
///