Refactored to use the more straightforward, but perhaps slightly slower, double allocation
This commit is contained in:
parent
8f6e3bc004
commit
c6434c61b3
@ -20,39 +20,23 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
|
||||
#include "Stdafx.h"
|
||||
#include "Common.h"
|
||||
|
||||
static bool AllocationFunctionsConfigured = false;
|
||||
|
||||
//This custom allocation is used in order to store an MP* struct immediately
|
||||
//before the limb data it references. They are always allocated together.
|
||||
//Therefore, our managed classes only need to store a pointer to the MP struct,
|
||||
//rather than the MP struct itself.
|
||||
//Becasue we cannot store an unmanaged struct in a managed class or struct,
|
||||
//we would need to either pin or copy the struct on stack field by field
|
||||
//every time we had to use it, this way we can just pass "const" pointers around.
|
||||
//for pointers that may be reallocated to MPIR, the struct must still be copied
|
||||
//to stack, but that's only one of three or so for a typical MPIR call.
|
||||
void* CustomAllocate (size_t alloc_size)
|
||||
void CustomFree (void* ptr)
|
||||
{
|
||||
auto ptr = malloc(alloc_size + StructSize);
|
||||
return (char*)ptr + StructSize;
|
||||
void (*freeFunc) (void*, size_t);
|
||||
mp_get_memory_functions (NULL, NULL, &freeFunc);
|
||||
freeFunc(ptr, 0);
|
||||
}
|
||||
|
||||
void* CustomReallocate (void* ptr, size_t old_size, size_t new_size)
|
||||
void* CustomAllocate(size_t size)
|
||||
{
|
||||
auto newPtr = realloc((char*)ptr - StructSize, new_size + StructSize);
|
||||
return (char*)newPtr + StructSize;
|
||||
void* (*allocateFunc) (size_t);
|
||||
mp_get_memory_functions(&allocateFunc, NULL, NULL);
|
||||
return allocateFunc(size);
|
||||
}
|
||||
|
||||
void CustomFree (void* ptr, size_t size)
|
||||
void* CustomReallocate(void* old, size_t size)
|
||||
{
|
||||
free((char*)ptr - StructSize);
|
||||
void* (*reallocateFunc) (void*, size_t, size_t);
|
||||
mp_get_memory_functions(NULL, &reallocateFunc, NULL);
|
||||
return reallocateFunc(old, 0, size);
|
||||
}
|
||||
|
||||
void SetCustomAllocationFunctions()
|
||||
{
|
||||
if(!AllocationFunctionsConfigured)
|
||||
{
|
||||
mp_set_memory_functions(CustomAllocate, CustomReallocate, CustomFree);
|
||||
AllocationFunctionsConfigured = true;
|
||||
}
|
||||
}
|
@ -19,9 +19,6 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
#pragma once
|
||||
|
||||
//call this method from the static constructor of all MPIR.Net wrapper classes.
|
||||
void SetCustomAllocationFunctions();
|
||||
|
||||
void* CustomAllocate (size_t alloc_size);
|
||||
void* CustomReallocate (void* ptr, size_t old_size, size_t new_size);
|
||||
void CustomFree (void* ptr, size_t size);
|
||||
void* CustomReallocate (void* ptr, size_t new_size);
|
||||
void CustomFree (void* ptr);
|
||||
|
@ -20,69 +20,68 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
|
||||
#include "Stdafx.h"
|
||||
#include "Common.h"
|
||||
|
||||
#define DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
void Mpir##name##Expression::AssignTo(HugeInt^ destination) \
|
||||
{ \
|
||||
EDIT_PTR(destination);
|
||||
|
||||
#define DEFINE_ASSIGNMENT_EPILOG \
|
||||
SAVE_PTR(destination); \
|
||||
}
|
||||
#define DEFINE_ASSIGNMENT_PROLOG(name) void Mpir##name##Expression::AssignTo(HugeInt^ destination)
|
||||
|
||||
#define DEFINE_UNARY_ASSIGNMENT(name, operation) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
operation(src_destination, CONST_PTR(Operand)); \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
{ \
|
||||
operation(destination->_value, Operand->_value); \
|
||||
}
|
||||
|
||||
#define DEFINE_BINARY_ASSIGNMENT(name, operation, left, right) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
operation(src_destination, left, right); \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
{ \
|
||||
operation(destination->_value, left, right); \
|
||||
}
|
||||
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_REF(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, CONST_PTR(Left), CONST_PTR(Right))
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_VAL(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, CONST_PTR(Left), Right)
|
||||
#define DEFINE_BINARY_ASSIGNMENT_VAL_REF(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, Left, CONST_PTR(Right))
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_REF(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, Left->_value, Right->_value)
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_VAL(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, Left->_value, Right)
|
||||
#define DEFINE_BINARY_ASSIGNMENT_VAL_REF(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, Left, Right->_value)
|
||||
#define DEFINE_BINARY_ASSIGNMENT_VAL_VAL(name, operation) DEFINE_BINARY_ASSIGNMENT(name, operation, Left, Right)
|
||||
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_SI(name, positiveOp, negativeOp) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
if (Right >= 0) \
|
||||
positiveOp(src_destination, CONST_PTR(Left), static_cast<mpir_ui>(Right)); \
|
||||
else \
|
||||
negativeOp(src_destination, CONST_PTR(Left), -static_cast<mpir_ui>(Right)); \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
#define DEFINE_BINARY_ASSIGNMENT_REF_SI(name, positiveOp, negativeOp) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
{ \
|
||||
if (Right >= 0) \
|
||||
positiveOp(destination->_value, Left->_value, static_cast<mpir_ui>(Right)); \
|
||||
else \
|
||||
negativeOp(destination->_value, Left->_value, -static_cast<mpir_ui>(Right)); \
|
||||
}
|
||||
|
||||
#define DEFINE_BINARY_ASSIGNMENT_SI_REF(name, positiveOp, negativeOp1, negativeOp2) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
if (Left >= 0) \
|
||||
positiveOp(src_destination, static_cast<mpir_ui>(Left), CONST_PTR(Right)); \
|
||||
else \
|
||||
{ \
|
||||
negativeOp1(src_destination, CONST_PTR(Right), -static_cast<mpir_ui>(Left)); \
|
||||
negativeOp2(src_destination, src_destination); \
|
||||
} \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
#define DEFINE_BINARY_ASSIGNMENT_SI_REF(name, positiveOp, negativeOp1, negativeOp2) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
{ \
|
||||
if (Left >= 0) \
|
||||
positiveOp(destination->_value, static_cast<mpir_ui>(Left), Right->_value); \
|
||||
else \
|
||||
{ \
|
||||
negativeOp1(destination->_value, Right->_value, -static_cast<mpir_ui>(Left)); \
|
||||
negativeOp2(destination->_value, destination->_value); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT(name, operation, left, right) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
if(destination != Left) \
|
||||
mpz_set(src_destination, Left->_value); \
|
||||
operation(src_destination, left, right); \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT(name, operation, left, right) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
{ \
|
||||
if(destination != Left) \
|
||||
mpz_set(destination->_value, Left->_value); \
|
||||
operation(destination->_value, left, right); \
|
||||
}
|
||||
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_SI(name, positiveOp, negativeOp, left, right) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
if(destination != Left) \
|
||||
mpz_set(src_destination, Left->_value); \
|
||||
if (right >= 0) \
|
||||
positiveOp(src_destination, left, static_cast<mpir_ui>(right)); \
|
||||
else \
|
||||
negativeOp(src_destination, left, -static_cast<mpir_ui>(right)); \
|
||||
DEFINE_ASSIGNMENT_EPILOG
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_SI(name, positiveOp, negativeOp, left, right) \
|
||||
DEFINE_ASSIGNMENT_PROLOG(name) \
|
||||
{ \
|
||||
if(destination != Left) \
|
||||
mpz_set(destination->_value, Left->_value); \
|
||||
if (right >= 0) \
|
||||
positiveOp(destination->_value, left, static_cast<mpir_ui>(right)); \
|
||||
else \
|
||||
negativeOp(destination->_value, left, -static_cast<mpir_ui>(right)); \
|
||||
}
|
||||
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_REF(name, operation) DEFINE_ADDMUL_ASSIGNMENT(name, operation, CONST_PTR(Right->Left), CONST_PTR(Right->Right))
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_VAL(name, operation) DEFINE_ADDMUL_ASSIGNMENT(name, operation, CONST_PTR(Right->Left), Right->Right)
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_SI(name, positiveop, negativeOp) DEFINE_ADDMUL_ASSIGNMENT_SI(name, positiveop, negativeOp, CONST_PTR(Right->Left), Right->Right)
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_REF(name, operation) DEFINE_ADDMUL_ASSIGNMENT(name, operation, Right->Left->_value, Right->Right->_value)
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_VAL(name, operation) DEFINE_ADDMUL_ASSIGNMENT(name, operation, Right->Left->_value, Right->Right)
|
||||
#define DEFINE_ADDMUL_ASSIGNMENT_REF_SI(name, positiveop, negativeOp) DEFINE_ADDMUL_ASSIGNMENT_SI(name, positiveop, negativeOp, Right->Left->_value, Right->Right)
|
||||
|
||||
using namespace System::Runtime::InteropServices;
|
||||
|
||||
@ -90,28 +89,16 @@ namespace MPIR
|
||||
{
|
||||
#pragma region construction
|
||||
|
||||
static HugeInt::HugeInt()
|
||||
{
|
||||
SetCustomAllocationFunctions();
|
||||
}
|
||||
|
||||
HugeInt::HugeInt(mpz_srcptr src_this)
|
||||
{
|
||||
SAVE_PTR(this);
|
||||
}
|
||||
|
||||
HugeInt::HugeInt()
|
||||
{
|
||||
mpz_t src_this;
|
||||
mpz_init(src_this);
|
||||
SAVE_PTR(this);
|
||||
AllocateStruct();
|
||||
mpz_init(_value);
|
||||
}
|
||||
|
||||
HugeInt::HugeInt(mp_bitcnt_t value)
|
||||
HugeInt::HugeInt(mp_bitcnt_t bits)
|
||||
{
|
||||
mpz_t src_this;
|
||||
mpz_init2(src_this, value);
|
||||
SAVE_PTR(this);
|
||||
AllocateStruct();
|
||||
mpz_init2(_value, bits);
|
||||
}
|
||||
|
||||
HugeInt::HugeInt(String^ value)
|
||||
@ -126,33 +113,31 @@ namespace MPIR
|
||||
|
||||
void HugeInt::FromString(String^ value, int base)
|
||||
{
|
||||
mpz_t src_this;
|
||||
AllocateStruct();
|
||||
|
||||
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
|
||||
bool success = 0 == mpz_init_set_str(src_this, (char*)(void*)ptr, base);
|
||||
bool success = 0 == mpz_init_set_str(_value, (char*)(void*)ptr, base);
|
||||
Marshal::FreeHGlobal(ptr);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
mpz_clear(src_this);
|
||||
DeallocateStruct();
|
||||
throw gcnew ArgumentException("InvalidNumber", "value");
|
||||
}
|
||||
|
||||
SAVE_PTR(this);
|
||||
}
|
||||
|
||||
HugeInt^ HugeInt::FromLong(mpir_si value)
|
||||
{
|
||||
mpz_t src_a;
|
||||
mpz_init_set_si(src_a, value);
|
||||
return gcnew HugeInt(src_a);
|
||||
auto result = gcnew HugeInt();
|
||||
mpz_set_si(result->_value, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
HugeInt^ HugeInt::FromUlong(mpir_ui value)
|
||||
{
|
||||
mpz_t src_a;
|
||||
mpz_init_set_ui(src_a, value);
|
||||
return gcnew HugeInt(src_a);
|
||||
auto result = gcnew HugeInt();
|
||||
mpz_set_ui(result->_value, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
//unmanaged destructor makes the compiler implement IDisposable
|
||||
@ -166,10 +151,7 @@ namespace MPIR
|
||||
HugeInt::!HugeInt()
|
||||
{
|
||||
if(_value != 0)
|
||||
{
|
||||
mpz_clear(_value);
|
||||
_value = 0;
|
||||
}
|
||||
DeallocateStruct();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@ -185,7 +167,7 @@ namespace MPIR
|
||||
{
|
||||
char* str = mpz_get_str(NULL, base, _value);
|
||||
String^ result = gcnew String(str);
|
||||
CustomFree(str, 0);
|
||||
CustomFree(str);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -21,40 +21,6 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
using namespace System;
|
||||
|
||||
typedef __mpz_struct StructType;
|
||||
static const int StructSize = sizeof(StructType);
|
||||
|
||||
//makes a local var from the managed mpz struct data of the specified instance.
|
||||
//this must be done when we're about to call an MPIR method that may realloc
|
||||
//the limb data, since we're using a custom alloc scheme where the referencing MP* struct
|
||||
//is stored in the same allocated block.
|
||||
//Local var must subsequently be saved with SAVE_PTR.
|
||||
//all other pointers used in the same method that are "const" for MPIR
|
||||
//must be wrapped in CONST_PTR
|
||||
#define EDIT_PTR(x) mpz_t src_##x; src_##x[0] = *x->_value
|
||||
|
||||
////makes a local var from the managed mpz struct data of this instance
|
||||
//#define THIS_PTR EDIT_PTR(this)
|
||||
|
||||
//converts from allocated limbs pointer to the mpz struct pointer the class will keep
|
||||
#define ToStructPtr(x) (StructType*)((char*)x - StructSize)
|
||||
|
||||
//updates the managed mpz struct data for the specified instance from a local var
|
||||
#define SAVE_PTR(x) \
|
||||
x->_value = ToStructPtr(src_##x->_mp_d); \
|
||||
*x->_value = src_##x[0]
|
||||
|
||||
////updates the managed mpz struct data for this instance from a local var
|
||||
//#define SAVE_THIS SAVE_PTR(this)
|
||||
|
||||
//wraps a "const" pointer for safe calling into MPIR methods.
|
||||
//The underlying MP* structs for any editable pointers are copied to local vars.
|
||||
//"const" pointers distinct from those are used unchanged;
|
||||
//but if a "const" pointer is the same as one that was copied,
|
||||
//it must reference the same local var because some MPIR methods compare them and
|
||||
//optimize for such equality.
|
||||
#define CONST_PTR(x) (x != destination ? x->_value : src_destination)
|
||||
|
||||
//defines a unary expression class
|
||||
#define DEFINE_UNARY_EXPRESSION(name, type) \
|
||||
public ref class Mpir##name##Expression : IMpirExpression \
|
||||
@ -132,12 +98,21 @@ namespace MPIR
|
||||
|
||||
private:
|
||||
//construction
|
||||
HugeInt(mpz_srcptr src);
|
||||
void AllocateStruct()
|
||||
{
|
||||
_value = (__mpz_struct*)CustomAllocate(sizeof(__mpz_struct));
|
||||
}
|
||||
void DeallocateStruct()
|
||||
{
|
||||
mpz_clear(_value);
|
||||
CustomFree(_value);
|
||||
_value = nullptr;
|
||||
}
|
||||
//HugeInt(mpz_srcptr src);
|
||||
void FromString(String^ value, int base);
|
||||
|
||||
public:
|
||||
//construction
|
||||
static HugeInt();
|
||||
HugeInt();
|
||||
HugeInt(mp_bitcnt_t bits);
|
||||
HugeInt(String^ value);
|
||||
@ -165,11 +140,7 @@ namespace MPIR
|
||||
virtual void AssignTo(HugeInt^ destination)
|
||||
{
|
||||
if(this != destination)
|
||||
{
|
||||
EDIT_PTR(destination);
|
||||
mpz_set(src_destination, _value);
|
||||
SAVE_PTR(destination);
|
||||
}
|
||||
mpz_set(destination->_value, _value);
|
||||
}
|
||||
|
||||
//arithmetic
|
||||
|
@ -24,4 +24,5 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
|
||||
#pragma once
|
||||
|
||||
#include "mpir.h"
|
||||
#include "Common.h"
|
||||
#include "HugeInt.h"
|
||||
|
Loading…
Reference in New Issue
Block a user