using System; using System.Runtime.InteropServices; using System.Diagnostics; namespace Math.Gmp.Native { /// /// Represents a multiple precision floating-point number. /// /// /// /// The floating point functions accept and return exponents in the C type . /// Currently this is usually a long, but on some systems it’s an int for efficiency. /// /// /// In .NET, this is a 32-bit integer. /// /// /// /// /// /// public class mpf_t : mp_base { [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal bool _initialized = false; /// /// Creates a new multiple precision floating-point number. /// public mpf_t() { size_t length = /*sizeof(int) + sizeof(int) + sizeof(int)*/ 12U + (size_t)IntPtr.Size; _pointer = gmp_lib.allocate(length).ToIntPtr(); gmp_lib.ZeroMemory(_pointer, (int)length); } /// /// The number of limbs currently in use, or the negative of that when representing a negative value. /// /// /// /// Zero is represented by and both set to zero, /// and in that case the data is unused. /// (In the future might be undefined when representing zero.) /// /// public override mp_size_t _mp_size { get { return Marshal.ReadInt32(_pointer, /*sizeof(int)*/ 4); } } /// /// The precision of the mantissa, in limbs. /// /// /// /// In any calculation the aim is to produce limbs of result (the most significant being non-zero). /// /// public int _mp_prec { get { return Marshal.ReadInt32(_pointer, 0); } } /// /// The exponent, in limbs, determining the location of the implied radix point. /// /// /// /// Zero means the radix point is just above the most significant limb. /// Positive values mean a radix point offset towards the lower limbs and hence a value ≥ 1, as for example in the diagram above. /// Negative exponents mean a radix point further above the highest limb. /// /// /// Naturally the exponent can be any value, it doesn’t have to fall within the limbs as the diagram shows, /// it can be a long way above or a long way below. /// Limbs other than those included in the {, } data are treated as zero. /// /// public int _mp_exp { get { return Marshal.ReadInt32(_pointer, /*sizeof(int) + sizeof(int)*/ 8); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal override IntPtr _mp_d_intptr { get { return Marshal.ReadIntPtr(_pointer, /*sizeof(int) + sizeof(int) + sizeof(int)*/ 12); } set { Marshal.WriteIntPtr(_pointer, /*sizeof(int) + sizeof(int) + sizeof(int)*/ 12, value); } } /// /// Gets the unmanaged memory pointer of the multiple precision floating-point number. /// /// The unmanaged memory pointer of the multiple precision floating-point number. public IntPtr ToIntPtr() { return _pointer; } /// /// Converts a value to an value. /// /// A value. /// An value. /// /// /// Base is assumed to be 10 unless the first character of the string is B /// followed by the base 2 to 62 or -62 to -2 followed /// by a space and then the floating-point number. /// Negative values are used to specify that the exponent is in decimal. /// /// public static implicit operator mpf_t(string value) { int @base = 10; mpf_t x = new mpf_t(); gmp_lib.mpf_init(x); if (value != null && value.Substring(0, 1).ToUpperInvariant() == "B") { int pos = value.IndexOf(' ', 1); if (pos != -1 && int.TryParse(value.Substring(1, pos - 1), out @base) == true) value = value.Substring(pos + 1); } char_ptr s = new char_ptr(value); gmp_lib.mpf_set_str(x, s, @base); gmp_lib.free(s); return x; } /// /// Return the string representation of the float. /// /// The string representation of the float. public override string ToString() { if (!_initialized) return null; ptr exp = new ptr(0); char_ptr s_ptr = gmp_lib.mpf_get_str(char_ptr.Zero, exp, 10, 0, this); string s = s_ptr.ToString(); gmp_lib.free(s_ptr); if (s.StartsWith("-", StringComparison.Ordinal)) return "-0." + s.Substring(1) + "e" + exp.Value._value.ToString(System.Globalization.CultureInfo.InvariantCulture); else return "0." + s + "e" + exp.Value._value.ToString(System.Globalization.CultureInfo.InvariantCulture); } } }