Redefined MPIR.Net addition and subtraction assignment to use addmul/submul when applicable

This commit is contained in:
Alex Dyachenko 2016-01-18 21:45:21 -05:00
parent 65aba6b72f
commit bd0da54f7e
3 changed files with 220 additions and 8 deletions

View File

@ -263,6 +263,19 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntAddProductHugeInt2()
{
using (var a = new HugeInt("98750293847520938457029384572093480498357"))
using (var c = new HugeInt("23094582093845093574093845093485039450934"))
using (var b = new HugeInt("-394580293847502987609283945873594873409587"))
{
var expr = c * b + a;
a.Value = expr;
Assert.AreEqual("-9112666988874677841199955832262586145147830205230375090322356322089362221491205901", a.ToString());
}
}
[TestMethod]
public void IntAddProductLimb()
{
@ -369,6 +382,19 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntAddProductSignedLimbTo4()
{
using (var a = new HugeInt("98750293847520938457029384572093480498357"))
using (var c = new HugeInt("23094582093845093574093845093485039450934"))
{
var b = Platform.Si(-498734523097853458, -2017853458);
var expr = b * c + a;
a.Value = expr;
Assert.AreEqual(Platform.Select("-11518065386718058599763388064972875060082210203928832731415", "-46601482240379908737297906081375735555240112731415"), a.ToString());
}
}
#endregion
#region Subtract Product
@ -386,6 +412,19 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntSubtractProductHugeIntFrom()
{
using (var a = new HugeInt("98750293847520938457029384572093480498359"))
using (var c = new HugeInt("23094582093845093574093845093485039450934"))
using (var b = new HugeInt("394580293847502987609283945873594873409587"))
{
var expr = c * b - a;
a.Value = expr;
Assert.AreEqual("9112666988874677841199955832262586145147830205230375090322356322089362221491205899", a.ToString());
}
}
[TestMethod]
public void IntSubtractProductLimb()
{
@ -399,6 +438,19 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntSubtractProductLimbFrom()
{
using (var a = new HugeInt("98750293847520938457029384572093480498359"))
using (var c = new HugeInt("23094582093845093574093845093485039450934"))
{
var b = Platform.Ui(498734523097853458, 3997853458);
var expr = c * b - a;
a.Value = expr;
Assert.AreEqual(Platform.Select("11518065386718058599763388064972875060082210203928832731413", "92328754786193194014003719366476113668089432731413"), a.ToString());
}
}
[TestMethod]
public void IntSubtractProductSignedLimb()
{
@ -412,6 +464,19 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntSubtractProductSignedLimbFrom()
{
using (var a = new HugeInt("98750293847520938457029384572093480498359"))
using (var c = new HugeInt("-23094582093845093574093845093485039450934"))
{
var b = Platform.Si(-498734523097853458, -2017853458);
var expr = b * c - a;
a.Value = expr;
Assert.AreEqual(Platform.Select("11518065386718058599763388064972875060082210203928832731413", "46601482240379908737297906081375735555240112731413"), a.ToString());
}
}
[TestMethod]
public void IntSubtractProductSignedLimb2()
{
@ -437,6 +502,30 @@ namespace MPIR.Tests.HugeIntTests
}
}
[TestMethod]
public void IntSubtractProductSignedLimbFrom3()
{
using (var a = new HugeInt("98750293847520938457029384572093480498359"))
using (var c = new HugeInt("-23094582093845093574093845093485039450934"))
{
var b = Platform.Si(498734523097853458, 2017853458);
a.Value = c * b - a;
Assert.AreEqual(Platform.Select("-11518065386718058797263975760014751974140979348115793728131", "-46601482437880496432339782995434504699427073728131"), a.ToString());
}
}
[TestMethod]
public void IntSubtractProductSignedLimb4()
{
using (var a = new HugeInt("98750293847520938457029384572093480498357"))
using (var c = new HugeInt("23094582093845093574093845093485039450934"))
{
var b = Platform.Si(498734523097853458, 2017853458);
a.Value = a - c * b;
Assert.AreEqual(Platform.Select("-11518065386718058599763388064972875060082210203928832731415", "-46601482240379908737297906081375735555240112731415"), a.ToString());
}
}
#endregion
#region Shift Left

View File

@ -59,7 +59,7 @@ along with the MPIR Library. If not, see http://www.gnu.org/licenses/.
private ref class MPEXPR(name) : base \
{ \
internal: \
type Operand; \
initonly type Operand; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(type operand) \
{ \
@ -72,8 +72,8 @@ private ref class MPEXPR(name) : base \
private ref class MPEXPR(name) : base \
{ \
internal: \
leftType Left; \
rightType Right; \
initonly leftType Left; \
initonly rightType Right; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(leftType left, rightType right) \
{ \
@ -87,9 +87,9 @@ private ref class MPEXPR(name) : base \
private ref class MPEXPR(name) : base \
{ \
internal: \
leftType Left; \
middleType Middle; \
rightType Right; \
initonly leftType Left; \
initonly middleType Middle; \
initonly rightType Right; \
virtual void AssignTo(MP(ptr) destination) override; \
MPEXPR(name)(leftType left, middleType middle, rightType right) \
{ \

View File

@ -435,11 +435,9 @@ namespace MPIR
DEFINE_UNARY_ASSIGNMENT_REF(Negate, Int, MP(neg))
DEFINE_UNARY_ASSIGNMENT_REF(Abs, Int, MP(abs))
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, 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))
@ -476,6 +474,131 @@ namespace MPIR
DEFINE_TERNARY_ASSIGNMENT_REF_REF_REF(PowerMod, Int, MP(powm));
DEFINE_TERNARY_ASSIGNMENT_REF_VAL_REF(PowerMod, Int, Ui, Int, MP(powm_ui))
#define WHEN_IS_DEST(i, a) \
auto x##i = dynamic_cast<MPTYPE^>(a); \
if (!IS_NULL(x##i) && x##i->_value == destination)
#define WHEN_IS(i, a, atype) \
auto x##i = dynamic_cast<MPEXPR(atype)^>(a); \
if (!IS_NULL(x##i))
DEFINE_ASSIGNMENT_PROLOG(AddIntInt)
{
WHEN_IS_DEST(1, Left)
{
WHEN_IS(2, Right, MultiplyIntInt)
{
IN_CONTEXT(x2->Left, x2->Right);
MP(addmul)(destination, CTXT(0), CTXT(1));
return;
}
WHEN_IS(3, Right, MultiplyIntUi)
{
IN_CONTEXT(x3->Left);
MP(addmul_ui)(destination, CTXT(0), x3->Right);
return;
}
WHEN_IS(4, Right, MultiplyIntSi)
{
IN_CONTEXT(x4->Left);
auto si = x4->Right;
if (si < 0)
MP(submul_ui)(destination, CTXT(0), (mpir_ui)-si);
else
MP(addmul_ui)(destination, CTXT(0), (mpir_ui)si);
return;
}
}
WHEN_IS_DEST(5, Right)
{
WHEN_IS(6, Left, MultiplyIntInt)
{
IN_CONTEXT(x6->Left, x6->Right);
MP(addmul)(destination, CTXT(0), CTXT(1));
return;
}
WHEN_IS(7, Left, MultiplyIntUi)
{
IN_CONTEXT(x7->Left);
MP(addmul_ui)(destination, CTXT(0), x7->Right);
return;
}
WHEN_IS(8, Left, MultiplyIntSi)
{
IN_CONTEXT(x8->Left);
auto si = x8->Right;
if (si < 0)
MP(submul_ui)(destination, CTXT(0), (mpir_ui)-si);
else
MP(addmul_ui)(destination, CTXT(0), (mpir_ui)si);
return;
}
}
IN_CONTEXT(Left, Right);
MP(add)(destination, CTXT(0), CTXT(1));
}
DEFINE_ASSIGNMENT_PROLOG(SubtractIntInt)
{
WHEN_IS_DEST(1, Left)
{
WHEN_IS(2, Right, MultiplyIntInt)
{
IN_CONTEXT(x2->Left, x2->Right);
MP(submul)(destination, CTXT(0), CTXT(1));
return;
}
WHEN_IS(3, Right, MultiplyIntUi)
{
IN_CONTEXT(x3->Left);
MP(submul_ui)(destination, CTXT(0), x3->Right);
return;
}
WHEN_IS(4, Right, MultiplyIntSi)
{
IN_CONTEXT(x4->Left);
auto si = x4->Right;
if (si < 0)
MP(addmul_ui)(destination, CTXT(0), (mpir_ui)-si);
else
MP(submul_ui)(destination, CTXT(0), (mpir_ui)si);
return;
}
}
WHEN_IS_DEST(5, Right)
{
WHEN_IS(6, Left, MultiplyIntInt)
{
IN_CONTEXT(x6->Left, x6->Right);
MP(submul)(destination, CTXT(0), CTXT(1));
MP(neg)(destination, destination);
return;
}
WHEN_IS(7, Left, MultiplyIntUi)
{
IN_CONTEXT(x7->Left);
MP(submul_ui)(destination, CTXT(0), x7->Right);
MP(neg)(destination, destination);
return;
}
WHEN_IS(8, Left, MultiplyIntSi)
{
IN_CONTEXT(x8->Left);
auto si = x8->Right;
if (si < 0)
MP(addmul_ui)(destination, CTXT(0), (mpir_ui)-si);
else
MP(submul_ui)(destination, CTXT(0), (mpir_ui)si);
MP(neg)(destination, destination);
return;
}
}
IN_CONTEXT(Left, Right);
MP(sub)(destination, CTXT(0), CTXT(1));
}
mpir_ui MPEXPR_NAME::Mod(mpir_ui d, RoundingModes rounding)
{
IN_CONTEXT(this);