using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Math.Gmp.Native
{
///
/// Represents a pointer to an array of mp_limb_t values in unmanaged memory,
///
///
///
///
///
public class mp_ptr : IEnumerable
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal mp_base mp;
///
/// Creates a new array of limbs in unmanaged memory.
///
/// The number of limbs.
///
///
/// When done with the array, you must release the unmanaged memory by calling free.
///
///
public mp_ptr(mp_size_t size) : this(new uint[size * gmp_lib.mp_uint_per_limb])
{
}
///
/// Creates a new array of limbs initialized with in unmanaged memory.
///
/// The values of the limbs.
///
///
/// If there is not enough bytes to fill out the most significant limb, it is padded with zeroes.
///
///
/// When done with the array, you must release the unmanaged memory by calling free.
///
///
public mp_ptr(byte[] values)
{
if (values == null) throw new ArgumentNullException("values");
mp = new mp_base();
if (values.GetLength(0) == 0)
{
mp._size = 0;
mp.Pointer = IntPtr.Zero;
}
else
{
mp._size = (values.Length + IntPtr.Size - 1) / IntPtr.Size;
mp.Pointer = gmp_lib.allocate((size_t)(mp._size * IntPtr.Size)).ToIntPtr();
Marshal.Copy(new Int32[] { 0, 0 }, 0, (IntPtr)(mp.Pointer.ToInt64() + IntPtr.Size * (mp._size - 1)), IntPtr.Size >> 2);
Marshal.Copy(values, 0, mp.Pointer, values.Length);
}
}
///
/// Creates a new array of limbs initialized with in unmanaged memory.
///
/// The values of the limbs.
///
///
/// If there is not enough 16-bit words to fill out the most significant limb, it is padded with zeroes.
///
///
/// When done with the array, you must release the unmanaged memory by calling free.
///
///
public mp_ptr(ushort[] values)
{
if (values == null) throw new ArgumentNullException("values");
mp = new mp_base();
mp._size = (2 * values.Length + IntPtr.Size - 1) / IntPtr.Size;
mp.Pointer = gmp_lib.allocate((size_t)(mp._size * IntPtr.Size)).ToIntPtr();
Marshal.Copy(new Int32[] { 0, 0 }, 0, (IntPtr)(mp.Pointer.ToInt64() + IntPtr.Size * (mp._size - 1)), IntPtr.Size >> 2);
Marshal.Copy((short[])(object)values, 0, mp.Pointer, values.Length);
}
///
/// Creates a new array of limbs initialized with in unmanaged memory.
///
/// The values of the limbs.
///
///
/// If there is not enough 32-bit words to fill out the most significant limb, it is padded with zeroes.
///
///
/// When done with the array, you must release the unmanaged memory by calling free.
///
///
public mp_ptr(uint[] values)
{
if (values == null) throw new ArgumentNullException("values");
mp = new mp_base();
mp._size = (4 * values.Length + IntPtr.Size - 1) / IntPtr.Size;
mp.Pointer = gmp_lib.allocate((size_t)(mp._size * IntPtr.Size)).ToIntPtr();
Marshal.Copy(new Int32[] { 0, 0 }, 0, (IntPtr)(mp.Pointer.ToInt64() + IntPtr.Size * (mp._size - 1)), IntPtr.Size >> 2);
Marshal.Copy((int[])(object)values, 0, mp.Pointer, values.Length);
}
///
/// Creates a new array of limbs initialized with in unmanaged memory.
///
/// The values of the limbs.
///
///
/// If limbs size is 32 bits, the 64-bit values are split into 32-bit limbs.
///
///
/// When done with the array, you must release the unmanaged memory by calling free.
///
///
public mp_ptr(ulong[] values)
{
if (values == null) throw new ArgumentNullException("values");
mp = new mp_base();
mp._size = (8 * values.Length + IntPtr.Size - 1) / IntPtr.Size;
mp.Pointer = gmp_lib.allocate((size_t)(mp._size * IntPtr.Size)).ToIntPtr();
Marshal.Copy(new Int32[] { 0, 0 }, 0, (IntPtr)(mp.Pointer.ToInt64() + IntPtr.Size * (mp._size - 1)), IntPtr.Size >> 2);
Marshal.Copy((long[])(object)values, 0, mp.Pointer, values.Length);
}
///
/// Creates new pointer to array of limbs at .
///
/// Represents an array of limbs.
public mp_ptr(mp_base mp)
{
this.mp = mp;
}
///
/// The number of limbs.
///
///
public mp_size_t Size
{
get
{
return mp._mp_size;
}
}
///
/// Gets or sets the value of the limb at .
///
/// The zero-based index of the limb to get or set.
///
public mp_limb_t this[int index]
{
get
{
if (index < 0) throw new ArgumentOutOfRangeException("index", "Index cannot be negative.");
if (IntPtr.Size == 4)
{
const int max_index = int.MaxValue / sizeof(int);
if (index > max_index) throw new ArgumentOutOfRangeException("index", "Index must be less than or equal to " + max_index.ToString(System.Globalization.CultureInfo.InvariantCulture) + ".");
return new mp_limb_t((uint)Marshal.ReadInt32(mp._mp_d_intptr, index * sizeof(int)));
}
else
{
const int max_index = int.MaxValue / sizeof(long);
if (index > max_index) throw new ArgumentOutOfRangeException("index", "Index must be less than or equal to " + max_index.ToString(System.Globalization.CultureInfo.InvariantCulture) + ".");
return new mp_limb_t((ulong)Marshal.ReadInt64(mp._mp_d_intptr, index * sizeof(long)));
}
}
set
{
if (index < 0) throw new ArgumentOutOfRangeException("index", "Index cannot be negative.");
if (IntPtr.Size == 4)
{
const int max_index = int.MaxValue / sizeof(int);
if (index > max_index) throw new ArgumentOutOfRangeException("index", "Index must be less than or equal to " + max_index.ToString(System.Globalization.CultureInfo.InvariantCulture) + ".");
Marshal.WriteInt32(mp._mp_d_intptr, index * sizeof(int), (int)(value.Value));
}
else
{
const int max_index = int.MaxValue / sizeof(long);
if (index > max_index) throw new ArgumentOutOfRangeException("index", "Index must be less than or equal to " + max_index.ToString(System.Globalization.CultureInfo.InvariantCulture) + ".");
Marshal.WriteInt64(mp._mp_d_intptr, index * sizeof(long), (long)(value.Value));
}
}
}
///
/// Returns pointer to limbs in unmanaged memory.
///
/// Returns pointer to limbs in unmanaged memory.
public IntPtr ToIntPtr()
{
return mp._mp_d_intptr;
}
///
/// Returns an enumerator that iterates through the array of limbs.
///
/// An enumerator that iterates through the array of limbs.
public IEnumerator GetEnumerator()
{
return new _limb_enumerator(this);
}
///
/// Returns an enumerator that iterates through the array of limbs.
///
/// An enumerator that iterates through the array of limbs.
IEnumerator IEnumerable.GetEnumerator()
{
return new _limb_enumerator(this);
}
private class _limb_enumerator : IEnumerator
{
int index;
mp_ptr limbs;
public _limb_enumerator(mp_ptr limbs)
{
this.limbs = limbs;
Reset();
}
public mp_limb_t Current
{
get
{
return this.limbs[index];
}
}
object IEnumerator.Current
{
get
{
return (object)Current;
}
}
public void Dispose()
{
}
public bool MoveNext()
{
index++;
return index < System.Math.Abs(limbs.Size);
}
public void Reset()
{
index = -1;
}
}
}
}