Math.Gmp.Native/Math.Gmp.Native/mpf_t.cs

182 lines
6.7 KiB
C#
Raw Permalink Normal View History

2017-11-04 16:02:37 +01:00

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Math.Gmp.Native
{
/// <summary>
/// Represents a multiple precision floating-point number.
/// </summary>
/// <remarks>
/// <para>
2017-12-15 02:18:55 +01:00
/// The floating point functions accept and return exponents in the C type <see cref="mp_exp_t">mp_exp_t</see>.
2017-11-04 16:02:37 +01:00
/// Currently this is usually a long, but on some systems its an int for efficiency.
/// </para>
/// <para>
/// In .NET, this is a 32-bit integer.
/// </para>
/// </remarks>
2017-12-15 02:18:55 +01:00
/// <seealso cref="mp_exp_t">mp_exp_t</seealso>
/// <seealso cref="mp_limb_t">mp_limb_t</seealso>
/// <seealso cref="mpq_t">mpq_t</seealso>
/// <seealso cref="mpz_t">mpz_t</seealso>
2017-11-04 16:02:37 +01:00
public class mpf_t : mp_base
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _initialized = false;
2017-11-04 16:02:37 +01:00
internal void Initializing()
2017-11-04 16:02:37 +01:00
{
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);
}
internal void Initialized()
{
//gmp_lib.ZeroMemory(Pointer, (int)length);
_initialized = true;
}
internal void Clear()
{
if (_initialized) gmp_lib.free(Pointer);
Pointer = IntPtr.Zero;
_initialized = false;
2017-11-04 16:02:37 +01:00
}
/// <summary>
/// The number of limbs currently in use, or the negative of that when representing a negative value.
/// </summary>
/// <remarks>
/// <para>
2017-12-15 02:18:55 +01:00
/// Zero is represented by <see cref="_mp_size">_mp_size</see> and <see cref="_mp_exp">_mp_exp</see> both set to zero,
/// and in that case the <see cref="mp_base._mp_d">mp_base._mp_d</see> data is unused.
/// (In the future <see cref="_mp_exp">_mp_exp</see> might be undefined when representing zero.)
2017-11-04 16:02:37 +01:00
/// </para>
/// </remarks>
public override mp_size_t _mp_size
{
get
{
return Marshal.ReadInt32(Pointer, /*sizeof(int)*/ 4);
2017-11-04 16:02:37 +01:00
}
}
/// <summary>
/// The precision of the mantissa, in limbs.
/// </summary>
/// <remarks>
/// <para>
2017-12-15 02:18:55 +01:00
/// In any calculation the aim is to produce <see cref="_mp_prec">_mp_prec</see> limbs of result (the most significant being non-zero).
2017-11-04 16:02:37 +01:00
/// </para>
/// </remarks>
public int _mp_prec
{
get
{
return Marshal.ReadInt32(Pointer, 0);
2017-11-04 16:02:37 +01:00
}
}
/// <summary>
/// The exponent, in limbs, determining the location of the implied radix point.
/// </summary>
/// <remarks>
/// <para>
/// 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 &#8805; 1, as for example in the diagram above.
/// Negative exponents mean a radix point further above the highest limb.
/// </para>
/// <para>
/// Naturally the exponent can be any value, it doesnt have to fall within the limbs as the diagram shows,
/// it can be a long way above or a long way below.
2017-12-15 02:18:55 +01:00
/// Limbs other than those included in the {<see cref="mp_base._mp_d">mp_base._mp_d</see>, <see cref="_mp_size">_mp_size</see>} data are treated as zero.
2017-11-04 16:02:37 +01:00
/// </para>
/// </remarks>
public int _mp_exp
{
get
{
return Marshal.ReadInt32(Pointer, /*sizeof(int) + sizeof(int)*/ 8);
2017-11-04 16:02:37 +01:00
}
}
/// <summary>
/// Gets or sets the pointer to the significand array of limbs of the floating-point number.
/// </summary>
2017-11-04 16:02:37 +01:00
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public override IntPtr _mp_d_intptr
2017-11-04 16:02:37 +01:00
{
get
{
return Marshal.ReadIntPtr(Pointer, /*sizeof(int) + sizeof(int) + sizeof(int)*/ 12);
2017-11-04 16:02:37 +01:00
}
set
{
Marshal.WriteIntPtr(Pointer, /*sizeof(int) + sizeof(int) + sizeof(int)*/ 12, value);
2017-11-04 16:02:37 +01:00
}
}
/// <summary>
/// Gets the unmanaged memory pointer of the multiple precision floating-point number.
/// </summary>
/// <returns>The unmanaged memory pointer of the multiple precision floating-point number.</returns>
public IntPtr ToIntPtr()
{
return Pointer;
2017-11-04 16:02:37 +01:00
}
/// <summary>
2017-12-15 02:18:55 +01:00
/// Converts a <see cref="string">string</see> value to an <see cref="mpf_t">mpf_t</see> value.
2017-11-04 16:02:37 +01:00
/// </summary>
2017-12-15 02:18:55 +01:00
/// <param name="value">A <see cref="string">string</see> value.</param>
/// <returns>An <see cref="mpf_t">mpf_t</see> value.</returns>
2017-11-04 16:02:37 +01:00
/// <remarks>
/// <para>
/// Base is assumed to be 10 unless the first character of the string is <c>B</c>
/// followed by the base <c>2</c> to <c>62</c> or <c>-62</c> to <c>-2</c> followed
/// by a space and then the floating-point number.
/// Negative values are used to specify that the exponent is in decimal.
/// </para>
/// </remarks>
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;
}
/// <summary>
/// Return the string representation of the float.
/// </summary>
/// <returns>The string representation of the float.</returns>
public override string ToString()
{
if (!_initialized) return null;
ptr<mp_exp_t> exp = new ptr<mp_exp_t>(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);
2017-11-04 16:02:37 +01:00
else
return "0." + s + "e" + exp.Value.Value.ToString(System.Globalization.CultureInfo.InvariantCulture);
2017-11-04 16:02:37 +01:00
}
}
}