Major refactoring in preparation for adding the rational class. Broken build due to partial commit.
This commit is contained in:
parent
55e44923cf
commit
6e4af8e176
@ -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>
|
||||
|
@ -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>
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
};
|
259
mpir.net/mpir.net/ExpressionMacros.h
Normal file
259
mpir.net/mpir.net/ExpressionMacros.h
Normal 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
|
@ -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
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user