Init
This commit is contained in:
101
DependentExtensions/cat/math/BigMontgomery.hpp
Normal file
101
DependentExtensions/cat/math/BigMontgomery.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_MONTGOMERY_HPP
|
||||
#define CAT_BIG_MONTGOMERY_HPP
|
||||
|
||||
#include <cat/math/BigRTL.hpp>
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Performs fast modular arithmetic in the Montgomery Residue Number System
|
||||
class BigMontgomery : public BigRTL
|
||||
{
|
||||
static const int MON_OVERHEAD = 3 + 4;
|
||||
int mon_regs;
|
||||
|
||||
protected:
|
||||
Leg *TempProduct;
|
||||
Leg *TempProductHi;
|
||||
Leg *CachedModulus;
|
||||
Leg mod_inv;
|
||||
|
||||
public:
|
||||
BigMontgomery(int regs, int bits);
|
||||
|
||||
// Must call SetModulus() before using this object
|
||||
void SetModulus(const Leg *mod);
|
||||
|
||||
public:
|
||||
const Leg *GetModulus() { return CachedModulus; }
|
||||
void CopyModulus(Leg *out);
|
||||
|
||||
public:
|
||||
// Convert value in register into RNS, stored in out
|
||||
void MonInput(const Leg *in, Leg *out);
|
||||
|
||||
// Convert value in register from RNS, stored in out
|
||||
void MonOutput(const Leg *in, Leg *out);
|
||||
|
||||
// Note: This will clobber the input product!
|
||||
// Reduce a double-register product to a single register in the RNS
|
||||
void MonReduceProduct(Leg *inout_product, Leg *out);
|
||||
|
||||
public:
|
||||
// Inputs and outputs must be in the Montgomery RNS
|
||||
void MonAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonSubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonNegate(const Leg *in, Leg *out);
|
||||
void MonDouble(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Inputs and outputs must be in the Montgomery RNS
|
||||
void MonMultiply(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonSquare(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Base must be in the Montgomery RNS. in_base != out
|
||||
void MonExpMod(const Leg *in_base, const Leg *in_exp, Leg *out);
|
||||
|
||||
public:
|
||||
// Input is NOT in the RNS (don't call MonInput)
|
||||
// Probably a prime, certainty = 4^-trials. 20: %99.9999999999 certainty
|
||||
bool IsRabinMillerPrime(IRandom *prng, const Leg *n, int trials = 20);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_MONTGOMERY_HPP
|
||||
95
DependentExtensions/cat/math/BigPseudoMersenne.hpp
Normal file
95
DependentExtensions/cat/math/BigPseudoMersenne.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
|
||||
Several algorithms based on ideas from the
|
||||
"Handbook of Elliptic and Hyperelliptic Curve Cryptography"
|
||||
http://www.hyperelliptic.org/HEHCC/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
#define CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
|
||||
#include <cat/math/BigRTL.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Performs fast arithmetic modulo 2^bits-C, C = 1 (mod 4) or 3 (mod 8), C < 16384
|
||||
class BigPseudoMersenne : public BigRTL
|
||||
{
|
||||
static const int PM_OVERHEAD = 6; // overhead for MrSquareRoot()
|
||||
int pm_regs;
|
||||
|
||||
protected:
|
||||
Leg *CachedModulus;
|
||||
Leg modulus_c;
|
||||
|
||||
void CAT_FASTCALL MrReduceProductX(Leg overflow, Leg *inout);
|
||||
void CAT_FASTCALL MrReduceProduct(const Leg *in_hi, const Leg *in_lo, Leg *out);
|
||||
|
||||
public:
|
||||
BigPseudoMersenne(int regs, int bits, int C);
|
||||
|
||||
public:
|
||||
const Leg *GetModulus() { return CachedModulus; }
|
||||
void CAT_FASTCALL CopyModulus(Leg *out);
|
||||
|
||||
public:
|
||||
// Result may be one modulus too large, so efficiently correct that
|
||||
void CAT_FASTCALL MrReduce(Leg *inout);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrAddX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL MrSubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrSubtractX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL MrNegate(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrDouble(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrMultiply(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrMultiplyX(const Leg *in_a, Leg in_b, Leg *out);
|
||||
void CAT_FASTCALL MrSquare(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrInvert(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrSquareRoot(const Leg *in, Leg *out);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
164
DependentExtensions/cat/math/BigRTL.hpp
Normal file
164
DependentExtensions/cat/math/BigRTL.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
|
||||
Several algorithms based on ideas from the
|
||||
"Handbook of Elliptic and Hyperelliptic Curve Cryptography"
|
||||
http://www.hyperelliptic.org/HEHCC/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_RTL_HPP
|
||||
#define CAT_BIG_RTL_HPP
|
||||
|
||||
#include <cat/math/Legs.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Implements a register transfer language (RTL) for big integer arithmetic
|
||||
class BigRTL
|
||||
{
|
||||
static const int BIG_OVERHEAD = 7; // overhead for ModularInverse()
|
||||
int library_regs;
|
||||
|
||||
protected:
|
||||
int library_legs;
|
||||
Leg *library_memory;
|
||||
|
||||
protected:
|
||||
static Leg CAT_FASTCALL ShiftRight(int legs, const Leg *in, int shift, Leg *out);
|
||||
static Leg CAT_FASTCALL ShiftLeft(int legs, const Leg *in, int shift, Leg *out);
|
||||
|
||||
protected:
|
||||
static u8 CAT_FASTCALL Add(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
static u8 CAT_FASTCALL Add(int legs_a, const Leg *in_a, int legs_b, const Leg *in_b, Leg *out); // legs_b <= legs_a
|
||||
static u8 CAT_FASTCALL Subtract(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
|
||||
protected:
|
||||
static Leg CAT_FASTCALL MultiplyX(int legs, const Leg *in_a, Leg in_b, Leg *out);
|
||||
static Leg CAT_FASTCALL MultiplyXAdd(int legs, const Leg *in_a, Leg in_b, const Leg *in_c, Leg *out);
|
||||
static Leg CAT_FASTCALL DoubleAdd(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
|
||||
protected:
|
||||
static void CAT_FASTCALL DivideCore(int A_used, Leg A_overflow, Leg *A, int B_used, Leg *B, Leg *Q); // A = remainder
|
||||
|
||||
public:
|
||||
BigRTL(int regs, int bits);
|
||||
~BigRTL();
|
||||
|
||||
public:
|
||||
Leg * CAT_FASTCALL Get(int reg_index);
|
||||
CAT_INLINE int Legs() { return library_legs; }
|
||||
CAT_INLINE int RegBytes() { return library_legs * sizeof(Leg); }
|
||||
|
||||
public:
|
||||
// Save one single register to an endian-neutral byte array
|
||||
void CAT_FASTCALL Save(const Leg *in, void *out, int bytes);
|
||||
|
||||
// Load one single register from an endian-neutral byte array
|
||||
void CAT_FASTCALL Load(const void *in, int bytes, Leg *out);
|
||||
|
||||
bool CAT_FASTCALL LoadFromString(const char *in, int base, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL Copy(const Leg *in, Leg *out);
|
||||
void CAT_FASTCALL CopyX(Leg in, Leg *out);
|
||||
|
||||
public:
|
||||
int CAT_FASTCALL LegsUsed(const Leg *in);
|
||||
|
||||
public:
|
||||
bool CAT_FASTCALL Greater(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL GreaterX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL Less(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL LessX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL Equal(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL EqualX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL IsZero(const Leg *in);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL ShiftLeft(const Leg *in, int shift, Leg *out);
|
||||
void CAT_FASTCALL MoveLegsRight(const Leg *in, int legs, Leg *out);
|
||||
|
||||
public:
|
||||
u8 CAT_FASTCALL Add(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
u8 CAT_FASTCALL AddX(Leg *inout, Leg x);
|
||||
u8 CAT_FASTCALL Subtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
u8 CAT_FASTCALL SubtractX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL Negate(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
u8 CAT_FASTCALL Double(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Eat all trailing least significant zeroes from the argument and return the number eatten
|
||||
int CAT_FASTCALL EatTrailingZeroes(Leg *inout);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL MultiplyX(const Leg *in_a, Leg in_b, Leg *out); // out = a[] * b
|
||||
Leg CAT_FASTCALL MultiplyXAdd(const Leg *in_a, Leg in_b, const Leg *in_c, Leg *out); // out = a[] * b + c[]
|
||||
Leg CAT_FASTCALL DoubleAdd(const Leg *in_a, const Leg *in_b, Leg *out); // out = a[] * 2 + b[]
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MultiplyLow(const Leg *in_a, const Leg *in_b, Leg *out); // out = a[] * b[], low half
|
||||
|
||||
public:
|
||||
// out[] gets the low part of the product, next reg gets high part
|
||||
// note: in_a != out, in_b != out
|
||||
void CAT_FASTCALL Multiply(const Leg *in_a, const Leg *in_b, Leg *out); // out+1:out = a[] * b[]
|
||||
void CAT_FASTCALL Square(const Leg *in, Leg *out); // out+1:out = in[] * in[]
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL DivideX(const Leg *in_a, Leg in_b, Leg *out); // out = a[] / b, returns modulus
|
||||
Leg CAT_FASTCALL ModulusX(const Leg *in_a, Leg in_b); // returns a[] % b
|
||||
|
||||
public:
|
||||
bool CAT_FASTCALL Divide(const Leg *in_a, const Leg *in_b, Leg *out_q, Leg *out_r);
|
||||
|
||||
// Divide the product of two registers (a+1:a) by single register (b)
|
||||
// Resulting quotient is two registers (q+1:q) and remainder is one register (r)
|
||||
bool CAT_FASTCALL DivideProduct(const Leg *in_a, const Leg *in_b, Leg *out_q, Leg *out_r);
|
||||
|
||||
public:
|
||||
// r = a * b (mod m)
|
||||
void CAT_FASTCALL MulMod(const Leg *in_a, const Leg *in_b, const Leg *in_m, Leg *r);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL ModularInverse(const Leg *x, const Leg *modulus, Leg *inverse);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL MultiplicativeInverseX(Leg x);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_RTL_HPP
|
||||
195
DependentExtensions/cat/math/BigTwistedEdwards.hpp
Normal file
195
DependentExtensions/cat/math/BigTwistedEdwards.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Addition and doubling formulas using Extended Twisted Edwards coordinates from
|
||||
Hisil<69>Wong<6E>Carter<65>Dawson paper "Twisted Edwards Curves Revisited" (Asiacrypt 2008)
|
||||
|
||||
w-MOF scalar multiplication from http://www.sdl.hitachi.co.jp/crypto/mof/index-e.html
|
||||
|
||||
Scalar multiplication precomputation with "conjugate addition" inspired by
|
||||
Longa-Gebotys paper "Novel Precomputation Schemes for Elliptic Curve Cryptosystems" (2008)
|
||||
*/
|
||||
|
||||
/*
|
||||
Twisted Edwards E(p) Curve: a * x^2 + y^2 = 1 + d * x^2 * y^2, a = -1, p = 2^256 - c, c small
|
||||
|
||||
Edwards coordinates: (X : Y : Z)
|
||||
Extended Edwards coordinates: (X : Y : T : Z), T = XY
|
||||
Edwards to Extended Edwards: (X : Y : Z) -> (XZ : YZ : XY : ZZ)
|
||||
Extended Edwards to Edwards: (X : Y : T : Z) -> (X : Y : Z)
|
||||
|
||||
-(X : Y : T : Z) = (-X : Y : -T : Z)
|
||||
|
||||
Additive Identity element: X = 0
|
||||
|
||||
When Z = 1, a multiplication can be omitted
|
||||
|
||||
Mixing operations for more speed:
|
||||
doubling, doubling -> E = 2E
|
||||
doubling, add -> Ee = 2E, E = Ee + Ee
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
#define CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
|
||||
#include <cat/math/BigPseudoMersenne.hpp>
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class BigTwistedEdwards : public BigPseudoMersenne
|
||||
{
|
||||
static const int POINT_REGS = 4;
|
||||
static const int XOFF = 0;
|
||||
int YOFF, TOFF, ZOFF, POINT_STRIDE;
|
||||
|
||||
// Point multiplication default window
|
||||
static const int WINDOW_BITS = 6;
|
||||
static const int PRECOMP_POINTS = 1 << (WINDOW_BITS-1);
|
||||
static const int PRECOMP_NEG_OFFSET = PRECOMP_POINTS / 2;
|
||||
|
||||
static const int TE_OVERHEAD = (1 + PRECOMP_POINTS) * POINT_REGS + 9 + POINT_REGS * 2;
|
||||
int te_regs;
|
||||
|
||||
// Local workspace
|
||||
Leg *A, *B, *C, *D, *E, *F, *G, *H, *CurveQ, *Generator;
|
||||
Leg *TempPt;
|
||||
|
||||
protected:
|
||||
Leg curve_d;
|
||||
|
||||
// Simultaneous Add and Subtract for efficient precomputation (A +/- B) in 14M 1D 11a (versus 16M 2D 16a)
|
||||
void PtPrecompAddSub(const Leg *in_a, const Leg *in_b, Leg *sum, Leg *diff, int neg_offset);
|
||||
|
||||
public:
|
||||
BigTwistedEdwards(int regs, int bits, int C, int D, const u8 *Q, const u8 *GenPt);
|
||||
|
||||
int PtLegs() { return Legs() * POINT_REGS; }
|
||||
|
||||
Leg GetCurveD() { return curve_d; }
|
||||
const Leg *GetCurveQ() { return CurveQ; }
|
||||
const Leg *GetGenerator() { return Generator; }
|
||||
|
||||
public:
|
||||
// Unpack an Extended Projective point (X,Y,T,Z) from affine point (x,y)
|
||||
void PtUnpack(Leg *inout);
|
||||
|
||||
// Set a point to the identity
|
||||
void PtIdentity(Leg *inout);
|
||||
|
||||
// Check if the affine point (x,y) is the additive identity x=0
|
||||
bool IsAffineIdentity(const Leg *in);
|
||||
|
||||
public:
|
||||
void PtCopy(const Leg *in, Leg *out);
|
||||
|
||||
// Fill the X coordinate of the point with a random value
|
||||
void PtFillRandomX(IRandom *prng, Leg *out);
|
||||
|
||||
// Generate a random point on the curve that is not part of a small subgroup
|
||||
void PtGenerate(IRandom *prng, Leg *out);
|
||||
|
||||
public:
|
||||
// Solve for Y given the X point on a curve
|
||||
void PtSolveAffineY(Leg *inout);
|
||||
|
||||
// Verify that the point (x,y) exists on the given curve
|
||||
bool PtValidAffine(const Leg *in);
|
||||
|
||||
public:
|
||||
// out(x) = X/Z
|
||||
void SaveAffineX(const Leg *in, void *out_x);
|
||||
|
||||
// out(x,y) = (X/Z,Y/Z)
|
||||
void SaveAffineXY(const Leg *in, void *out_x, void *out_y);
|
||||
|
||||
// out(X,Y) = (X,Y) without attempting to convert to affine from projective
|
||||
void SaveProjectiveXY(const Leg *in, void *out_x, void *out_y);
|
||||
|
||||
// out(X,Y,Z,T) = (in_x,in_y), returns false if the coordinates are invalid
|
||||
bool LoadVerifyAffineXY(const void *in_x, const void *in_y, Leg *out);
|
||||
|
||||
// Compute affine coordinates for (X,Y), set Z=1, and compute T = xy
|
||||
void PtNormalize(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Negation Formula
|
||||
void PtNegate(const Leg *in, Leg *out);
|
||||
|
||||
// Extended Twisted Edwards Unified Addition Formula (works when both inputs are the same) in 8M 1D 9a
|
||||
void PtEAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void PtAdd(const Leg *in_a, const Leg *in_b, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Unified Subtraction Formula (works when both inputs are the same) in 8M 1D 9a
|
||||
void PtESubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void PtSubtract(const Leg *in_a, const Leg *in_b, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Dedicated Doubling Formula in 4M 4S 5a
|
||||
void PtEDouble(const Leg *in, Leg *out);
|
||||
void PtDouble(const Leg *in, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Dedicated Doubling Formula Assuming Z=1, in 4M 3S 4a
|
||||
void PtEDoubleZ1(const Leg *in, Leg *out);
|
||||
void PtDoubleZ1(const Leg *in, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
public:
|
||||
// Allocate a table for use with PtMultiplyPrecomp()
|
||||
// Free the table with Aligned::Delete()
|
||||
Leg *PtMultiplyPrecompAlloc(int w);
|
||||
|
||||
// Precompute odd multiples of input point
|
||||
void PtMultiplyPrecomp(const Leg *in, int w, Leg *table);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Scalar Multiplication k*p
|
||||
// Requires precomputation with PtMultiplyPrecomp()
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtMultiply(const Leg *in_precomp, int w, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
// Extended Twisted Edwards Scalar Multiplication k*p
|
||||
// Uses default precomputation
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtMultiply(const Leg *in_p, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
// A reference multiplier to verify that PtMultiply() is functionally the same
|
||||
void RefMul(const Leg *in_p, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Simultaneous Scalar Multiplication k*P + l*Q
|
||||
// Requires precomputation with PtMultiplyPrecomp()
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtSiMultiply(const Leg *precomp_p, const Leg *precomp_q, int w,
|
||||
const Leg *in_k, u8 msb_k, const Leg *in_l, u8 msb_l, Leg *out);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
246
DependentExtensions/cat/math/BitMath.hpp
Normal file
246
DependentExtensions/cat/math/BitMath.hpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BITMATH_HPP
|
||||
#define CAT_BITMATH_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Next highest power of two (e.g. 13 -> 16)
|
||||
CAT_INLINE u32 NextHighestPow2(u32 n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
return n + 1;
|
||||
}
|
||||
CAT_INLINE u64 NextHighestPow2(u64 n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
n |= n >> 32;
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
// Bit Scan Forward (BSF)
|
||||
// Scans from bit 0 to MSB
|
||||
// Undefined when input is zero
|
||||
CAT_INLINE u32 BSF32(u32 x);
|
||||
CAT_INLINE u32 BSF64(u64 x);
|
||||
|
||||
// Bit Scan Reverse (BSR)
|
||||
// Scans from MSB to bit 0
|
||||
// Undefined when input is zero
|
||||
CAT_INLINE u32 BSR32(u32 x);
|
||||
CAT_INLINE u32 BSR64(u64 x);
|
||||
|
||||
// Returns the count of bits set in the input for types up to 128 bits
|
||||
template<typename T> CAT_INLINE T BitCount(T v)
|
||||
{
|
||||
// From Stanford Bit Twiddling Hacks collection
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
||||
v = v - ((v >> 1) & (T)~(T)0/3);
|
||||
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
|
||||
v = (v + (v >> 4)) & (T)~(T)0/255*15;
|
||||
return (T)(v * ((T)~(T)0/255)) >> ((sizeof(v) - 1) * 8);
|
||||
}
|
||||
|
||||
// Reconstruct a 32-bit or 64-bit counter that increments by one each time,
|
||||
// given a truncated sample of its low bits, and the last accepted value of the counter.
|
||||
template<int BITS, typename T> CAT_INLINE T ReconstructCounter(T last_accepted_count, u32 partial_low_bits)
|
||||
{
|
||||
const u32 IV_MSB = (1 << BITS); // BITS < 32
|
||||
const u32 IV_MASK = (IV_MSB - 1);
|
||||
|
||||
s32 diff = partial_low_bits - (u32)(last_accepted_count & IV_MASK);
|
||||
return ((last_accepted_count & ~(T)IV_MASK) | partial_low_bits)
|
||||
- (((IV_MSB >> 1) - (diff & IV_MASK)) & IV_MSB)
|
||||
+ (diff & IV_MSB);
|
||||
}
|
||||
|
||||
|
||||
u32 BSF32(u32 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
|
||||
|
||||
u32 index;
|
||||
_BitScanForward((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
BSF eax, [x]
|
||||
CAT_ASM_END
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSFl %1, %%eax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
return BSR32(x ^ (x - 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSR32(u32 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
|
||||
|
||||
u32 index;
|
||||
_BitScanReverse((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
BSR eax, [x]
|
||||
CAT_ASM_END
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSRl %1, %%eax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
// Adapted from the Stanford Bit Twiddling Hacks collection
|
||||
register u32 shift, r;
|
||||
|
||||
r = (x > 0xFFFF) << 4; x >>= r;
|
||||
shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
|
||||
shift = (x > 0xF) << 2; x >>= shift; r |= shift;
|
||||
shift = (x > 0x3) << 1; x >>= shift; r |= shift;
|
||||
r |= (x >> 1);
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSF64(u64 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
|
||||
|
||||
u32 index;
|
||||
_BitScanForward64((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSFq %1, %%rax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
return BSR64(x ^ (x - 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSR64(u64 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
|
||||
|
||||
u32 index;
|
||||
_BitScanReverse64((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSRq %1, %%rax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
// Adapted from the Stanford Bit Twiddling Hacks collection
|
||||
register u32 shift, r;
|
||||
|
||||
r = (x > 0xFFFFFFFF) << 5; x >>= r;
|
||||
shift = (x > 0xFFFF) << 4; x >>= shift; r |= shift;
|
||||
shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
|
||||
shift = (x > 0xF) << 2; x >>= shift; r |= shift;
|
||||
shift = (x > 0x3) << 1; x >>= shift; r |= shift;
|
||||
r |= (u32)(x >> 1);
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BITMATH_HPP
|
||||
196
DependentExtensions/cat/math/Legs.hpp
Normal file
196
DependentExtensions/cat/math/Legs.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_LEGS_HPP
|
||||
#define CAT_LEGS_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
|
||||
#define CAT_LEG_BITS 64
|
||||
#define CAT_USED_BITS(x) BSR64(x) /* does not work if x = 0 */
|
||||
#define CAT_TRAILING_ZEROES(x) BSF64(x) /* does not work if x = 0 */
|
||||
typedef u64 Leg;
|
||||
typedef s64 LegSigned;
|
||||
#if !defined(CAT_COMPILER_MSVC)
|
||||
typedef u128 LegPair;
|
||||
typedef s128 LegPairSigned;
|
||||
# define CAT_LEG_PAIRMUL(A, B) ((LegPair)A * B)
|
||||
#else
|
||||
# define CAT_NO_LEGPAIR
|
||||
#endif
|
||||
|
||||
// If x86-64 and MSVC
|
||||
#if defined(CAT_ISA_X86) && defined(CAT_COMPILER_MSVC)
|
||||
#define CAT_USE_LEGS_ASM64 /* use 64-bit assembly code inner loops */
|
||||
#endif
|
||||
|
||||
#elif defined(CAT_WORD_32)
|
||||
|
||||
#define CAT_LEG_BITS 32
|
||||
#define CAT_USED_BITS(x) BSR32(x) /* does not work if x = 0 */
|
||||
#define CAT_TRAILING_ZEROES(x) BSF32(x) /* does not work if x = 0 */
|
||||
typedef u32 Leg;
|
||||
typedef s32 LegSigned;
|
||||
typedef u64 LegPair;
|
||||
typedef s64 LegPairSigned;
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
# define CAT_LEG_PAIRMUL(A, B) __emulu(A, B) /* slightly faster in ICC */
|
||||
#else
|
||||
# define CAT_LEG_PAIRMUL(A, B) ((LegPair)A * B)
|
||||
#endif
|
||||
|
||||
#endif // CAT_WORD_32
|
||||
|
||||
// Largest value that can be taken on by a Leg
|
||||
const Leg CAT_LEG_LARGEST = ~(Leg)0;
|
||||
|
||||
// MSB of a leg
|
||||
const Leg CAT_LEG_MSB = (Leg)1 << (CAT_LEG_BITS - 1);
|
||||
|
||||
|
||||
#if defined(CAT_NO_LEGPAIR)
|
||||
|
||||
////
|
||||
// Platforms that do not have LegPair (assumes 64-bit MSVC)
|
||||
////
|
||||
|
||||
|
||||
// p(hi:lo) = A * B
|
||||
#define CAT_LEG_MUL(A, B, p_hi, p_lo) \
|
||||
{ \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C
|
||||
#define CAT_LEG_MULADD(A, B, C, p_hi, p_lo) \
|
||||
{ \
|
||||
u64 _C0 = C; \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
p_hi += ((p_lo += _C0) < _C0); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C + D
|
||||
#define CAT_LEG_MULADD2(A, B, C, D, p_hi, p_lo) \
|
||||
{ \
|
||||
u64 _C0 = C, _D0 = D; \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
p_hi += ((p_lo += _C0) < _C0); \
|
||||
p_hi += ((p_lo += _D0) < _D0); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C1:C0)
|
||||
#define CAT_LEG_COMBA2(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
u64 _p_hi, _p_lo; \
|
||||
_p_lo = _umul128(A, B, &_p_hi); \
|
||||
_p_hi += ((C0 += _p_lo) < _p_lo); \
|
||||
C2 = ((C1 += _p_hi) < _p_hi); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C2:C1:C0)
|
||||
#define CAT_LEG_COMBA3(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
u64 _p_hi, _p_lo; \
|
||||
_p_lo = _umul128(A, B, &_p_hi); \
|
||||
_p_hi += ((C0 += _p_lo) < _p_lo); \
|
||||
C2 += ((C1 += _p_hi) < _p_hi); \
|
||||
}
|
||||
|
||||
|
||||
#else // has LegPair
|
||||
|
||||
////
|
||||
// Platforms that have LegPair (assumes 32-bit MSVC or any-bit GCC)
|
||||
////
|
||||
|
||||
|
||||
// p(hi:lo) = A * B
|
||||
#define CAT_LEG_MUL(A, B, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C
|
||||
#define CAT_LEG_MULADD(A, B, C, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B) + (Leg)(C); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C + D
|
||||
#define CAT_LEG_MULADD2(A, B, C, D, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B) + (Leg)(C) + (Leg)(D); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C1:C0)
|
||||
#define CAT_LEG_COMBA2(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
LegPair _cp = CAT_LEG_PAIRMUL(A, B) + (C0); \
|
||||
(C0) = (Leg)_cp; \
|
||||
_cp = (_cp >> CAT_LEG_BITS) + (C1); \
|
||||
(C1) = (Leg)_cp; \
|
||||
(C2) = (Leg)(_cp >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C2:C1:C0)
|
||||
#define CAT_LEG_COMBA3(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
LegPair _cp = CAT_LEG_PAIRMUL(A, B) + (C0); \
|
||||
(C0) = (Leg)_cp; \
|
||||
_cp = (_cp >> CAT_LEG_BITS) + (C1); \
|
||||
(C1) = (Leg)_cp; \
|
||||
(C2) += (Leg)(_cp >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// Q(hi:lo) = A(hi:lo) / B
|
||||
#define CAT_LEG_DIV(A_hi, A_lo, B, Q_hi, Q_lo) \
|
||||
{ \
|
||||
LegPair _Ax = ((LegPair)(A_hi) << CAT_LEG_BITS) | (Leg)(A_lo); \
|
||||
LegPair _qt = (LegPair)(_Ax / (B)); \
|
||||
(Q_hi) = (Leg)(_qt >> CAT_LEG_BITS); \
|
||||
(Q_lo) = (Leg)_qt; \
|
||||
}
|
||||
|
||||
#endif // CAT_NO_LEGPAIR
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_LEGS_HPP
|
||||
Reference in New Issue
Block a user