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);
}
}
}