Stubbed out a HugeRational class. Broken build: interfaces not yet implemented.

This commit is contained in:
Alex Dyachenko 2014-05-05 21:10:24 -04:00
parent 8db0846661
commit bc0cbe8621
7 changed files with 2806 additions and 9 deletions

View File

@ -143,6 +143,7 @@
<ItemGroup>
<ClInclude Include="..\..\..\mpir.net\mpir.net\Common.h" />
<ClInclude Include="..\..\..\mpir.net\mpir.net\HugeInt.h" />
<ClInclude Include="..\..\..\mpir.net\mpir.net\HugeRational.h" />
<ClInclude Include="..\..\..\mpir.net\mpir.net\Random.h" />
<ClInclude Include="..\..\..\mpir.net\mpir.net\resource.h" />
<ClInclude Include="..\..\..\mpir.net\mpir.net\Stdafx.h" />
@ -151,6 +152,7 @@
<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" />
<ClCompile Include="..\..\..\mpir.net\mpir.net\Stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>

View File

@ -30,6 +30,9 @@
<ClInclude Include="..\..\..\mpir.net\mpir.net\Random.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\mpir.net\mpir.net\HugeRational.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\mpir.net\mpir.net\AssemblyInfo.cpp">
@ -47,6 +50,9 @@
<ClCompile Include="..\..\..\mpir.net\mpir.net\Random.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\mpir.net\mpir.net\HugeRational.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\..\mpir.net\mpir.net\ReadMe.txt" />

View File

@ -507,7 +507,7 @@ namespace MPIR
unsigned char csize_bytes[4];
mpir_out_struct out;
/* 4 bytes for size */
// 4 bytes for size
for(int i = 0; i < 4; i++)
{
auto byte = stream->ReadByte();
@ -554,7 +554,7 @@ namespace MPIR
int c;
size_t nread = 0;
/* Skip whitespace. */
// Skip whitespace
while ((c = reader->Peek()) >= 0 && Char::IsWhiteSpace(c))
{
nread++;

View File

@ -330,9 +330,10 @@ namespace MPIR
#pragma region IntegerExpression
/// <summary>
/// Base class for all expressions resulting from many operations on MPIR types. Expressions can be arbitrarily nested, and are lazily evaluated
/// Base class for all integer expressions resulting from many integer operations on MPIR types.
/// <para>Expressions can be arbitrarily nested, and are lazily evaluated
/// when they are either assigned to the Value property of an MPIR object, or are consumed by a function or operator that returns a primitive type.
/// Assignment to the Value property is necessary because .Net does not support overloading the assignment operator.
/// </para>Assignment to the Value property is necessary because .Net does not support overloading the assignment operator.
/// </summary>
public ref class IntegerExpression abstract : public IComparable, IComparable<IntegerExpression^>, IEquatable<IntegerExpression^>
{
@ -1618,7 +1619,7 @@ namespace MPIR
/// <summary>
/// Multi-precision Integer class.
/// </summary>
public ref class HugeInt sealed : IntegerExpression
public ref class HugeInt : IntegerExpression
{
internal:
//fields
@ -1630,16 +1631,17 @@ namespace MPIR
{
_value = (mpz_ptr)((*__gmp_allocate_func)(sizeof(__mpz_struct)));
}
void DeallocateStruct()
void FromString(String^ value, int base);
String^ ToString(int base, bool lowercase, int maxDigits);
internal:
virtual void DeallocateStruct()
{
mpz_clear(_value);
(*__gmp_free_func)(_value, sizeof(__mpz_struct));
_value = nullptr;
}
void FromString(String^ value, int base);
String^ ToString(int base, bool lowercase, int maxDigits);
internal:
//assignment
virtual void AssignTo(mpz_ptr destination) override
{

View File

@ -0,0 +1,748 @@
/*
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/.
*/
#include "Stdafx.h"
#include "Random.h"
#include "HugeRational.h"
using namespace System::Runtime::InteropServices;
using namespace System::Text;
namespace MPIR
{
/*
#pragma region construction
HugeInt::HugeInt()
{
AllocateStruct();
mpz_init(_value);
}
HugeInt::HugeInt(IntegerExpression^ value)
{
AllocateStruct();
mpz_init(_value);
value->AssignTo(_value);
}
HugeInt::HugeInt(mp_bitcnt_t bits)
{
AllocateStruct();
mpz_init2(_value, bits);
}
void HugeInt::FromString(String^ value, int base)
{
AllocateStruct();
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
bool success = 0 == mpz_init_set_str(_value, (char*)(void*)ptr, base);
Marshal::FreeHGlobal(ptr);
if(!success)
{
DeallocateStruct();
throw gcnew ArgumentException("Invalid number", "value");
}
}
void HugeInt::SetTo(String^ value, int base)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(value);
bool success = 0 == mpz_set_str(_value, (char*)(void*)ptr, base);
Marshal::FreeHGlobal(ptr);
if(!success)
throw gcnew ArgumentException("Invalid number", "value");
}
HugeInt^ HugeInt::FromLong(mpir_si value)
{
auto result = gcnew HugeInt();
mpz_set_si(result->_value, value);
return result;
}
HugeInt^ HugeInt::FromUlong(mpir_ui value)
{
auto result = gcnew HugeInt();
mpz_set_ui(result->_value, value);
return result;
}
HugeInt^ HugeInt::FromDouble(double value)
{
auto result = gcnew HugeInt();
mpz_set_d(result->_value, value);
return result;
}
#pragma endregion
#pragma region object overrides
String^ HugeInt::ToString(int base, bool lowercase, int maxDigits)
{
size_t allocated;
bool negative = false;
bool truncated = false;
EvaluationContext context;
if(maxDigits > 0 && CompareAbsTo(MpirSettings::_toStringModulo) >= 0)
{
(this->Abs() % MpirSettings::_toStringModulo)->Rounding(RoundingModes::Truncate)->AssignTo(context);
truncated = true;
negative = this->Sign() < 0;
allocated = maxDigits + 5;
}
else
{
AssignTo(context);
allocated = mpz_sizeinbase(_value, base == 0 ? 10 : base) + 2;
}
char* allocatedStr = (char*)(*__gmp_allocate_func)(allocated);
char* str = allocatedStr;
if(negative)
*str++ = '-';
if(truncated)
{
*str++ = '.';
*str++ = '.';
*str++ = '.';
}
mpz_get_str(str, (base <= 36 && !lowercase) ? -base : base, context.Args[0]);
auto result = gcnew String(allocatedStr);
(*__gmp_free_func)(allocatedStr, allocated);
return result;
}
int IntegerExpression::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--)
hash ^= *ptr++;
if(context.Args[0]->_mp_size < 0)
hash = (mp_limb_t)-(mpir_si)hash;
return hash.GetHashCode();
}
#pragma endregion
#pragma region Interface implementations
int IntegerExpression::CompareTo(Object^ a, bool& valid)
{
valid = true;
if (IS_NULL(a))
return 1;
IntegerExpression^ expr = dynamic_cast<IntegerExpression^>(a);
if(!IS_NULL(expr))
return CompareTo(expr);
EvaluationContext context;
if(a->GetType() == mpir_ui::typeid)
{
AssignTo(context);
return mpz_cmp_ui(context.Args[0], (mpir_ui)a);
}
if(a->GetType() == mpir_si::typeid)
{
AssignTo(context);
return mpz_cmp_si(context.Args[0], (mpir_si)a);
}
if(a->GetType() == double::typeid)
{
AssignTo(context);
return mpz_cmp_d(context.Args[0], (double)a);
}
valid = false;
return 0;
}
int IntegerExpression::CompareTo(Object^ a)
{
bool valid;
auto result = CompareTo(a, valid);
if (valid)
return result;
throw gcnew ArgumentException("Invalid argument type", "a");
}
int IntegerExpression::CompareTo(IntegerExpression^ a)
{
if (IS_NULL(a))
return 1;
IN_CONTEXT(this, a);
return mpz_cmp(context.Args[0], context.Args[1]);
}
bool IntegerExpression::Equals(Object^ a)
{
bool valid;
auto result = CompareTo(a, valid);
return valid && result == 0;
}
bool IntegerExpression::Equals(IntegerExpression^ a)
{
return CompareTo(a) == 0;
}
#pragma endregion
#pragma region expression special cases
void IntegerDivideExpression::custom_mpz_div(mpz_ptr q, mpz_srcptr n, mpz_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);
break;
case RoundingModes::Ceiling:
IS_NULL(_remainder)
? mpz_cdiv_q(q, n, d)
: mpz_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);
break;
}
}
void IntegerDivideUiExpression::custom_mpz_div_ui(mpz_ptr q, mpz_srcptr n, mpir_ui d)
{
mpir_ui limb;
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
limb = IS_NULL(_remainder)
? mpz_fdiv_q_ui(q, n, d)
: mpz_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);
break;
default:
limb = IS_NULL(_remainder)
? mpz_tdiv_q_ui(q, n, d)
: mpz_tdiv_qr_ui(q, _remainder->_value, n, d);
break;
}
if(!IS_NULL(_limbRemainder))
_limbRemainder(limb);
}
void IntegerShiftRightExpression::custom_mpz_div_2exp(mpz_ptr q, mpz_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);
break;
case RoundingModes::Ceiling:
_remainder
? mpz_cdiv_r_2exp(q, n, d)
: mpz_cdiv_q_2exp(q, n, d);
break;
default:
_remainder
? mpz_tdiv_r_2exp(q, n, d)
: mpz_tdiv_q_2exp(q, n, d);
break;
}
}
void IntegerModExpression::custom_mpz_mod(mpz_ptr r, mpz_srcptr n, mpz_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);
break;
case RoundingModes::Ceiling:
IS_NULL(_quotient)
? mpz_cdiv_r(r, n, d)
: mpz_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);
break;
}
}
void IntegerModUiExpression::custom_mpz_mod_ui(mpz_ptr r, mpz_srcptr n, mpir_ui d)
{
mpir_ui limb;
switch((rounding == RoundingModes::Default) ? MpirSettings::RoundingMode : rounding)
{
case RoundingModes::Floor:
limb = IS_NULL(_quotient)
? mpz_fdiv_r_ui(r, n, d)
: mpz_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);
break;
default:
limb = IS_NULL(_quotient)
? mpz_tdiv_r_ui(r, n, d)
: mpz_tdiv_qr_ui(_quotient->_value, r, n, d);
break;
}
if(!IS_NULL(_limbRemainder))
_limbRemainder(limb);
}
void IntegerRootExpression::custom_mpz_root(mpz_ptr dest, mpz_srcptr oper, mpir_ui power)
{
if(!IS_NULL(_remainder))
mpz_rootrem(dest, _remainder->_value, oper, power);
else if (IS_NULL(_exact))
mpz_nthroot(dest, oper, power);
else
_exact(mpz_root(dest, oper, power) != 0);
}
void IntegerSquareRootExpression::custom_mpz_sqrt(mpz_ptr dest, mpz_srcptr oper)
{
IS_NULL(_remainder)
? mpz_sqrt(dest, oper)
: mpz_sqrtrem(dest, _remainder->_value, oper);
}
void IntegerGcdExpression::custom_mpz_gcd(mpz_ptr dest, mpz_srcptr a, mpz_srcptr b)
{
switch ((IS_NULL(_s) ? 0 : 1) + (IS_NULL(_t) ? 0 : 2))
{
case 0:
mpz_gcd(dest, a, b);
break;
case 1:
mpz_gcdext(dest, _s->_value, NULL, a, b);
break;
case 2:
mpz_gcdext(dest, _t->_value, NULL, b, a);
break;
case 3:
mpz_gcdext(dest, _s->_value, _t->_value, a, b);
break;
}
}
#pragma endregion
#pragma region Arithmetic
DEFINE_OPERATIONS(DEFINE)
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_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(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(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(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_VAL(ShiftLeft, Int, Bits, mpz_mul_2exp)
DEFINE_BINARY_ASSIGNMENT_REF_VAL(ShiftRight, Int, Bits, custom_mpz_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_VAL(Power, Int, Ui, mpz_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_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(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_TERNARY_ASSIGNMENT_REF_REF_REF(PowerMod, Int, mpz_powm);
DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(PowerMod, Int, Ui, Int, mpz_powm_ui)
mpir_ui IntegerExpression::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);
case RoundingModes::Ceiling:
return mpz_cdiv_ui(context.Args[0], d);
default:
return mpz_tdiv_ui(context.Args[0], d);
}
}
#pragma endregion
#pragma region IO
#define chunkSize 1024
size_t HugeInt::Write(Stream^ stream)
{
mpir_out_struct out;
mpz_out_raw_m(out, _value);
auto buffer = gcnew array<unsigned char>(chunkSize);
auto ptr = out->written;
auto toWrite = (int)out->writtenSize;
while(toWrite > 0)
{
auto len = Math::Min(chunkSize, toWrite);
Marshal::Copy(IntPtr(ptr), buffer, 0, len);
stream->Write(buffer, 0, len);
ptr += len;
toWrite -= len;
}
(*__gmp_free_func)(out->allocated, out->allocatedSize);
return out->writtenSize;
}
size_t HugeInt::Read(Stream^ stream)
{
unsigned char csize_bytes[4];
mpir_out_struct out;
// 4 bytes for size
for(int i = 0; i < 4; i++)
{
auto byte = stream->ReadByte();
if(byte < 0)
throw gcnew Exception("Unexpected end of stream");
csize_bytes[i] = byte;
}
mpz_inp_raw_p(_value, csize_bytes, out);
if(out->writtenSize != 0)
{
auto buffer = gcnew array<unsigned char>(chunkSize);
auto ptr = out->written;
auto toRead = (int)out->writtenSize;
while(toRead > 0)
{
auto len = Math::Min(chunkSize, toRead);
if (len != stream->Read(buffer, 0, len))
throw gcnew Exception("Unexpected end of stream");
Marshal::Copy(buffer, 0, IntPtr(ptr), len);
ptr += len;
toRead -= len;
}
mpz_inp_raw_m(_value, out);
}
return 4 + out->writtenSize;
}
size_t HugeInt::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)
{
int c;
size_t nread = 0;
// Skip whitespace
while ((c = reader->Peek()) >= 0 && Char::IsWhiteSpace(c))
{
nread++;
reader->Read();
}
return ReadNoWhite(reader, base, nread);
}
#define PEEK_NEXT_CHAR \
reader->Read(); \
c = reader->Peek(); \
nread++;
// adapted from inp_str, which is shared by mpq_inp_str
size_t HugeInt::ReadNoWhite(TextReader^ reader, int base, size_t nread)
{
char *str;
size_t alloc_size, str_size;
bool negative = false;
mp_size_t xsize;
const unsigned char* digit_value = __gmp_digit_value_tab;
int c = reader->Peek();
if (base > 36)
{
// For bases > 36, use the collating sequence
// 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
digit_value += 224;
if (base > 62)
throw gcnew ArgumentException("Invalid base", "base");
}
if (c == '-')
{
negative = true;
PEEK_NEXT_CHAR;
}
if (c == EOF || digit_value[c] >= (base == 0 ? 10 : base))
throw gcnew Exception("No digits found");
// If BASE is 0, try to find out the base by looking at the initial characters.
if (base == 0)
{
base = 10;
if (c == '0')
{
base = 8;
PEEK_NEXT_CHAR;
switch(c = reader->Peek())
{
case 'x':
case 'X':
base = 16;
PEEK_NEXT_CHAR;
break;
case 'b':
case 'B':
base = 2;
PEEK_NEXT_CHAR;
}
}
}
// Skip leading zeros
while (c == '0')
{
PEEK_NEXT_CHAR;
}
alloc_size = 100;
str = (char *) (*__gmp_allocate_func) (alloc_size);
str_size = 0;
while (c != EOF)
{
int dig = digit_value[c];
if (dig >= base)
break;
if (str_size >= alloc_size)
{
size_t old_alloc_size = alloc_size;
alloc_size = alloc_size * 3 / 2;
str = (char *) (*__gmp_reallocate_func) (str, old_alloc_size, alloc_size);
}
str[str_size++] = dig;
reader->Read();
c = reader->Peek();
}
nread += str_size;
// Make sure the string is not empty, mpn_set_str would fail.
if (str_size == 0)
{
_value ->_mp_size = 0;
}
else
{
xsize = (((mp_size_t)
(str_size / __mp_bases[base].chars_per_bit_exactly))
/ GMP_NUMB_BITS + 2);
MPZ_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);
_value->_mp_size = (int)(negative ? -xsize : xsize);
}
(*__gmp_free_func) (str, alloc_size);
return nread;
}
#pragma endregion
#pragma region number-theoretic
bool HugeInt::IsProbablePrime(MpirRandom^ random, int probability, mpir_ui pretested)
{
return mpz_probable_prime_p(_value, random->_value, probability, pretested) != 0;
}
bool HugeInt::IsLikelyPrime(MpirRandom^ random, mpir_ui pretested)
{
return mpz_likely_prime_p(_value, random->_value, pretested) != 0;
}
MAKE_FUNCTION_WITH_LIMB (IntegerExpression, DEFINE, NextPrimeCandidate, Rnd)
DEFINE_ASSIGNMENT_PROLOG(NextPrimeCandidateIntRnd)
{
IN_CONTEXT(Left);
mpz_next_prime_candidate(destination, context.Args[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 (IntegerExpression, DEFINE, Invert, Int)
DEFINE_ASSIGNMENT_PROLOG(InvertIntInt)
{
IN_CONTEXT(Left, Right);
if (mpz_invert(destination, context.Args[0], context.Args[1]) == 0)
throw gcnew ArgumentException("Inverse does not exist");
}
MAKE_FUNCTION_WITH_ONE (IntegerRemoveFactorsExpression, DEFINE, RemoveFactors, Int)
DEFINE_ASSIGNMENT_PROLOG(RemoveFactorsIntInt)
{
IN_CONTEXT(Left, Right);
auto result = mpz_remove(destination, context.Args[0], context.Args[1]);
if(!IS_NULL(_count))
_count(result);
}
DEFINE_BINARY_ASSIGNMENT_VAL_VAL(Power, Ui, Ui, mpz_ui_pow_ui)
DEFINE_ASSIGNMENT_PROLOG(FactorialUiUi)
{
switch (Right)
{
case 1:
mpz_fac_ui(destination, Left);
break;
case 2:
mpz_2fac_ui(destination, Left);
break;
default:
mpz_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_ASSIGNMENT_PROLOG(FibonacciUi)
{
IS_NULL(_previous)
? mpz_fib_ui(destination, Operand)
: mpz_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);
}
#pragma endregion
*/
};

File diff suppressed because it is too large Load Diff