Major refactoring in preparation for adding the rational class. Broken build due to partial commit.

This commit is contained in:
Alex Dyachenko 2014-05-10 15:30:45 -04:00
parent 55e44923cf
commit 6e4af8e176
10 changed files with 1014 additions and 845 deletions

View File

@ -150,7 +150,6 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\mpir.net\mpir.net\AssemblyInfo.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\Common.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeInt.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeRational.cpp" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\Random.cpp" />
@ -170,6 +169,9 @@
<ItemGroup>
<Image Include="..\..\..\mpir.net\mpir.net\app.ico" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\mpir.net\mpir.net\ExpressionMacros.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -44,9 +44,6 @@
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeInt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\mpir.net\mpir.net\Common.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\mpir.net\mpir.net\Random.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -67,4 +64,9 @@
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\mpir.net\mpir.net\ExpressionMacros.h">
<Filter>Header Files</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -26,7 +26,7 @@ using System.Reflection;
namespace MPIR.Tests
{
internal static class Accessors
internal static class Accessors<T>
{
private static readonly ConstructorInfo _intPtrConstructor;
private static readonly FieldInfo _getValue;
@ -40,45 +40,127 @@ namespace MPIR.Tests
private static FieldInfo GetAccessor(string name)
{
return typeof(HugeInt).GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
return typeof(T).GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
}
public static int NumberOfLimbsAllocated(this HugeInt x)
{
if (x._value() == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)x._value().ToPointer())[0];
}
}
public static int NumberOfLimbsUsed(this HugeInt x)
{
if (x._value() == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)x._value().ToPointer())[1];
}
}
public static IntPtr Limbs(this HugeInt x)
{
if (x._value() == IntPtr.Zero)
return IntPtr.Zero;
unsafe
{
return new IntPtr(((void**)x._value().ToPointer())[1]);
}
}
public static IntPtr _value(this HugeInt x)
internal static IntPtr _value(T x)
{
return (IntPtr)_intPtrConstructor.Invoke(new object[] { _getValue.GetValue(x) });
}
}
internal static class IntAccessors
{
internal static IntPtr _value(this HugeInt x)
{
return Accessors<HugeInt>._value(x);
}
internal static int NumberOfLimbsAllocated(this HugeInt x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[0];
}
}
internal static int NumberOfLimbsUsed(this HugeInt x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[1];
}
}
internal static IntPtr Limbs(this HugeInt x)
{
if (_value(x) == IntPtr.Zero)
return IntPtr.Zero;
unsafe
{
return new IntPtr(((void**)_value(x).ToPointer())[1]);
}
}
}
internal static class RationalAccessors
{
internal static IntPtr _value(this HugeRational x)
{
return Accessors<HugeRational>._value(x);
}
internal static int NumeratorNumberOfLimbsAllocated(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[0];
}
}
internal static int NumeratorNumberOfLimbsUsed(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[1];
}
}
internal static IntPtr NumeratorLimbs(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return IntPtr.Zero;
unsafe
{
return new IntPtr(((void**)_value(x).ToPointer())[1]);
}
}
internal static int DenominatorNumberOfLimbsAllocated(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[4];
}
}
internal static int DenominatorNumberOfLimbsUsed(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return 0;
unsafe
{
return ((int*)_value(x).ToPointer())[5];
}
}
internal static IntPtr DenominatorLimbs(this HugeRational x)
{
if (_value(x) == IntPtr.Zero)
return IntPtr.Zero;
unsafe
{
return new IntPtr(((void**)_value(x).ToPointer())[3]);
}
}
}
}

View File

@ -19,104 +19,134 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
#pragma once
#define DEFINE_ASSIGNMENT_PROLOG(name) void Mpir##name##Expression::AssignTo(mpz_ptr destination)
#pragma region misc macros
#define DEFINE_UNARY_ASSIGNMENT_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr) \
{ \
Operand->AssignTo(destination); \
operation(destination, destination); \
}
#define LIT2(x) x
#define LIT(x) LIT2(x)
#define IS_NULL(a) (Object::ReferenceEquals(a, nullptr))
#define PIN(x) pin_ptr<T> pinptr##x = &x[0]; void* pinned_##x = pinptr##x;
#define DEFINE_UNARY_ASSIGNMENT_VAL(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr) \
{ \
operation(destination, Operand); \
}
#define IN_CONTEXT_1(a) \
EvaluationContext context; \
a->AssignTo(context)
#define DEFINE_BINARY_ASSIGNMENT_REF_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr##typeAbbr) \
{ \
IN_CONTEXT(Left, Right); \
operation(destination, context.Args[0], context.Args[1]); \
}
#define IN_CONTEXT_2(a, b) \
EvaluationContext context; \
a->AssignTo(context); \
b->AssignTo(context)
#define DEFINE_BINARY_ASSIGNMENT_REF_VAL(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Left->AssignTo(destination); \
operation(destination, destination, Right); \
}
#define IN_CONTEXT_3(a, b, c) \
EvaluationContext context; \
a->AssignTo(context); \
b->AssignTo(context); \
c->AssignTo(context)
#define DEFINE_BINARY_ASSIGNMENT_VAL_REF(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Right->AssignTo(destination); \
operation(destination, Left, destination); \
}
#define COUNT_ARGS_IMPL2(_1, _2, _3, name, ...) name
#define COUNT_ARGS_IMPL(args) COUNT_ARGS_IMPL2 args
#define COUNT_ARGS(...) COUNT_ARGS_IMPL((__VA_ARGS__, 3, 2, 1))
#define MACRO_CHOOSE2(prefix, number) prefix##number
#define MACRO_CHOOSE1(prefix, number) MACRO_CHOOSE2(prefix, number)
#define MACRO_CHOOSE(prefix, number) MACRO_CHOOSE1(prefix, number)
#define MACRO_GLUE(x, y) x y
#define IN_CONTEXT(...) MACRO_GLUE(MACRO_CHOOSE(IN_CONTEXT_, COUNT_ARGS(__VA_ARGS__)), (__VA_ARGS__))
#define DEFINE_BINARY_ASSIGNMENT_VAL_VAL(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
operation(destination, Left, Right); \
}
#define TYPE_FOR_ABBR_Int HugeInt^
#define TYPE_FOR_ABBR_Expr IntegerExpression^
#define TYPE_FOR_ABBR_Si mpir_si
#define TYPE_FOR_ABBR_Ui mpir_ui
#define TYPE_FOR_ABBR_Bits mp_bitcnt_t
#define TYPE_FOR_ABBR_Rnd MpirRandom^
#define DEFINE_BINARY_ASSIGNMENT_REF_SI(name, leftTypeAbbr, rightTypeAbbr, positiveOp, negativeOp) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Left->AssignTo(destination); \
if (Right >= 0) \
positiveOp(destination, destination, (mpir_ui)Right); \
else \
negativeOp(destination, destination, (mpir_ui)-Right); \
}
#pragma endregion
#define DEFINE_BINARY_ASSIGNMENT_SI_REF(name, leftTypeAbbr, rightTypeAbbr, positiveOp, negativeOp1, negativeOp2) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Right->AssignTo(destination); \
if (Left >= 0) \
positiveOp(destination, (mpir_ui)Left, destination); \
else \
{ \
negativeOp1(destination, destination, (mpir_ui)-Left); \
negativeOp2(destination, destination); \
} \
}
#pragma region enums
#define DEFINE_TERNARY_ASSIGNMENT_REF_REF_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr##typeAbbr##typeAbbr) \
{ \
IN_CONTEXT(Left, Middle, Right); \
operation(destination, context.Args[0], context.Args[1], context.Args[2]); \
}
namespace MPIR
{
/// <summary>
/// This enum defines the rounding modes MPIR supports. Division and modulo operations take an optional rounding mode parameter, or use the default, which is set in the static MpirSettings class.
/// </summary>
public enum class RoundingModes
{
/// <summary>Rounding mode is unspecified. Use a higher level default if available, fall back to Truncate.</summary>
Default,
/// <summary>Truncate. Quotient is rounded toward zero, and remainder has the same sign as the source number.</summary>
Truncate,
/// <summary>Round up. Quotient is rounded toward +infinity, and remainder has the opposite sign to the divisor.</summary>
Ceiling,
/// <summary>Round down. Quotient is rounded toward -infinity, and remainder has the sames sign as the divisor.</summary>
Floor,
};
#define DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(name, leftT, middleT, rightT, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftT##middleT##rightT) \
{ \
IN_CONTEXT(Left, Right); \
operation(destination, context.Args[0], Middle, context.Args[1]); \
}
/// <summary>
/// This enum defines the limb order used when importing or exporting a number.
/// </summary>
public enum class LimbOrder : __int8
{
/// <summary>Most significant limb comes first.</summary>
MostSignificantFirst = 1,
/// <summary>Least significant limb comes first.</summary>
LeastSignificantFirst = -1,
};
enum EvaluationOptions : __int8
/// <summary>
/// This enum defines the byte order within each limb when importing or exporting a number.
/// </summary>
public enum class Endianness : __int8
{
/// <summary>The native byte order of the CPU is used.</summary>
Native = 0,
/// <summary>Most significant byte comes first in a limb.</summary>
BigEndian = 1,
/// <summary>Least significant byte comes first in a limb.</summary>
LittleEndian = -1,
};
}
enum EvaluationOptions : __int32
{
None = 0x0,
Temp1Initialized = 0x1,
Temp2Initialized = 0x2,
Temp3Initialized = 0x4,
IntInitialized = 0x1,
Temp1InitializedInt = IntInitialized,
Temp2InitializedInt = IntInitialized << 1,
Temp3InitializedInt = IntInitialized << 2,
RationalInitialized = 0x10,
Temp1InitializedRational = RationalInitialized,
Temp2InitializedRational = RationalInitialized << 1,
Temp3InitializedRational = RationalInitialized << 2,
FloatInitialized = 0x100,
Temp1InitializedFloat = FloatInitialized,
Temp2InitializedFloat = FloatInitialized << 1,
Temp3InitializedFloat = FloatInitialized << 2,
};
#pragma endregion
struct EvaluationContext
{
public:
__mpz_struct Temp[3];
mpz_ptr Args[3];
union
{
__mpz_struct Integer;
__mpq_struct Rational;
__mpf_struct Float;
}
Temp[3];
union
{
mpz_ptr IntArgs[3];
mpq_ptr RationalArgs[3];
mpf_ptr FloatArgs[3];
};
union
{
struct
{
unsigned __int8 Index;
EvaluationOptions Options;
unsigned __int8 Index;
};
__int64 Zero;
};
@ -128,11 +158,25 @@ struct EvaluationContext
~EvaluationContext()
{
if(Options & EvaluationOptions::Temp1Initialized)
mpz_clear(Args[0]);
if(Options & EvaluationOptions::Temp2Initialized)
mpz_clear(Args[1]);
if(Options & EvaluationOptions::Temp3Initialized)
mpz_clear(Args[2]);
if(Options & EvaluationOptions::Temp1InitializedInt)
mpz_clear(IntArgs[0]);
if(Options & EvaluationOptions::Temp2InitializedInt)
mpz_clear(IntArgs[1]);
if(Options & EvaluationOptions::Temp3InitializedInt)
mpz_clear(IntArgs[2]);
if(Options & EvaluationOptions::Temp1InitializedRational)
mpq_clear(RationalArgs[0]);
if(Options & EvaluationOptions::Temp2InitializedRational)
mpq_clear(RationalArgs[1]);
if(Options & EvaluationOptions::Temp3InitializedRational)
mpq_clear(RationalArgs[2]);
if(Options & EvaluationOptions::Temp1InitializedFloat)
mpf_clear(FloatArgs[0]);
if(Options & EvaluationOptions::Temp2InitializedFloat)
mpf_clear(FloatArgs[1]);
if(Options & EvaluationOptions::Temp3InitializedFloat)
mpf_clear(FloatArgs[2]);
}
};

View File

@ -0,0 +1,259 @@
/*
Copyright 2014 Alex Dyachenko
This file is part of the MPIR Library.
The MPIR Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
The MPIR Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
*/
#pragma region Expression macros
//defines a unary expression class
#define DEFINE_UNARY_EXPRESSION(base, name, type) \
private ref class MPEXPR(name) : base \
{ \
internal: \
type Operand; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(type operand) \
{ \
Operand = operand; \
} \
};
//defines a binary expression class
#define DEFINE_BINARY_EXPRESSION(base, name, leftType, rightType) \
private ref class MPEXPR(name) : base \
{ \
internal: \
leftType Left; \
rightType Right; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(leftType left, rightType right) \
{ \
Left = left; \
Right = right; \
} \
};
//defines a ternary expression class
#define DEFINE_TERNARY_EXPRESSION(base, name, leftType, middleType, rightType) \
private ref class MPEXPR(name) : base \
{ \
internal: \
leftType Left; \
middleType Middle; \
rightType Right; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(leftType left, middleType middle, rightType right) \
{ \
Left = left; \
Middle = middle; \
Right = right; \
} \
};
//unary expressions
#define DEFINE_UNARY_EXPRESSION_WITH_ONE(base, name, typeAbbr) \
DEFINE_UNARY_EXPRESSION(base, name##typeAbbr, MPEXPR_NAME^)
#define DEFINE_UNARY_EXPRESSION_WITH_BUILT_INS_ONLY(base, name, typeAbbr) \
DEFINE_UNARY_EXPRESSION(base, name##typeAbbr, TYPE_FOR_ABBR_##typeAbbr)
//binary expressions
#define DEFINE_BINARY_EXPRESSION_WITH_BUILT_INS_ONLY(base, name, leftTypeAbbr, rightTypeAbbr) \
DEFINE_BINARY_EXPRESSION(base, name##leftTypeAbbr##rightTypeAbbr, TYPE_FOR_ABBR_##leftTypeAbbr, TYPE_FOR_ABBR_##rightTypeAbbr)
#define DEFINE_BINARY_EXPRESSION_WITH_TWO(base, name, typeAbbr) \
DEFINE_BINARY_EXPRESSION(base, name##typeAbbr##typeAbbr, MPEXPR_NAME^, MPEXPR_NAME^)
#define DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_RIGHT(base, name, leftTypeAbbr, rightTypeAbbr) \
DEFINE_BINARY_EXPRESSION(base, name##leftTypeAbbr##rightTypeAbbr, MPEXPR_NAME^, TYPE_FOR_ABBR_##rightTypeAbbr)
#define DEFINE_BINARY_EXPRESSION_WITH_BUILT_IN_LEFT(base, name, leftTypeAbbr, rightTypeAbbr) \
DEFINE_BINARY_EXPRESSION(base, name##leftTypeAbbr##rightTypeAbbr, TYPE_FOR_ABBR_##leftTypeAbbr, MPEXPR_NAME^)
//ternary expressions
#define DEFINE_TERNARY_EXPRESSION_WITH_THREE(base, name, typeAbbr) \
DEFINE_TERNARY_EXPRESSION(base, name##typeAbbr##typeAbbr##typeAbbr, MPEXPR_NAME^, MPEXPR_NAME^, MPEXPR_NAME^)
#define DEFINE_TERNARY_EXPRESSION_WITH_BUILT_IN_MIDDLE(base, name, leftTypeAbbr, middleTypeAbbr, rightTypeAbbr) \
DEFINE_TERNARY_EXPRESSION(base, name##leftTypeAbbr##middleTypeAbbr##rightTypeAbbr, MPEXPR_NAME^, TYPE_FOR_ABBR_##middleTypeAbbr, MPEXPR_NAME^)
#pragma endregion
#pragma region Method macros
//void functions
#define MAKE_VOID_FUNCTION(base, action, op, type) \
MAKE_VOID_FUNCTION_##action(base, op, op##type)
#define MAKE_VOID_FUNCTION_DECLARE(base, op, result) \
base^ op();
#define MAKE_VOID_FUNCTION_DEFINE(base, op, result) \
base^ MPEXPR_NAME::op() { return gcnew MPEXPR(result)(this); }
//one-arg functions
#define MAKE_FUNCTION_WITH_ONE(base, action, op, argTypeAbbr) \
MAKE_FUNCTION_WITH_ONE_##action(base, op, Expr, op##Int##argTypeAbbr)
#define MAKE_FUNCTION_WITH_LIMB(base, action, op, argTypeAbbr) \
MAKE_FUNCTION_WITH_ONE_##action(base, op, argTypeAbbr, op##Int##argTypeAbbr)
#define MAKE_FUNCTION_WITH_ONE_DECLARE(base, op, argTypeAbbr, result) \
base^ op(TYPE_FOR_ABBR_##argTypeAbbr a);
#define MAKE_FUNCTION_WITH_ONE_DEFINE(base, op, argTypeAbbr, result) \
base^ MPEXPR_NAME::op(TYPE_FOR_ABBR_##argTypeAbbr a) { return gcnew MPEXPR(result)(this, a); }
//two-arg functions
#define MAKE_FUNCTION_WITH_TWO(base, action, op, leftTypeAbbr, rightTypeAbbr) \
MAKE_FUNCTION_WITH_TWO_##action(base, op, Expr, Expr, op##Int##leftTypeAbbr##rightTypeAbbr)
#define MAKE_FUNCTION_WITH_TWO_LLIMB(base, action, op, leftTypeAbbr, rightTypeAbbr) \
MAKE_FUNCTION_WITH_TWO_##action(base, op, leftTypeAbbr, Expr, op##Int##leftTypeAbbr##rightTypeAbbr)
#define MAKE_FUNCTION_WITH_TWO_DECLARE(base, op, leftTypeAbbr, rightTypeAbbr, result) \
base^ op(TYPE_FOR_ABBR_##leftTypeAbbr a, TYPE_FOR_ABBR_##rightTypeAbbr b);
#define MAKE_FUNCTION_WITH_TWO_DEFINE(base, op, leftTypeAbbr, rightTypeAbbr, result) \
base^ MPEXPR_NAME::op(TYPE_FOR_ABBR_##leftTypeAbbr a, TYPE_FOR_ABBR_##rightTypeAbbr b) { return gcnew MPEXPR(result)(this, a, b); }
//functions with one argument and simple result
//#define MAKE_SIMPLE_FUNCTION_WITH_ONE(base, action, op, resultType, argType) \
// MAKE_SIMPLE_FUNCTION_WITH_ONE_##action(base, op, resultType, Expr)
//
//#define MAKE_SIMPLE_FUNCTION_WITH_LIMB(base, action, op, resultType, argType) \
// MAKE_SIMPLE_FUNCTION_WITH_ONE_##action(base, op, resultType, argType)
//
//#define MAKE_SIMPLE_FUNCTION_WITH_ONE_DECLARE(base, op, resultTypeAbbr, argTypeAbbr) \
// TYPE_FOR_ABBR_##resultTypeAbbr op(TYPE_FOR_ABBR_##argTypeAbbr a);
//
//#define MAKE_SIMPLE_FUNCTION_WITH_ONE_DEFINE(base, op, resultTypeAbbr, argTypeAbbr) \
// TYPE_FOR_ABBR_##resultTypeAbbr HugeInt::op(TYPE_FOR_ABBR_##argTypeAbbr a) { return gcnew LIT(MPTYPE_NAME)result##Expression(this, a); }
//unary operators
#define MAKE_UNARY_OPERATOR(base, action, op, result, mpType) \
MAKE_UNARY_OPERATOR_##action(base, op, result##mpType, Expr)
#define MAKE_UNARY_OPERATOR_DECLARE(base, op, result, type) \
static base^ operator op(TYPE_FOR_ABBR_##type a);
#define MAKE_UNARY_OPERATOR_DEFINE(base, op, result, type) \
base^ MPEXPR_NAME::operator op(TYPE_FOR_ABBR_##type a) { return gcnew MPEXPR(result)(a); }
//binary operators
#define MAKE_BINARY_OPERATOR_DECLARE(base, op, result, leftType, rightType, left, right) \
static base^ operator op(TYPE_FOR_ABBR_##leftType a, TYPE_FOR_ABBR_##rightType b);
#define MAKE_BINARY_OPERATOR_DEFINE(base, op, result, leftType, rightType, left, right) \
base^ MPEXPR_NAME::operator op(TYPE_FOR_ABBR_##leftType a, TYPE_FOR_ABBR_##rightType b) { return gcnew MPEXPR(result)(left, right); }
#define MAKE_BINARY_OPERATOR_STANDARD(base, action, op, result, leftType, rightType) \
MAKE_BINARY_OPERATOR_##action(base, op, result##leftType##rightType, Expr, Expr, a, b)
#define MAKE_BINARY_OPERATOR_RLIMB(base, action, op, result, mpType, limbType) \
MAKE_BINARY_OPERATOR_##action(base, op, result##mpType##limbType, Expr, limbType, a, b)
#define MAKE_BINARY_OPERATOR_LLIMB(base, action, op, result, mpType, limbType) \
MAKE_BINARY_OPERATOR_##action(base, op, result##limbType##mpType, limbType, Expr, a, b)
#define MAKE_BINARY_OPERATOR_LLIMB_R(base, action, op, result, mpType, limbType) \
MAKE_BINARY_OPERATOR_##action(base, op, result##mpType##limbType, limbType, Expr, b, a)
#pragma endregion
#pragma region expression assignment macros
#define DEFINE_ASSIGNMENT_PROLOG(name) void MPEXPR(name)::AssignTo(MP(ptr) destination)
#define DEFINE_UNARY_ASSIGNMENT_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr) \
{ \
Operand->AssignTo(destination); \
operation(destination, destination); \
}
#define DEFINE_UNARY_ASSIGNMENT_VAL(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr) \
{ \
operation(destination, Operand); \
}
#define DEFINE_BINARY_ASSIGNMENT_REF_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr##typeAbbr) \
{ \
IN_CONTEXT(Left, Right); \
operation(destination, CTXT(0), CTXT(1)); \
}
#define DEFINE_BINARY_ASSIGNMENT_REF_VAL(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Left->AssignTo(destination); \
operation(destination, destination, Right); \
}
#define DEFINE_BINARY_ASSIGNMENT_VAL_REF(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Right->AssignTo(destination); \
operation(destination, Left, destination); \
}
#define DEFINE_BINARY_ASSIGNMENT_VAL_VAL(name, leftTypeAbbr, rightTypeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
operation(destination, Left, Right); \
}
#define DEFINE_BINARY_ASSIGNMENT_REF_SI(name, leftTypeAbbr, rightTypeAbbr, positiveOp, negativeOp) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Left->AssignTo(destination); \
if (Right >= 0) \
positiveOp(destination, destination, (mpir_ui)Right); \
else \
negativeOp(destination, destination, (mpir_ui)-Right); \
}
#define DEFINE_BINARY_ASSIGNMENT_SI_REF(name, leftTypeAbbr, rightTypeAbbr, positiveOp, negativeOp1, negativeOp2) \
DEFINE_ASSIGNMENT_PROLOG(name##leftTypeAbbr##rightTypeAbbr) \
{ \
Right->AssignTo(destination); \
if (Left >= 0) \
positiveOp(destination, (mpir_ui)Left, destination); \
else \
{ \
negativeOp1(destination, destination, (mpir_ui)-Left); \
negativeOp2(destination, destination); \
} \
}
#define DEFINE_TERNARY_ASSIGNMENT_REF_REF_REF(name, typeAbbr, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##typeAbbr##typeAbbr##typeAbbr) \
{ \
IN_CONTEXT(Left, Middle, Right); \
operation(destination, CTXT(0), CTXT(1), CTXT(2)); \
}
#define DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(name, leftT, middleT, rightT, operation) \
DEFINE_ASSIGNMENT_PROLOG(name##leftT##middleT##rightT) \
{ \
IN_CONTEXT(Left, Right); \
operation(destination, CTXT(0), Middle, CTXT(1)); \
}
#pragma endregion

View File

@ -18,6 +18,7 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
*/
#include "Stdafx.h"
#include "HugeInt.h"
#include "Random.h"
using namespace System::Runtime::InteropServices;
@ -30,38 +31,38 @@ namespace MPIR
void MpirSettings::ToStringDigits::set(int value)
{
_toStringDigits = value;
_toStringModulo = gcnew HugeInt(HugeInt::Power(10, value));
_toStringModulo = gcnew MPTYPE(MPTYPE::Power(10, value));
}
#pragma endregion
#pragma region construction
HugeInt::HugeInt()
MPTYPE::MPTYPE()
{
AllocateStruct();
mpz_init(_value);
MP(init)(_value);
}
HugeInt::HugeInt(IntegerExpression^ value)
MPTYPE::MPTYPE(MPEXPR_NAME^ value)
{
AllocateStruct();
mpz_init(_value);
MP(init)(_value);
value->AssignTo(_value);
}
HugeInt::HugeInt(mp_bitcnt_t bits)
MPTYPE::MPTYPE(mp_bitcnt_t bits)
{
AllocateStruct();
mpz_init2(_value, bits);
MP(init2)(_value, bits);
}
void HugeInt::FromString(String^ value, int base)
void MPTYPE::FromString(String^ value, int base)
{
AllocateStruct();
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
bool success = 0 == mpz_init_set_str(_value, (char*)(void*)ptr, base);
bool success = 0 == MP(init_set_str)(_value, (char*)(void*)ptr, base);
Marshal::FreeHGlobal(ptr);
if(!success)
@ -71,34 +72,34 @@ namespace MPIR
}
}
void HugeInt::SetTo(String^ value, int base)
void MPTYPE::SetTo(String^ value, int base)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
bool success = 0 == mpz_set_str(_value, (char*)(void*)ptr, base);
bool success = 0 == MP(set_str)(_value, (char*)(void*)ptr, base);
Marshal::FreeHGlobal(ptr);
if(!success)
throw gcnew ArgumentException("Invalid number", "value");
}
HugeInt^ HugeInt::FromLong(mpir_si value)
MPTYPE^ MPTYPE::FromLong(mpir_si value)
{
auto result = gcnew HugeInt();
mpz_set_si(result->_value, value);
auto result = gcnew MPTYPE();
MP(set_si)(result->_value, value);
return result;
}
HugeInt^ HugeInt::FromUlong(mpir_ui value)
MPTYPE^ MPTYPE::FromUlong(mpir_ui value)
{
auto result = gcnew HugeInt();
mpz_set_ui(result->_value, value);
auto result = gcnew MPTYPE();
MP(set_ui)(result->_value, value);
return result;
}
HugeInt^ HugeInt::FromDouble(double value)
MPTYPE^ MPTYPE::FromDouble(double value)
{
auto result = gcnew HugeInt();
mpz_set_d(result->_value, value);
auto result = gcnew MPTYPE();
MP(set_d)(result->_value, value);
return result;
}
@ -106,7 +107,7 @@ namespace MPIR
#pragma region object overrides
String^ HugeInt::ToString(int base, bool lowercase, int maxDigits)
String^ MPTYPE::ToString(int base, bool lowercase, int maxDigits)
{
size_t allocated;
bool negative = false;
@ -123,7 +124,7 @@ namespace MPIR
else
{
AssignTo(context);
allocated = mpz_sizeinbase(_value, base == 0 ? 10 : base) + 2;
allocated = MP(sizeinbase)(_value, base == 0 ? 10 : base) + 2;
}
char* allocatedStr = (char*)(*__gmp_allocate_func)(allocated);
@ -138,23 +139,23 @@ namespace MPIR
*str++ = '.';
}
mpz_get_str(str, (base <= 36 && !lowercase) ? -base : base, context.Args[0]);
MP(get_str)(str, (base <= 36 && !lowercase) ? -base : base, CTXT(0));
auto result = gcnew String(allocatedStr);
(*__gmp_free_func)(allocatedStr, allocated);
return result;
}
int IntegerExpression::GetHashCode()
int MPEXPR_NAME::GetHashCode()
{
IN_CONTEXT(this);
mp_limb_t hash = 0;
mp_limb_t* ptr = context.Args[0]->_mp_d;
for(int i = abs(context.Args[0]->_mp_size); i > 0; i--)
mp_limb_t* ptr = CTXT(0)->_mp_d;
for(int i = abs(CTXT(0)->_mp_size); i > 0; i--)
hash ^= *ptr++;
if(context.Args[0]->_mp_size < 0)
if(CTXT(0)->_mp_size < 0)
hash = (mp_limb_t)-(mpir_si)hash;
return hash.GetHashCode();
@ -164,14 +165,14 @@ namespace MPIR
#pragma region Interface implementations
int IntegerExpression::CompareTo(Object^ a, bool& valid)
int MPEXPR_NAME::CompareTo(Object^ a, bool& valid)
{
valid = true;
if (IS_NULL(a))
return 1;
IntegerExpression^ expr = dynamic_cast<IntegerExpression^>(a);
MPEXPR_NAME^ expr = dynamic_cast<MPEXPR_NAME^>(a);
if(!IS_NULL(expr))
return CompareTo(expr);
@ -180,26 +181,26 @@ namespace MPIR
if(a->GetType() == mpir_ui::typeid)
{
AssignTo(context);
return mpz_cmp_ui(context.Args[0], (mpir_ui)a);
return MP(cmp_ui)(CTXT(0), (mpir_ui)a);
}
if(a->GetType() == mpir_si::typeid)
{
AssignTo(context);
return mpz_cmp_si(context.Args[0], (mpir_si)a);
return MP(cmp_si)(CTXT(0), (mpir_si)a);
}
if(a->GetType() == double::typeid)
{
AssignTo(context);
return mpz_cmp_d(context.Args[0], (double)a);
return MP(cmp_d)(CTXT(0), (double)a);
}
valid = false;
return 0;
}
int IntegerExpression::CompareTo(Object^ a)
int MPEXPR_NAME::CompareTo(Object^ a)
{
bool valid;
auto result = CompareTo(a, valid);
@ -210,16 +211,16 @@ namespace MPIR
throw gcnew ArgumentException("Invalid argument type", "a");
}
int IntegerExpression::CompareTo(IntegerExpression^ a)
int MPEXPR_NAME::CompareTo(MPEXPR_NAME^ a)
{
if (IS_NULL(a))
return 1;
IN_CONTEXT(this, a);
return mpz_cmp(context.Args[0], context.Args[1]);
return MP(cmp)(CTXT(0), CTXT(1));
}
bool IntegerExpression::Equals(Object^ a)
bool MPEXPR_NAME::Equals(Object^ a)
{
bool valid;
auto result = CompareTo(a, valid);
@ -227,7 +228,7 @@ namespace MPIR
return valid && result == 0;
}
bool IntegerExpression::Equals(IntegerExpression^ a)
bool MPEXPR_NAME::Equals(MPEXPR_NAME^ a)
{
return CompareTo(a) == 0;
}
@ -236,31 +237,31 @@ namespace MPIR
#pragma region expression special cases
void IntegerDivideExpression::custom_mpz_div(mpz_ptr q, mpz_srcptr n, mpz_srcptr d)
void MPEXPR(Divide)::CUSTOM_MP(div)(MP(ptr) q, MP(srcptr) n, MP(srcptr) d)
{
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
IS_NULL(_remainder)
? mpz_fdiv_q(q, n, d)
: mpz_fdiv_qr(q, _remainder->_value, n, d);
? MP(fdiv_q)(q, n, d)
: MP(fdiv_qr)(q, _remainder->_value, n, d);
break;
case RoundingModes::Ceiling:
IS_NULL(_remainder)
? mpz_cdiv_q(q, n, d)
: mpz_cdiv_qr(q, _remainder->_value, n, d);
? MP(cdiv_q)(q, n, d)
: MP(cdiv_qr)(q, _remainder->_value, n, d);
break;
default:
IS_NULL(_remainder)
? mpz_tdiv_q(q, n, d)
: mpz_tdiv_qr(q, _remainder->_value, n, d);
? MP(tdiv_q)(q, n, d)
: MP(tdiv_qr)(q, _remainder->_value, n, d);
break;
}
}
void IntegerDivideUiExpression::custom_mpz_div_ui(mpz_ptr q, mpz_srcptr n, mpir_ui d)
void MPEXPR(DivideUi)::CUSTOM_MP(div_ui)(MP(ptr) q, MP(srcptr) n, mpir_ui d)
{
mpir_ui limb;
@ -268,20 +269,20 @@ namespace MPIR
{
case RoundingModes::Floor:
limb = IS_NULL(_remainder)
? mpz_fdiv_q_ui(q, n, d)
: mpz_fdiv_qr_ui(q, _remainder->_value, n, d);
? MP(fdiv_q_ui)(q, n, d)
: MP(fdiv_qr_ui)(q, _remainder->_value, n, d);
break;
case RoundingModes::Ceiling:
limb = IS_NULL(_remainder)
? mpz_cdiv_q_ui(q, n, d)
: mpz_cdiv_qr_ui(q, _remainder->_value, n, d);
? MP(cdiv_q_ui)(q, n, d)
: MP(cdiv_qr_ui)(q, _remainder->_value, n, d);
break;
default:
limb = IS_NULL(_remainder)
? mpz_tdiv_q_ui(q, n, d)
: mpz_tdiv_qr_ui(q, _remainder->_value, n, d);
? MP(tdiv_q_ui)(q, n, d)
: MP(tdiv_qr_ui)(q, _remainder->_value, n, d);
break;
}
@ -289,55 +290,55 @@ namespace MPIR
_limbRemainder(limb);
}
void IntegerShiftRightExpression::custom_mpz_div_2exp(mpz_ptr q, mpz_srcptr n, mp_bitcnt_t d)
void MPEXPR(ShiftRight)::CUSTOM_MP(div_2exp)(MP(ptr) q, MP(srcptr) n, mp_bitcnt_t d)
{
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
_remainder
? mpz_fdiv_r_2exp(q, n, d)
: mpz_fdiv_q_2exp(q, n, d);
? MP(fdiv_r_2exp)(q, n, d)
: MP(fdiv_q_2exp)(q, n, d);
break;
case RoundingModes::Ceiling:
_remainder
? mpz_cdiv_r_2exp(q, n, d)
: mpz_cdiv_q_2exp(q, n, d);
? MP(cdiv_r_2exp)(q, n, d)
: MP(cdiv_q_2exp)(q, n, d);
break;
default:
_remainder
? mpz_tdiv_r_2exp(q, n, d)
: mpz_tdiv_q_2exp(q, n, d);
? MP(tdiv_r_2exp)(q, n, d)
: MP(tdiv_q_2exp)(q, n, d);
break;
}
}
void IntegerModExpression::custom_mpz_mod(mpz_ptr r, mpz_srcptr n, mpz_srcptr d)
void MPEXPR(Mod)::CUSTOM_MP(mod)(MP(ptr) r, MP(srcptr) n, MP(srcptr) d)
{
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
IS_NULL(_quotient)
? mpz_fdiv_r(r, n, d)
: mpz_fdiv_qr(_quotient->_value, r, n, d);
? MP(fdiv_r)(r, n, d)
: MP(fdiv_qr)(_quotient->_value, r, n, d);
break;
case RoundingModes::Ceiling:
IS_NULL(_quotient)
? mpz_cdiv_r(r, n, d)
: mpz_cdiv_qr(_quotient->_value, r, n, d);
? MP(cdiv_r)(r, n, d)
: MP(cdiv_qr)(_quotient->_value, r, n, d);
break;
default:
IS_NULL(_quotient)
? mpz_tdiv_r(r, n, d)
: mpz_tdiv_qr(_quotient->_value, r, n, d);
? MP(tdiv_r)(r, n, d)
: MP(tdiv_qr)(_quotient->_value, r, n, d);
break;
}
}
void IntegerModUiExpression::custom_mpz_mod_ui(mpz_ptr r, mpz_srcptr n, mpir_ui d)
void MPEXPR(ModUi)::CUSTOM_MP(mod_ui)(MP(ptr) r, MP(srcptr) n, mpir_ui d)
{
mpir_ui limb;
@ -345,20 +346,20 @@ namespace MPIR
{
case RoundingModes::Floor:
limb = IS_NULL(_quotient)
? mpz_fdiv_r_ui(r, n, d)
: mpz_fdiv_qr_ui(_quotient->_value, r, n, d);
? MP(fdiv_r_ui)(r, n, d)
: MP(fdiv_qr_ui)(_quotient->_value, r, n, d);
break;
case RoundingModes::Ceiling:
limb = IS_NULL(_quotient)
? mpz_cdiv_r_ui(r, n, d)
: mpz_cdiv_qr_ui(_quotient->_value, r, n, d);
? MP(cdiv_r_ui)(r, n, d)
: MP(cdiv_qr_ui)(_quotient->_value, r, n, d);
break;
default:
limb = IS_NULL(_quotient)
? mpz_tdiv_r_ui(r, n, d)
: mpz_tdiv_qr_ui(_quotient->_value, r, n, d);
? MP(tdiv_r_ui)(r, n, d)
: MP(tdiv_qr_ui)(_quotient->_value, r, n, d);
break;
}
@ -366,41 +367,41 @@ namespace MPIR
_limbRemainder(limb);
}
void IntegerRootExpression::custom_mpz_root(mpz_ptr dest, mpz_srcptr oper, mpir_ui power)
void MPEXPR(Root)::CUSTOM_MP(root)(MP(ptr) dest, MP(srcptr) oper, mpir_ui power)
{
if(!IS_NULL(_remainder))
mpz_rootrem(dest, _remainder->_value, oper, power);
MP(rootrem)(dest, _remainder->_value, oper, power);
else if (IS_NULL(_exact))
mpz_nthroot(dest, oper, power);
MP(nthroot)(dest, oper, power);
else
_exact(mpz_root(dest, oper, power) != 0);
_exact(MP(root)(dest, oper, power) != 0);
}
void IntegerSquareRootExpression::custom_mpz_sqrt(mpz_ptr dest, mpz_srcptr oper)
void MPEXPR(SquareRoot)::CUSTOM_MP(sqrt)(MP(ptr) dest, MP(srcptr) oper)
{
IS_NULL(_remainder)
? mpz_sqrt(dest, oper)
: mpz_sqrtrem(dest, _remainder->_value, oper);
? MP(sqrt)(dest, oper)
: MP(sqrtrem)(dest, _remainder->_value, oper);
}
void IntegerGcdExpression::custom_mpz_gcd(mpz_ptr dest, mpz_srcptr a, mpz_srcptr b)
void MPEXPR(Gcd)::CUSTOM_MP(gcd)(MP(ptr) dest, MP(srcptr) a, MP(srcptr) b)
{
switch ((IS_NULL(_s) ? 0 : 1) + (IS_NULL(_t) ? 0 : 2))
{
case 0:
mpz_gcd(dest, a, b);
MP(gcd)(dest, a, b);
break;
case 1:
mpz_gcdext(dest, _s->_value, NULL, a, b);
MP(gcdext)(dest, _s->_value, NULL, a, b);
break;
case 2:
mpz_gcdext(dest, _t->_value, NULL, b, a);
MP(gcdext)(dest, _t->_value, NULL, b, a);
break;
case 3:
mpz_gcdext(dest, _s->_value, _t->_value, a, b);
MP(gcdext)(dest, _s->_value, _t->_value, a, b);
break;
}
}
@ -409,67 +410,112 @@ namespace MPIR
#pragma region Arithmetic
DEFINE_OPERATIONS(DEFINE)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, +, Add, Int, Int)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, +, Add, Int, Ui)
MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, +, Add, Int, Ui)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, +, Add, Int, Si)
MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, +, Add, Int, Si)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, -, Subtract, Int, Int)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Int, Ui)
MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Int, Ui)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Int, Si)
MAKE_BINARY_OPERATOR_LLIMB (MPEXPR_NAME, DEFINE, -, Subtract, Int, Si)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, *, Multiply, Int, Int)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, *, Multiply, Int, Ui)
MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, *, Multiply, Int, Ui)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, *, Multiply, Int, Si)
MAKE_BINARY_OPERATOR_LLIMB_R (MPEXPR_NAME, DEFINE, *, Multiply, Int, Si)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, <<, ShiftLeft, Int, Bits)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR(ShiftRight), DEFINE, >>, ShiftRight, Int, Bits)
MAKE_UNARY_OPERATOR (MPEXPR_NAME, DEFINE, -, Negate, Int)
MAKE_VOID_FUNCTION (MPEXPR_NAME, DEFINE, Abs, Int)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR(Divide), DEFINE, /, Divide, Int, Int)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR(DivideUi), DEFINE, /, Divide, Int, Ui)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR(Mod), DEFINE, %, Mod, Int, Int)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR(ModUi), DEFINE, %, Mod, Int, Ui)
MAKE_BINARY_OPERATOR_RLIMB (MPEXPR_NAME, DEFINE, ^, Power, Int, Ui)
MAKE_FUNCTION_WITH_ONE (MPEXPR_NAME, DEFINE, DivideExactly, Int)
MAKE_FUNCTION_WITH_LIMB (MPEXPR_NAME, DEFINE, DivideExactly, Ui)
MAKE_FUNCTION_WITH_TWO (MPEXPR_NAME, DEFINE, PowerMod, Int, Int)
MAKE_FUNCTION_WITH_TWO_LLIMB (MPEXPR_NAME, DEFINE, PowerMod, Ui, Int)
MAKE_FUNCTION_WITH_LIMB (MPEXPR(Root), DEFINE, Root, Ui)
MAKE_VOID_FUNCTION (MPEXPR(SquareRoot), DEFINE, SquareRoot, Int)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, &, And, Int, Int)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, |, Or, Int, Int)
MAKE_BINARY_OPERATOR_STANDARD (MPEXPR_NAME, DEFINE, ^, Xor, Int, Int)
MAKE_UNARY_OPERATOR (MPEXPR_NAME, DEFINE, ~, Complement, Int)
DEFINE_UNARY_ASSIGNMENT_REF(Complement, Int, mpz_com)
DEFINE_UNARY_ASSIGNMENT_REF(Negate, Int, mpz_neg)
DEFINE_UNARY_ASSIGNMENT_REF(Abs, Int, mpz_abs)
DEFINE_UNARY_ASSIGNMENT_REF(Complement, Int, MP(com))
DEFINE_UNARY_ASSIGNMENT_REF(Negate, Int, MP(neg))
DEFINE_UNARY_ASSIGNMENT_REF(Abs, Int, MP(abs))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Add, Int, mpz_add)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Add, Int, Ui, mpz_add_ui)
DEFINE_BINARY_ASSIGNMENT_REF_SI (Add, Int, Si, mpz_add_ui, mpz_sub_ui)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Add, Int, MP(add))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Add, Int, Ui, MP(add_ui))
DEFINE_BINARY_ASSIGNMENT_REF_SI (Add, Int, Si, MP(add_ui), MP(sub_ui))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Subtract, Int, mpz_sub)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Subtract, Int, Ui, mpz_sub_ui)
DEFINE_BINARY_ASSIGNMENT_VAL_REF(Subtract, Ui, Int, mpz_ui_sub)
DEFINE_BINARY_ASSIGNMENT_REF_SI (Subtract, Int, Si, mpz_sub_ui, mpz_add_ui)
DEFINE_BINARY_ASSIGNMENT_SI_REF (Subtract, Si, Int, mpz_ui_sub, mpz_add_ui, mpz_neg)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Subtract, Int, MP(sub))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Subtract, Int, Ui, MP(sub_ui))
DEFINE_BINARY_ASSIGNMENT_VAL_REF(Subtract, Ui, Int, MP(ui_sub))
DEFINE_BINARY_ASSIGNMENT_REF_SI (Subtract, Int, Si, MP(sub_ui), MP(add_ui))
DEFINE_BINARY_ASSIGNMENT_SI_REF (Subtract, Si, Int, MP(ui_sub), MP(add_ui), MP(neg))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Multiply, Int, mpz_mul)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Multiply, Int, Ui, mpz_mul_ui)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Multiply, Int, Si, mpz_mul_si)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Multiply, Int, MP(mul))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Multiply, Int, Ui, MP(mul_ui))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Multiply, Int, Si, MP(mul_si))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Divide, Int, custom_mpz_div)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Divide, Int, Ui, custom_mpz_div_ui)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Mod, Int, custom_mpz_mod)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Mod, Int, Ui, custom_mpz_mod_ui)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Divide, Int, CUSTOM_MP(div))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Divide, Int, Ui, CUSTOM_MP(div_ui))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Mod, Int, CUSTOM_MP(mod))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Mod, Int, Ui, CUSTOM_MP(mod_ui))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftLeft, Int, Bits, mpz_mul_2exp)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftRight, Int, Bits, custom_mpz_div_2exp)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftLeft, Int, Bits, MP(mul_2exp))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftRight, Int, Bits, CUSTOM_MP(div_2exp))
DEFINE_BINARY_ASSIGNMENT_REF_REF(DivideExactly, Int, mpz_divexact)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(DivideExactly, Int, Ui, mpz_divexact_ui)
DEFINE_BINARY_ASSIGNMENT_REF_REF(DivideExactly, Int, MP(divexact))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(DivideExactly, Int, Ui, MP(divexact_ui))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Power, Int, Ui, mpz_pow_ui)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Power, Int, Ui, MP(pow_ui))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Root, Int, Ui, custom_mpz_root)
DEFINE_UNARY_ASSIGNMENT_REF (SquareRoot, Int, custom_mpz_sqrt)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Root, Int, Ui, CUSTOM_MP(root))
DEFINE_UNARY_ASSIGNMENT_REF (SquareRoot, Int, CUSTOM_MP(sqrt))
DEFINE_BINARY_ASSIGNMENT_REF_REF(And, Int, mpz_and)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Or, Int, mpz_ior)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Xor, Int, mpz_xor)
DEFINE_BINARY_ASSIGNMENT_REF_REF(And, Int, MP(and))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Or, Int, MP(ior))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Xor, Int, MP(xor))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Gcd, Int, custom_mpz_gcd)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Lcm, Int, mpz_lcm)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Lcm, Int, Ui, mpz_lcm_ui)
DEFINE_BINARY_ASSIGNMENT_REF_REF(Gcd, Int, CUSTOM_MP(gcd))
DEFINE_BINARY_ASSIGNMENT_REF_REF(Lcm, Int, MP(lcm))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Lcm, Int, Ui, MP(lcm_ui))
DEFINE_TERNARY_ASSIGNMENT_REF_REF_REF(PowerMod, Int, mpz_powm);
DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(PowerMod, Int, Ui, Int, mpz_powm_ui)
DEFINE_TERNARY_ASSIGNMENT_REF_REF_REF(PowerMod, Int, MP(powm));
DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(PowerMod, Int, Ui, Int, MP(powm_ui))
mpir_ui IntegerExpression::Mod(mpir_ui d, RoundingModes rounding)
mpir_ui MPEXPR_NAME::Mod(mpir_ui d, RoundingModes rounding)
{
IN_CONTEXT(this);
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
return mpz_fdiv_ui(context.Args[0], d);
return MP(fdiv_ui)(CTXT(0), d);
case RoundingModes::Ceiling:
return mpz_cdiv_ui(context.Args[0], d);
return MP(cdiv_ui)(CTXT(0), d);
default:
return mpz_tdiv_ui(context.Args[0], d);
return MP(tdiv_ui)(CTXT(0), d);
}
}
@ -479,10 +525,10 @@ namespace MPIR
#define chunkSize 1024
size_t HugeInt::Write(Stream^ stream)
size_t MPTYPE::Write(Stream^ stream)
{
mpir_out_struct out;
mpz_out_raw_m(out, _value);
MP(out_raw_m)(out, _value);
auto buffer = gcnew array<unsigned char>(chunkSize);
auto ptr = out->written;
@ -502,7 +548,7 @@ namespace MPIR
return out->writtenSize;
}
size_t HugeInt::Read(Stream^ stream)
size_t MPTYPE::Read(Stream^ stream)
{
unsigned char csize_bytes[4];
mpir_out_struct out;
@ -517,7 +563,7 @@ namespace MPIR
csize_bytes[i] = byte;
}
mpz_inp_raw_p(_value, csize_bytes, out);
MP(inp_raw_p)(_value, csize_bytes, out);
if(out->writtenSize != 0)
{
@ -536,20 +582,20 @@ namespace MPIR
toRead -= len;
}
mpz_inp_raw_m(_value, out);
MP(inp_raw_m)(_value, out);
}
return 4 + out->writtenSize;
}
size_t HugeInt::Write(TextWriter^ writer, int base, bool lowercase)
size_t MPTYPE::Write(TextWriter^ writer, int base, bool lowercase)
{
auto str = ToString(base, lowercase);
writer->Write(str);
return str->Length;
}
size_t HugeInt::Read(TextReader^ reader, int base)
size_t MPTYPE::Read(TextReader^ reader, int base)
{
int c;
size_t nread = 0;
@ -570,7 +616,7 @@ namespace MPIR
nread++;
// adapted from inp_str, which is shared by mpq_inp_str
size_t HugeInt::ReadNoWhite(TextReader^ reader, int base, size_t nread)
size_t MPTYPE::ReadNoWhite(TextReader^ reader, int base, size_t nread)
{
char *str;
size_t alloc_size, str_size;
@ -660,7 +706,7 @@ namespace MPIR
xsize = (((mp_size_t)
(str_size / __mp_bases[base].chars_per_bit_exactly))
/ GMP_NUMB_BITS + 2);
MPZ_REALLOC (_value, xsize);
MP(realloc) (_value, xsize);
// Convert the byte array in base BASE to our bignum format.
xsize = mpn_set_str (_value->_mp_d, (unsigned char *) str, str_size, base);
@ -674,80 +720,80 @@ namespace MPIR
#pragma region number-theoretic
bool HugeInt::IsProbablePrime(MpirRandom^ random, int probability, mpir_ui pretested)
bool MPTYPE::IsProbablePrime(MpirRandom^ random, int probability, mpir_ui pretested)
{
return mpz_probable_prime_p(_value, random->_value, probability, pretested) != 0;
return MP(probable_prime_p)(_value, random->_value, probability, pretested) != 0;
}
bool HugeInt::IsLikelyPrime(MpirRandom^ random, mpir_ui pretested)
bool MPTYPE::IsLikelyPrime(MpirRandom^ random, mpir_ui pretested)
{
return mpz_likely_prime_p(_value, random->_value, pretested) != 0;
return MP(likely_prime_p)(_value, random->_value, pretested) != 0;
}
MAKE_FUNCTION_WITH_LIMB (IntegerExpression, DEFINE, NextPrimeCandidate, Rnd)
MAKE_FUNCTION_WITH_LIMB (MPEXPR_NAME, DEFINE, NextPrimeCandidate, Rnd)
DEFINE_ASSIGNMENT_PROLOG(NextPrimeCandidateIntRnd)
{
IN_CONTEXT(Left);
mpz_next_prime_candidate(destination, context.Args[0], Right->_value);
MP(next_prime_candidate)(destination, CTXT(0), Right->_value);
}
MAKE_FUNCTION_WITH_ONE (IntegerGcdExpression, DEFINE, Gcd, Int)
MAKE_FUNCTION_WITH_ONE (IntegerExpression, DEFINE, Lcm, Int)
MAKE_FUNCTION_WITH_LIMB (IntegerExpression, DEFINE, Lcm, Ui)
MAKE_FUNCTION_WITH_ONE (MPEXPR(Gcd), DEFINE, Gcd, Int)
MAKE_FUNCTION_WITH_ONE (MPEXPR_NAME, DEFINE, Lcm, Int)
MAKE_FUNCTION_WITH_LIMB (MPEXPR_NAME, DEFINE, Lcm, Ui)
MAKE_FUNCTION_WITH_ONE (IntegerExpression, DEFINE, Invert, Int)
MAKE_FUNCTION_WITH_ONE (MPEXPR_NAME, DEFINE, Invert, Int)
DEFINE_ASSIGNMENT_PROLOG(InvertIntInt)
{
IN_CONTEXT(Left, Right);
if (mpz_invert(destination, context.Args[0], context.Args[1]) == 0)
if (MP(invert)(destination, CTXT(0), CTXT(1)) == 0)
throw gcnew ArgumentException("Inverse does not exist");
}
MAKE_FUNCTION_WITH_ONE (IntegerRemoveFactorsExpression, DEFINE, RemoveFactors, Int)
MAKE_FUNCTION_WITH_ONE (MPEXPR(RemoveFactors), DEFINE, RemoveFactors, Int)
DEFINE_ASSIGNMENT_PROLOG(RemoveFactorsIntInt)
{
IN_CONTEXT(Left, Right);
auto result = mpz_remove(destination, context.Args[0], context.Args[1]);
auto result = MP(remove)(destination, CTXT(0), CTXT(1));
if(!IS_NULL(_count))
_count(result);
}
DEFINE_BINARY_ASSIGNMENT_VAL_VAL(Power, Ui, Ui, mpz_ui_pow_ui)
DEFINE_BINARY_ASSIGNMENT_VAL_VAL(Power, Ui, Ui, MP(ui_pow_ui))
DEFINE_ASSIGNMENT_PROLOG(FactorialUiUi)
{
switch (Right)
{
case 1:
mpz_fac_ui(destination, Left);
MP(fac_ui)(destination, Left);
break;
case 2:
mpz_2fac_ui(destination, Left);
MP(2fac_ui)(destination, Left);
break;
default:
mpz_mfac_uiui(destination, Left, Right);
MP(mfac_uiui)(destination, Left, Right);
break;
}
}
DEFINE_UNARY_ASSIGNMENT_VAL(Primorial, Ui, mpz_primorial_ui)
DEFINE_BINARY_ASSIGNMENT_VAL_VAL(Binomial, Ui, Ui, mpz_bin_uiui)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Binomial, Int, Ui, mpz_bin_ui)
DEFINE_UNARY_ASSIGNMENT_VAL(Primorial, Ui, MP(primorial_ui))
DEFINE_BINARY_ASSIGNMENT_VAL_VAL(Binomial, Ui, Ui, MP(bin_uiui))
DEFINE_BINARY_ASSIGNMENT_REF_VAL(Binomial, Int, Ui, MP(bin_ui))
DEFINE_ASSIGNMENT_PROLOG(FibonacciUi)
{
IS_NULL(_previous)
? mpz_fib_ui(destination, Operand)
: mpz_fib2_ui(destination, _previous->_value, Operand);
? MP(fib_ui)(destination, Operand)
: MP(fib2_ui)(destination, _previous->_value, Operand);
}
DEFINE_ASSIGNMENT_PROLOG(LucasUi)
{
IS_NULL(_previous)
? mpz_lucnum_ui(destination, Operand)
: mpz_lucnum2_ui(destination, _previous->_value, Operand);
? MP(lucnum_ui)(destination, Operand)
: MP(lucnum2_ui)(destination, _previous->_value, Operand);
}
#pragma endregion

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
*/
#include "StdAfx.h"
#include "HugeInt.h"
#include "Random.h"
namespace MPIR
@ -25,7 +26,7 @@ namespace MPIR
DEFINE_ASSIGNMENT_PROLOG(RandomInt)
{
IN_CONTEXT(Right);
mpz_urandomm(destination, Left->_value, context.Args[0]);
mpz_urandomm(destination, Left->_value, context.IntArgs[0]);
}
DEFINE_ASSIGNMENT_PROLOG(RandomIntBits)

View File

@ -216,7 +216,7 @@ namespace MPIR
/// </para></summary>
/// <param name="bitCount">number of bits to generate</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
IntegerExpression^ GetIntBits(mp_bitcnt_t bitCount) { return gcnew MpirRandomIntBitsExpression(this, bitCount); }
IntegerExpression^ GetIntBits(mp_bitcnt_t bitCount) { return gcnew IntegerRandomIntBitsExpression(this, bitCount); }
/// <summary>
/// Generates a random integer with long strings of zeros and ones in the binary representation.
@ -227,7 +227,7 @@ namespace MPIR
/// </para></summary>
/// <param name="bitCount">number of bits to generate</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
IntegerExpression^ GetIntBitsChunky(mp_bitcnt_t bitCount) { return gcnew MpirRandomIntBitsChunkyExpression(this, bitCount); }
IntegerExpression^ GetIntBitsChunky(mp_bitcnt_t bitCount) { return gcnew IntegerRandomIntBitsChunkyExpression(this, bitCount); }
/// <summary>
/// Generates a uniformly distributed random integer in the range 0 to <paramref name="max"/> - 1, inclusive.
@ -235,7 +235,7 @@ namespace MPIR
/// </para></summary>
/// <param name="max">exclusive upper bound for the number to generate</param>
/// <returns>An expression object that, when assigned to the Value property or consumed by a primitive-returning method, generates the random number</returns>
IntegerExpression^ GetInt(IntegerExpression^ max) { return gcnew MpirRandomIntExpression(this, max); }
IntegerExpression^ GetInt(IntegerExpression^ max) { return gcnew IntegerRandomIntExpression(this, max); }
#pragma endregion
};

View File

@ -26,4 +26,3 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
#include "mpir.h"
#include "gmp-impl.h"
#include "Common.h"
#include "HugeInt.h"