This commit is contained in:
2025-11-24 14:19:51 +05:30
commit f5c1412b28
6734 changed files with 1527575 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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