commit
85e50f6cc8
3
.gitignore
vendored
3
.gitignore
vendored
@ -21,6 +21,7 @@ bld/
|
|||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
|
build/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
@ -258,4 +259,4 @@ paket-files/
|
|||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
# Python Tools for Visual Studio (PTVS)
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "BigInteger.h"
|
#include "BigInteger.h"
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
|
#include "Galois.h"
|
||||||
|
|
||||||
using namespace CryptoCPP::Math;
|
using namespace CryptoCPP::Math;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ int main()
|
|||||||
// |3 4|
|
// |3 4|
|
||||||
Matrix * m = new Matrix(2, 2);
|
Matrix * m = new Matrix(2, 2);
|
||||||
m->set_row
|
m->set_row
|
||||||
(new Vector(2, new long long[2]{ 1, 2 }), 0) WITH
|
(new Vector(2, new long long[2]{ 1, 2 }), 0)
|
||||||
(new Vector(2, new long long[2]{ 3, 4 }), 1);
|
(new Vector(2, new long long[2]{ 3, 4 }), 1);
|
||||||
|
|
||||||
// Create a 2x2 matrix
|
// Create a 2x2 matrix
|
||||||
@ -19,7 +20,7 @@ int main()
|
|||||||
// |7 8|
|
// |7 8|
|
||||||
Matrix * m1 = new Matrix(2, 2);
|
Matrix * m1 = new Matrix(2, 2);
|
||||||
m1->set_row
|
m1->set_row
|
||||||
(new Vector(2, new long long[2]{ 5, 6 }), 0) WITH
|
(new Vector(2, new long long[2]{ 5, 6 }), 0)
|
||||||
(new Vector(2, new long long[2]{ 7, 8 }), 1);
|
(new Vector(2, new long long[2]{ 7, 8 }), 1);
|
||||||
|
|
||||||
// Multiply matrices
|
// Multiply matrices
|
||||||
@ -36,6 +37,10 @@ int main()
|
|||||||
std::cout << "\nMatrix 'res':" << std::endl;
|
std::cout << "\nMatrix 'res':" << std::endl;
|
||||||
for (size_t t = 0; t < 4; ++t) std::cout << res->at(t, true) << ((t%2) ? '\n' : ' ');
|
for (size_t t = 0; t < 4; ++t) std::cout << res->at(t, true) << ((t%2) ? '\n' : ' ');
|
||||||
std::cout << "\ndet(m) = " << m->det() << "\ndet(m1) = " << m->det() << "\ndet(res) = " << res->det() << std::endl;
|
std::cout << "\ndet(m) = " << m->det() << "\ndet(m1) = " << m->det() << "\ndet(res) = " << res->det() << std::endl;
|
||||||
|
|
||||||
|
Galois * g1 = new Galois(2, 0b100011011, 0b10);
|
||||||
|
Galois * g2 = new Galois(2, 0b100011011, 0b11);
|
||||||
|
Galois * g3 = g1->mul(g2);
|
||||||
std::cin.ignore();
|
std::cin.ignore();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
#include "BigInteger.h"
|
#include "BigInteger.h"
|
||||||
|
|
||||||
|
|
||||||
namespace CryptoCPP {
|
namespace CryptoCPP {
|
||||||
namespace Math {
|
namespace Math {
|
||||||
BIGINT_API BigInteger::BigInteger(int64_t initialValue)
|
BIGINT_API BigInteger::BigInteger(long long initialValue)
|
||||||
{
|
{
|
||||||
data = new std::vector<BYTE>();
|
data = new std::vector<BYTE>();
|
||||||
|
|
||||||
// We know how big this should be and we know the size won't change
|
// We know how big this should be and we know the size won't change
|
||||||
static const size_t bytes = sizeof(int64_t);
|
static const size_t bytes = sizeof(initialValue);
|
||||||
for (size_t t = 0; t < bytes; ++t) data->push_back((initialValue >> (t * 8)) & 255);
|
for (size_t t = 0; t < bytes; ++t) data->push_back((initialValue >> (t * 8)) & 255);
|
||||||
|
|
||||||
sign = false;
|
sign = false;
|
||||||
@ -93,14 +94,14 @@ namespace CryptoCPP {
|
|||||||
return create;
|
return create;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API BigInteger * BigInteger::operator<<(uint64_t shiftcount) const
|
BIGINT_API BigInteger * BigInteger::operator<<(size_t shiftcount) const
|
||||||
{
|
{
|
||||||
BigInteger* create = new BigInteger(*this);
|
BigInteger* create = new BigInteger(*this);
|
||||||
create->ishl(shiftcount);
|
create->ishl(shiftcount);
|
||||||
return create;
|
return create;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API BigInteger * BigInteger::operator>>(uint64_t shiftcount) const
|
BIGINT_API BigInteger * BigInteger::operator>>(size_t shiftcount) const
|
||||||
{
|
{
|
||||||
BigInteger* create = new BigInteger(*this);
|
BigInteger* create = new BigInteger(*this);
|
||||||
create->ishr(shiftcount);
|
create->ishr(shiftcount);
|
||||||
@ -157,13 +158,13 @@ namespace CryptoCPP {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API BigInteger* BigInteger::operator<<=(uint64_t shiftcount)
|
BIGINT_API BigInteger* BigInteger::operator<<=(size_t shiftcount)
|
||||||
{
|
{
|
||||||
ishl(shiftcount);
|
ishl(shiftcount);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API BigInteger* BigInteger::operator>>=(uint64_t shiftcount)
|
BIGINT_API BigInteger* BigInteger::operator>>=(size_t shiftcount)
|
||||||
{
|
{
|
||||||
ishr(shiftcount);
|
ishr(shiftcount);
|
||||||
return this;
|
return this;
|
||||||
@ -338,7 +339,7 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
BIGINT_API BigInteger* BigInteger::idiv(const BigInteger & val, bool swaptarget)
|
BIGINT_API BigInteger* BigInteger::idiv(const BigInteger & val, bool swaptarget)
|
||||||
{
|
{
|
||||||
if (val.is_zero()) throw new std::exception("Divide by zero!");
|
if (val.is_zero()) throw new std::exception(); // Divide by zero!
|
||||||
BigInteger* rem = new BigInteger(0);
|
BigInteger* rem = new BigInteger(0);
|
||||||
BigInteger quot = BigInteger(0);
|
BigInteger quot = BigInteger(0);
|
||||||
|
|
||||||
@ -403,7 +404,7 @@ namespace CryptoCPP {
|
|||||||
for (size_t t = 0; t < data->size(); ++t) (*data)[t] = ~(*data)[t];
|
for (size_t t = 0; t < data->size(); ++t) (*data)[t] = ~(*data)[t];
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API void BigInteger::ishl(uint64_t shift)
|
BIGINT_API void BigInteger::ishl(size_t shift)
|
||||||
{
|
{
|
||||||
size_t set = shift / 8;
|
size_t set = shift / 8;
|
||||||
char sub = shift % 8;
|
char sub = shift % 8;
|
||||||
@ -430,7 +431,7 @@ namespace CryptoCPP {
|
|||||||
clip_zeroes();
|
clip_zeroes();
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API void BigInteger::ishr(uint64_t shift)
|
BIGINT_API void BigInteger::ishr(size_t shift)
|
||||||
{
|
{
|
||||||
size_t offset = shift / 8;
|
size_t offset = shift / 8;
|
||||||
char sub = shift % 8;
|
char sub = shift % 8;
|
||||||
@ -491,10 +492,10 @@ namespace CryptoCPP {
|
|||||||
return ((l1 > l2 && (!sign == grt)) || ((sign == grt) && l1 < l2)) ? 1 : 0;
|
return ((l1 > l2 && (!sign == grt)) || ((sign == grt) && l1 < l2)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGINT_API char BigInteger::shift_mask(int64_t shift, bool left)
|
BIGINT_API char BigInteger::shift_mask(size_t shift, bool left)
|
||||||
{
|
{
|
||||||
BYTE res = 0;
|
BYTE res = 0;
|
||||||
for (uint64_t i = shift; i > 0; --i) res = left ? (res >> 1) | 128 : (res << 1) | 1;
|
for (size_t i = shift; i > 0; --i) res = left ? (res >> 1) | 128 : (res << 1) | 1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,4 +548,5 @@ namespace CryptoCPP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,23 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef BIGINT_API
|
#if defined(__MINGW32__) || defined(_WIN32)
|
||||||
#define BIGINT_API __declspec(dllexport)
|
|
||||||
#else
|
#if defined(BIGINT_API)
|
||||||
#define BIGINT_API __declspec(dllimport)
|
#define BIGINT_API __declspec(dllexport)
|
||||||
#endif
|
#else
|
||||||
|
#define BIGINT_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BIGINT_API
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define BIGINT_API __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
#define BIGINT_API
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BYTE unsigned char
|
#define BYTE unsigned char
|
||||||
|
|
||||||
@ -16,7 +28,7 @@ namespace CryptoCPP {
|
|||||||
class BigInteger
|
class BigInteger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BIGINT_API BigInteger(int64_t initialValue);
|
BIGINT_API BigInteger(long long initialValue);
|
||||||
BIGINT_API BigInteger(const BigInteger& initialvalue);
|
BIGINT_API BigInteger(const BigInteger& initialvalue);
|
||||||
|
|
||||||
// These should just create a new bigint and call the internal functions on it
|
// These should just create a new bigint and call the internal functions on it
|
||||||
@ -29,8 +41,8 @@ namespace CryptoCPP {
|
|||||||
BIGINT_API BigInteger* operator&(const BigInteger& val) const;
|
BIGINT_API BigInteger* operator&(const BigInteger& val) const;
|
||||||
BIGINT_API BigInteger* operator|(const BigInteger& val) const;
|
BIGINT_API BigInteger* operator|(const BigInteger& val) const;
|
||||||
BIGINT_API BigInteger* operator~() const;
|
BIGINT_API BigInteger* operator~() const;
|
||||||
BIGINT_API BigInteger* operator<<(uint64_t shiftcount) const;
|
BIGINT_API BigInteger* operator<<(size_t shiftcount) const;
|
||||||
BIGINT_API BigInteger* operator>>(uint64_t shiftcount) const;
|
BIGINT_API BigInteger* operator>>(size_t shiftcount) const;
|
||||||
|
|
||||||
BIGINT_API BigInteger* operator+=(const BigInteger& val);
|
BIGINT_API BigInteger* operator+=(const BigInteger& val);
|
||||||
BIGINT_API BigInteger* operator-=(const BigInteger& val);
|
BIGINT_API BigInteger* operator-=(const BigInteger& val);
|
||||||
@ -40,8 +52,8 @@ namespace CryptoCPP {
|
|||||||
BIGINT_API BigInteger* operator^=(const BigInteger& val);
|
BIGINT_API BigInteger* operator^=(const BigInteger& val);
|
||||||
BIGINT_API BigInteger* operator&=(const BigInteger& val);
|
BIGINT_API BigInteger* operator&=(const BigInteger& val);
|
||||||
BIGINT_API BigInteger* operator|=(const BigInteger& val);
|
BIGINT_API BigInteger* operator|=(const BigInteger& val);
|
||||||
BIGINT_API BigInteger* operator<<=(uint64_t shiftcount);
|
BIGINT_API BigInteger* operator<<=(size_t shiftcount);
|
||||||
BIGINT_API BigInteger* operator>>=(uint64_t shiftcount);
|
BIGINT_API BigInteger* operator>>=(size_t shiftcount);
|
||||||
|
|
||||||
BIGINT_API bool operator<(const BigInteger& val) const;
|
BIGINT_API bool operator<(const BigInteger& val) const;
|
||||||
BIGINT_API bool operator>(const BigInteger& val) const;
|
BIGINT_API bool operator>(const BigInteger& val) const;
|
||||||
@ -66,8 +78,8 @@ namespace CryptoCPP {
|
|||||||
BIGINT_API void iand(const BigInteger& val, bool swaptarget);
|
BIGINT_API void iand(const BigInteger& val, bool swaptarget);
|
||||||
BIGINT_API void ior(const BigInteger& val, bool swaptarget);
|
BIGINT_API void ior(const BigInteger& val, bool swaptarget);
|
||||||
BIGINT_API void inot();
|
BIGINT_API void inot();
|
||||||
BIGINT_API void ishl(uint64_t shift);
|
BIGINT_API void ishl(size_t shift);
|
||||||
BIGINT_API void ishr(uint64_t shift);
|
BIGINT_API void ishr(size_t shift);
|
||||||
BIGINT_API void twos_complement();
|
BIGINT_API void twos_complement();
|
||||||
BIGINT_API void set_bit(size_t index, bool value);
|
BIGINT_API void set_bit(size_t index, bool value);
|
||||||
BIGINT_API void cpy(const BigInteger& val, bool withsign);
|
BIGINT_API void cpy(const BigInteger& val, bool withsign);
|
||||||
@ -75,7 +87,7 @@ namespace CryptoCPP {
|
|||||||
BIGINT_API char cmp(const BigInteger& other, bool grt) const;
|
BIGINT_API char cmp(const BigInteger& other, bool grt) const;
|
||||||
|
|
||||||
// Math helper functions
|
// Math helper functions
|
||||||
BIGINT_API char shift_mask(int64_t shift, bool left);
|
BIGINT_API char shift_mask(size_t shift, bool left);
|
||||||
|
|
||||||
// For sorting and whatnot
|
// For sorting and whatnot
|
||||||
BIGINT_API void clip_zeroes();
|
BIGINT_API void clip_zeroes();
|
||||||
@ -85,4 +97,5 @@ namespace CryptoCPP {
|
|||||||
BIGINT_API bool is_zero() const;
|
BIGINT_API bool is_zero() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
446
XMath/Galois.cpp
Normal file
446
XMath/Galois.cpp
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
#define GALOIS_API
|
||||||
|
|
||||||
|
#include "Galois.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace CryptoCPP{
|
||||||
|
namespace Math{
|
||||||
|
size_t _ceil(double d)
|
||||||
|
{
|
||||||
|
return (size_t)d + (d > (size_t)d ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t block_count(size_t bin_block_size, size_t bufs)
|
||||||
|
{
|
||||||
|
return (bufs * 8 * sizeof(BLOCK)) / bin_block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* do_copy(void* v, size_t size)
|
||||||
|
{
|
||||||
|
char * c = new char[size];
|
||||||
|
memcpy(c, v, size);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois::Galois(
|
||||||
|
BLOCK characteristic,
|
||||||
|
BLOCK * irreducible,
|
||||||
|
size_t irreducible_size,
|
||||||
|
BLOCK * value,
|
||||||
|
size_t value_size
|
||||||
|
) :
|
||||||
|
characteristic(characteristic),
|
||||||
|
irreducible(irreducible),
|
||||||
|
irreducible_size(irreducible_size),
|
||||||
|
binary_block_size(_ceil(characteristic/2.0)),
|
||||||
|
exponent(high_factor(irreducible, irreducible_size, _ceil(characteristic / 2.0), 0)),
|
||||||
|
data_size(value_size)
|
||||||
|
{
|
||||||
|
data = value;
|
||||||
|
}
|
||||||
|
GALOIS_API Galois::Galois(
|
||||||
|
BLOCK characteristic,
|
||||||
|
BLOCK irreducible,
|
||||||
|
BLOCK value
|
||||||
|
) : Galois(characteristic, new BLOCK[1]{ irreducible }, 1, new BLOCK[1]{value}, 1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
GALOIS_API Galois::Galois(const Galois & copy) :
|
||||||
|
characteristic(copy.characteristic),
|
||||||
|
exponent(copy.exponent),
|
||||||
|
irreducible(new BLOCK[copy.irreducible_size]),
|
||||||
|
irreducible_size(copy.irreducible_size),
|
||||||
|
binary_block_size(copy.binary_block_size),
|
||||||
|
data_size(copy.data_size)
|
||||||
|
{
|
||||||
|
data = new BLOCK[data_size];
|
||||||
|
memcpy(irreducible, copy.irreducible, irreducible_size * sizeof(BLOCK));
|
||||||
|
memcpy(data, copy.data, data_size * sizeof(BLOCK));
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois::~Galois()
|
||||||
|
{
|
||||||
|
delete[] irreducible;
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois * Galois::add(const Galois * value) const
|
||||||
|
{
|
||||||
|
bool imSmaller = value->data_size > data_size;
|
||||||
|
size_t state_size = imSmaller ? value->data_size : data_size;
|
||||||
|
BLOCK * state = new BLOCK[state_size];
|
||||||
|
memset(state, 0, state_size * sizeof(BLOCK));
|
||||||
|
memcpy(state, imSmaller ? value->data : data, state_size * sizeof(BLOCK));
|
||||||
|
|
||||||
|
iadd(imSmaller ? data : value->data, imSmaller ? data_size : value->data_size, binary_block_size, state, state_size, characteristic);
|
||||||
|
|
||||||
|
return new Galois(characteristic, (BLOCK *)do_copy(irreducible, irreducible_size * sizeof(BLOCK)), irreducible_size, state, state_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois * Galois::sub(const Galois * value) const
|
||||||
|
{
|
||||||
|
bool imSmaller = value->data_size > data_size;
|
||||||
|
size_t state_size = imSmaller ? value->data_size : data_size;
|
||||||
|
BLOCK * state = new BLOCK[state_size];
|
||||||
|
memset(state, 0, state_size * sizeof(BLOCK));
|
||||||
|
memcpy(state, data, data_size * sizeof(BLOCK));
|
||||||
|
|
||||||
|
isub(value->data, value->data_size, binary_block_size, state, state_size, characteristic);
|
||||||
|
|
||||||
|
return new Galois(characteristic, (BLOCK *)do_copy(irreducible, irreducible_size * sizeof(BLOCK)), irreducible_size, state, state_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois * Galois::mul(const Galois * value) const
|
||||||
|
{
|
||||||
|
bool nb1, nb2;
|
||||||
|
size_t
|
||||||
|
h1 = high_factor(data, data_size, binary_block_size, &nb1),
|
||||||
|
h2 = high_factor(value->data, value->data_size, value->binary_block_size, &nb2),
|
||||||
|
h1_idx = h1 / (8 * sizeof(BLOCK)),
|
||||||
|
h2_idx = h2 / (8 * sizeof(BLOCK));
|
||||||
|
|
||||||
|
// If one of the values is 0, return a zero-Galois
|
||||||
|
if (nb1 || nb2) return new Galois(characteristic, (BLOCK *)do_copy(irreducible, irreducible_size * sizeof(BLOCK)), irreducible_size, (BLOCK*)memset(new BLOCK[1], 0, sizeof(BLOCK)), 1);
|
||||||
|
|
||||||
|
// The product of two values with the same base is represented as the sum of their exponents
|
||||||
|
BLOCK * state = new BLOCK[h1_idx + h2_idx + 1];
|
||||||
|
memset(state, 0, (h1_idx + h2_idx + 1) * sizeof(BLOCK));
|
||||||
|
memcpy(state, this->data, this->data_size);
|
||||||
|
|
||||||
|
BLOCK * cmp_exp = new BLOCK[(exponent/(8 * sizeof(BLOCK))) + 1];
|
||||||
|
set_value(exponent, 1, binary_block_size, characteristic, cmp_exp);
|
||||||
|
|
||||||
|
imul(value->data, value->data_size, binary_block_size, &state, h1_idx + h2_idx + 1, characteristic, h1_idx, h2_idx);
|
||||||
|
ModResult * res = imod(state, h1_idx + h2_idx + 1, irreducible, irreducible_size, cmp_exp, (exponent / (8 * sizeof(BLOCK))) + 1, characteristic, binary_block_size);
|
||||||
|
delete[] state;
|
||||||
|
state = res->mod;
|
||||||
|
size_t state_size = res->mod_size;
|
||||||
|
delete[] res->div;
|
||||||
|
delete res;
|
||||||
|
|
||||||
|
return new Galois(characteristic, (BLOCK *)do_copy(irreducible, irreducible_size * sizeof(BLOCK)), irreducible_size, state, state_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois * Galois::inv() const
|
||||||
|
{
|
||||||
|
struct FactorItem {
|
||||||
|
FactorItem(BLOCK * factor, size_t factor_size) { this->factor = factor; this->factor_size = factor_size; }
|
||||||
|
BLOCK * factor;
|
||||||
|
size_t factor_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t exp = ((exponent + 1) / (8 * sizeof(BLOCK))) + 1;
|
||||||
|
BLOCK * compute = new BLOCK[exp];
|
||||||
|
memset(compute, 0, exp * sizeof(size_t));
|
||||||
|
memcpy(compute, irreducible, irreducible_size * sizeof(BLOCK));
|
||||||
|
|
||||||
|
size_t compute_size = exp;
|
||||||
|
|
||||||
|
BLOCK * temp = new BLOCK[exp];
|
||||||
|
memset(temp, 0, exp * sizeof(BLOCK));
|
||||||
|
memcpy(temp, data, data_size * sizeof(BLOCK));
|
||||||
|
|
||||||
|
size_t temp_size = exp;
|
||||||
|
|
||||||
|
std::vector<FactorItem> factors = std::vector<FactorItem>();
|
||||||
|
struct ModResult * m;
|
||||||
|
size_t high;
|
||||||
|
size_t highest1 = 1, highest2 = 1;
|
||||||
|
|
||||||
|
// TODO: Implement extended Euclidean algorithm
|
||||||
|
bool nb;
|
||||||
|
volatile bool x = false;
|
||||||
|
Loop:
|
||||||
|
high_factor(temp, temp_size, binary_block_size, &nb);
|
||||||
|
if (nb) goto Next;
|
||||||
|
|
||||||
|
m = //new ModResult(); m->div = new size_t[m->div_size = 1]{(size_t)(change?0:1)}; m->mod = new size_t[m->mod_size = 1]{0};
|
||||||
|
imod(compute, compute_size, temp, temp_size, temp, temp_size, characteristic, binary_block_size);
|
||||||
|
delete[] compute;
|
||||||
|
compute = temp;
|
||||||
|
temp = m->mod;
|
||||||
|
compute_size = temp_size;
|
||||||
|
temp_size = m->mod_size;
|
||||||
|
factors.push_back(FactorItem(m->div, m->div_size));
|
||||||
|
|
||||||
|
// Record highest values
|
||||||
|
high = high_factor(m->div, m->div_size, binary_block_size, &nb);
|
||||||
|
if (high > highest1)
|
||||||
|
{
|
||||||
|
highest2 = highest1;
|
||||||
|
highest1 = high;
|
||||||
|
}
|
||||||
|
else if (high > highest2) highest2 = high;
|
||||||
|
delete m;
|
||||||
|
goto Loop;
|
||||||
|
|
||||||
|
Next:
|
||||||
|
// Free unneeded resources
|
||||||
|
delete[] temp;
|
||||||
|
delete[] compute;
|
||||||
|
|
||||||
|
// Remove invalid computation result
|
||||||
|
delete[] factors.at(factors.size() - 1).factor;
|
||||||
|
factors.pop_back();
|
||||||
|
|
||||||
|
if (factors.size() == 0) factors.push_back(FactorItem(new BLOCK[1]{1}, 1));
|
||||||
|
|
||||||
|
// Initialize left result of the diophantine equation
|
||||||
|
compute_size = highest1 * highest2;
|
||||||
|
compute = new BLOCK[compute_size];
|
||||||
|
memset(compute, 0, compute_size * sizeof(BLOCK));
|
||||||
|
memcpy(compute, factors.at(factors.size() - 1).factor, factors.at(factors.size() - 1).factor_size * sizeof(BLOCK));
|
||||||
|
delete[] factors.at(factors.size() - 1).factor;
|
||||||
|
factors.pop_back();
|
||||||
|
|
||||||
|
// Initialize the right result
|
||||||
|
temp_size = compute_size;
|
||||||
|
temp = new BLOCK[temp_size];
|
||||||
|
memset(temp, 0, compute_size * sizeof(BLOCK));
|
||||||
|
temp[0] |= 1;
|
||||||
|
|
||||||
|
BLOCK * cmp = new BLOCK[exp];
|
||||||
|
memset(cmp, 0, exp * sizeof(BLOCK));
|
||||||
|
cmp[exponent] = 1;
|
||||||
|
|
||||||
|
// Initialize a holder for performing intermediate computations on
|
||||||
|
size_t holder_size = compute_size;
|
||||||
|
BLOCK * holder = new BLOCK[holder_size];
|
||||||
|
|
||||||
|
BLOCK * transfer;
|
||||||
|
size_t transfer_size;
|
||||||
|
|
||||||
|
// Continue computation of both sides
|
||||||
|
while (factors.size() > 0)
|
||||||
|
{
|
||||||
|
FactorItem item = factors.at(factors.size() - 1);
|
||||||
|
factors.pop_back();
|
||||||
|
memcpy(memset(holder, 0, holder_size), item.factor, item.factor_size * sizeof(size_t));
|
||||||
|
|
||||||
|
size_t f1 = high_factor(temp, temp_size, binary_block_size, 0), f2 = high_factor(holder, holder_size, binary_block_size, 0);
|
||||||
|
|
||||||
|
imul(holder, holder_size, binary_block_size, &temp, temp_size, characteristic, f1 / (8 * sizeof(BLOCK)), f2 / (8 * sizeof(BLOCK)));
|
||||||
|
temp_size = (f1 / (8 * sizeof(BLOCK))) + (f2 / (8 * sizeof(BLOCK))) + 1;
|
||||||
|
ModResult * result = imod(temp, temp_size, irreducible, irreducible_size, cmp, exp, characteristic, binary_block_size);
|
||||||
|
memcpy(memset(temp, 0, temp_size * sizeof(BLOCK)), result->mod, result->mod_size);
|
||||||
|
delete[] result->mod;
|
||||||
|
delete[] result->div;
|
||||||
|
delete result;
|
||||||
|
|
||||||
|
// Do swap
|
||||||
|
transfer = compute;
|
||||||
|
transfer_size = compute_size;
|
||||||
|
|
||||||
|
compute = temp;
|
||||||
|
compute_size = temp_size;
|
||||||
|
|
||||||
|
temp = transfer;
|
||||||
|
temp_size = transfer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t result_size = ((high_factor(compute, compute_size, binary_block_size, &nb) + 1) / (8 * sizeof(BLOCK))) + 1;
|
||||||
|
BLOCK * result = new BLOCK[result_size];
|
||||||
|
memcpy(result, compute, result_size * sizeof(BLOCK));
|
||||||
|
delete[] compute;
|
||||||
|
delete[] temp;
|
||||||
|
delete[] cmp;
|
||||||
|
return new Galois(characteristic, (BLOCK*)do_copy(irreducible, irreducible_size * sizeof(BLOCK)), irreducible_size, result, result_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These internal functions assume that an adequate state size has been chose
|
||||||
|
GALOIS_API void Galois::iadd(BLOCK * data, size_t data_size, size_t bin_size, BLOCK * state, size_t state_size, BLOCK characteristic)
|
||||||
|
{
|
||||||
|
for (size_t t = block_count(bin_size, data_size); t > 0; --t)
|
||||||
|
set_value(
|
||||||
|
t - 1,
|
||||||
|
(
|
||||||
|
get_value(t-1, bin_size, state) +
|
||||||
|
get_value(t - 1, bin_size, data)
|
||||||
|
) % characteristic,
|
||||||
|
bin_size,
|
||||||
|
characteristic,
|
||||||
|
state
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API void Galois::isub(BLOCK * data, size_t data_size, size_t bin_size, BLOCK * state, size_t state_size, BLOCK characteristic)
|
||||||
|
{
|
||||||
|
for (size_t t = block_count(bin_size, data_size); t > 0; --t)
|
||||||
|
set_value(
|
||||||
|
t - 1,
|
||||||
|
(
|
||||||
|
characteristic +
|
||||||
|
get_value(t - 1, bin_size, state) -
|
||||||
|
get_value(t - 1, bin_size, data)
|
||||||
|
) % characteristic,
|
||||||
|
bin_size,
|
||||||
|
characteristic,
|
||||||
|
state
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API void Galois::imul(BLOCK * data, size_t data_size, size_t bin_size, BLOCK ** state, size_t state_size, BLOCK characteristic, size_t high1, size_t high2)
|
||||||
|
{
|
||||||
|
BLOCK * temp = new BLOCK[high1 + high2 + 1];
|
||||||
|
//memset(temp, 0, (high1 + high2 + 1) * sizeof(size_t));
|
||||||
|
|
||||||
|
BLOCK * res = new BLOCK[high1 + high2 + 1];
|
||||||
|
memset(res, 0, (high1 + high2 + 1) * sizeof(BLOCK));
|
||||||
|
|
||||||
|
size_t data_blocks = block_count(bin_size, data_size);
|
||||||
|
|
||||||
|
for (size_t t = block_count(bin_size, state_size); t > 0; --t)
|
||||||
|
{
|
||||||
|
memset(temp, 0, (high1 + high2 + 1) * sizeof(BLOCK));
|
||||||
|
//memcpy(temp, data, data_size * sizeof(size_t));
|
||||||
|
//ilsh(temp, data_size, bin_size, characteristic, t-1);
|
||||||
|
|
||||||
|
for (size_t tblk = 0; tblk < data_blocks; ++tblk) // Multiply each element
|
||||||
|
set_value(tblk + t - 1, get_value(tblk, bin_size, data) * get_value(t - 1, bin_size, *state), bin_size, characteristic, temp);
|
||||||
|
|
||||||
|
// Add shifted and multiplied value to state
|
||||||
|
iadd(temp, high1 + high2 + 1, bin_size, res, high1 + high2 + 1, characteristic);
|
||||||
|
}
|
||||||
|
delete[] *state;
|
||||||
|
*state = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API Galois::ModResult* Galois::imod(BLOCK * value, size_t value_size, BLOCK * modulo, size_t modulo_size, BLOCK * cmp, size_t cmp_size, BLOCK characteristic, size_t bin_size)
|
||||||
|
{
|
||||||
|
bool nb;
|
||||||
|
size_t mod_max = high_factor(modulo, modulo_size, bin_size, &nb);
|
||||||
|
if (nb) return 0;
|
||||||
|
size_t cmp_max = high_factor(cmp, cmp_size, bin_size, &nb);
|
||||||
|
if (nb) return 0;
|
||||||
|
|
||||||
|
BLOCK * aligned = 0;
|
||||||
|
ModResult * result = new ModResult();
|
||||||
|
result->mod = new BLOCK[value_size];
|
||||||
|
result->mod_size = value_size;
|
||||||
|
memcpy(result->mod, value, value_size * sizeof(BLOCK));
|
||||||
|
|
||||||
|
result->div = 0;
|
||||||
|
|
||||||
|
LoopStart: // Loop start
|
||||||
|
// Loop evaluation
|
||||||
|
size_t idx = high_factor(result->mod, result->mod_size, bin_size, &nb);
|
||||||
|
if (nb || idx < cmp_max || (idx == cmp_max && result->mod[idx / (8 * sizeof(BLOCK))] < cmp[cmp_max / (8 * sizeof(BLOCK))])) goto LoopEnd; // Break
|
||||||
|
|
||||||
|
// Loop body
|
||||||
|
if (aligned == 0) {
|
||||||
|
aligned = new BLOCK[value_size];
|
||||||
|
result->div_size = (((idx - mod_max) * bin_size) / (8 * sizeof(BLOCK))) + 1;
|
||||||
|
result->div = new BLOCK[result->div_size];
|
||||||
|
memset(result->div, 0, result->div_size * sizeof(BLOCK));
|
||||||
|
}
|
||||||
|
memcpy(memset(aligned, 0, value_size * sizeof(BLOCK)), modulo, modulo_size * sizeof(BLOCK));
|
||||||
|
ilsh(aligned, value_size, bin_size, characteristic, idx - mod_max);
|
||||||
|
isub(aligned, value_size, bin_size, result->mod, value_size, characteristic);
|
||||||
|
|
||||||
|
set_value(idx - mod_max, (get_value(idx - mod_max, bin_size, result->div) + 1) % characteristic, bin_size, characteristic, result->div);
|
||||||
|
|
||||||
|
// End of loop body
|
||||||
|
goto LoopStart;
|
||||||
|
LoopEnd:
|
||||||
|
|
||||||
|
if (result->div == 0) {
|
||||||
|
result->div = new BLOCK[1]{0};
|
||||||
|
result->div_size = 1;
|
||||||
|
}
|
||||||
|
delete[] aligned;
|
||||||
|
|
||||||
|
// Stuff after loop
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API void Galois::ilsh(BLOCK * state, size_t state_size, size_t bin_size, BLOCK characteristic, size_t shiftc)
|
||||||
|
{
|
||||||
|
for (size_t t = block_count(bin_size, state_size); t > shiftc; --t)
|
||||||
|
set_value(t - 1, get_value(t - 1 - shiftc, bin_size, state), bin_size, characteristic, state);
|
||||||
|
for (size_t t = shiftc; t > 0; --t)
|
||||||
|
set_value(t - 1, 0, bin_size, characteristic, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API size_t Galois::_mask(size_t bits, bool side)
|
||||||
|
{
|
||||||
|
size_t result = 0;
|
||||||
|
for(size_t t = 0; t<bits; ++t) result = side?(result<<1)|1:(result>>1)|high_bit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API BLOCK Galois::get_value(size_t index, size_t block_size, BLOCK * from)
|
||||||
|
{
|
||||||
|
// Compute block/sub-block indexing
|
||||||
|
size_t upper_bit_size = ((block_size*index)%(8*sizeof(BLOCK)))% block_size;
|
||||||
|
size_t upper_block_index = (index*block_size)/(8 * sizeof(BLOCK));
|
||||||
|
size_t lower_block_index = ((index - upper_bit_size)*block_size)/ (8 * sizeof(BLOCK));
|
||||||
|
|
||||||
|
// Boundary disparity check
|
||||||
|
if(upper_block_index!=lower_block_index)
|
||||||
|
{
|
||||||
|
// Get block values
|
||||||
|
size_t upper_block = from[upper_block_index] & _mask(upper_bit_size, true);
|
||||||
|
size_t lower_block = from[lower_block_index] & _mask(block_size -upper_bit_size, false);
|
||||||
|
|
||||||
|
// Do alignment
|
||||||
|
BLOCK block = (upper_block << (block_size - upper_bit_size)) | (lower_block >> ((sizeof(BLOCK)*8)-upper_bit_size));
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Passed: no boundary disparity
|
||||||
|
size_t shift = (block_size * index) % (8 * sizeof(BLOCK));
|
||||||
|
size_t block_index = (block_size * index) / (8 * sizeof(BLOCK));
|
||||||
|
|
||||||
|
// Get and mask
|
||||||
|
return from[block_index] >> shift & _mask(block_size, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API void Galois::set_value(size_t index, BLOCK value, size_t block_size, BLOCK characteristic, BLOCK * to)
|
||||||
|
{
|
||||||
|
value = value % characteristic;
|
||||||
|
|
||||||
|
// Compute block/sub-block indexing
|
||||||
|
size_t upper_bit_size = ((block_size*index)%(8*sizeof(BLOCK)))%block_size;
|
||||||
|
size_t upper_block_index = (index*block_size)/8;
|
||||||
|
size_t lower_block_index = ((index - upper_bit_size)*block_size)/8;
|
||||||
|
|
||||||
|
// Boundary disparity check
|
||||||
|
if(upper_block_index!=lower_block_index)
|
||||||
|
{
|
||||||
|
// Mask bits
|
||||||
|
to[upper_block_index] &= ~_mask(upper_bit_size, true);
|
||||||
|
to[lower_block_index] &= ~_mask(block_size - upper_bit_size, false);
|
||||||
|
|
||||||
|
// Get block values
|
||||||
|
to[upper_block_index] |= value >> (block_size - upper_bit_size);
|
||||||
|
to[lower_block_index] |= (value & _mask(block_size -upper_bit_size, false)) << ((8 * sizeof(BLOCK)) - (block_size - upper_bit_size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Passed: no boundary disparity
|
||||||
|
size_t shift = (block_size * index) % (8 * sizeof(BLOCK));
|
||||||
|
size_t block_index = (block_size * index) / (8 * sizeof(BLOCK));
|
||||||
|
|
||||||
|
// Mask bits
|
||||||
|
to[block_index] &= ~(_mask(block_size, true) << shift);
|
||||||
|
|
||||||
|
// Apply shift
|
||||||
|
to[block_index] |= value << shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GALOIS_API size_t Galois::high_factor(BLOCK * state, size_t state_size, size_t bin_size, bool * noBits)
|
||||||
|
{
|
||||||
|
if(noBits!=0) *noBits = false;
|
||||||
|
for (size_t t = block_count(bin_size, state_size); t > 0; --t)
|
||||||
|
if (get_value(t - 1, bin_size, state))
|
||||||
|
return t - 1;
|
||||||
|
if (noBits != 0) *noBits = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,86 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(__MINGW32__) || defined(_WIN32)
|
||||||
|
|
||||||
|
#if defined(GALOIS_API)
|
||||||
|
#undef GALOIS_API
|
||||||
|
#define GALOIS_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define GALOIS_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GALOIS_API
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define GALOIS_API __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
#define GALOIS_API
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BLOCK size_t
|
||||||
|
|
||||||
namespace CryptoCPP {
|
namespace CryptoCPP {
|
||||||
namespace Math {
|
namespace Math {
|
||||||
class Galois
|
class Galois
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Galois(size_t characteristic, size_t exponent, size_t irreducible);
|
GALOIS_API Galois(
|
||||||
|
BLOCK characteristic,
|
||||||
|
BLOCK * irreducible,
|
||||||
|
size_t irreducible_size,
|
||||||
|
BLOCK * value,
|
||||||
|
size_t value_size
|
||||||
|
);
|
||||||
|
GALOIS_API Galois(
|
||||||
|
BLOCK characteristic,
|
||||||
|
BLOCK irreducible,
|
||||||
|
BLOCK value
|
||||||
|
);
|
||||||
|
GALOIS_API Galois(const Galois & copy);
|
||||||
|
GALOIS_API ~Galois();
|
||||||
|
|
||||||
Galois * add(const Galois * value) const; // Add
|
// Addition
|
||||||
Galois * sub(const Galois * value) const; // Subtract
|
GALOIS_API Galois * add(const Galois * value) const;
|
||||||
Galois * mul(const Galois * value) const; // Multiply
|
|
||||||
Galois * inv(const Galois * value) const; // Inverse multiply
|
|
||||||
|
|
||||||
|
// Subtraction
|
||||||
|
GALOIS_API Galois * sub(const Galois * value) const;
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
GALOIS_API Galois * mul(const Galois * value) const;
|
||||||
|
|
||||||
|
// Inverse multiplication
|
||||||
|
GALOIS_API Galois * inv() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t characteristic, exponent, irreducible;
|
static const BLOCK high_bit = 1 << ((sizeof(BLOCK) * 8) - 1);
|
||||||
|
// GF parameters & value
|
||||||
|
BLOCK characteristic, *irreducible, *data;
|
||||||
|
// Storage params
|
||||||
|
size_t binary_block_size, data_size, irreducible_size, exponent;
|
||||||
|
|
||||||
// Reduce the value of this galois to one that fits the field parameters
|
|
||||||
void reduce();
|
|
||||||
|
|
||||||
// Self-mutable operations
|
struct ModResult {
|
||||||
void iadd(const Galois * value);
|
BLOCK * div;
|
||||||
void isub(const Galois * value);
|
size_t div_size;
|
||||||
void imul(const Galois * value);
|
BLOCK * mod;
|
||||||
void iinv(const Galois * value);
|
size_t mod_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Logic
|
||||||
|
GALOIS_API static void iadd(BLOCK * data, size_t data_size, size_t bin_size, BLOCK * state, size_t state_size, BLOCK characteristic); // Addition
|
||||||
|
GALOIS_API static void isub(BLOCK * data, size_t data_size, size_t bin_size, BLOCK * state, size_t state_size, BLOCK characteristic); // Subtraction
|
||||||
|
GALOIS_API static void imul(BLOCK * data, size_t data_size, size_t bin_size, BLOCK ** state, size_t state_size, BLOCK characteristic, size_t high1, size_t high2); // Multiplication
|
||||||
|
GALOIS_API static ModResult* imod(BLOCK * value, size_t value_size, BLOCK * modulo, size_t modulo_size, BLOCK * cmp, size_t cmp_size, BLOCK characteristic, size_t bin_size);
|
||||||
|
GALOIS_API static void ilsh(BLOCK * state, size_t state_size, size_t bin_size, BLOCK characteristic, size_t shiftc); // Left shift
|
||||||
|
|
||||||
|
// Data management. Don't look at these unless you want a headache
|
||||||
|
GALOIS_API static BLOCK _mask(size_t bits, bool side);
|
||||||
|
GALOIS_API static BLOCK get_value(size_t idx, size_t block_size, BLOCK * from);
|
||||||
|
GALOIS_API static void set_value(size_t idx, BLOCK value, size_t block_size, BLOCK characteristic, BLOCK * to);
|
||||||
|
GALOIS_API static size_t high_factor(BLOCK * state, size_t state_size, size_t bin_size, bool * noBits);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#define MATRIX_API
|
#define MATRIX_API
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
namespace CryptoCPP {
|
namespace CryptoCPP {
|
||||||
namespace Math {
|
namespace Math {
|
||||||
@ -20,13 +21,13 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
MATRIX_API long long Vector::at(size_t index) const
|
MATRIX_API long long Vector::at(size_t index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= count) throw new std::exception("Index out of bounds");
|
if (index < 0 || index >= count) throw new std::exception(); // Index out of bounds
|
||||||
return valueSet[index];
|
return valueSet[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API long long Vector::at(size_t index, long long newval)
|
MATRIX_API long long Vector::at(size_t index, long long newval)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= count) throw new std::exception("Index out of bounds");
|
if (index < 0 || index >= count) throw new std::exception(); // Index out of bounds
|
||||||
long long l = valueSet[index];
|
long long l = valueSet[index];
|
||||||
valueSet[index] = newval;
|
valueSet[index] = newval;
|
||||||
return l;
|
return l;
|
||||||
@ -40,12 +41,12 @@ namespace CryptoCPP {
|
|||||||
this->context = context;
|
this->context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* DelegatingFPTR::operator()(const Vector & input, size_t index) const
|
MATRIX_API const DelegatingFPTR DelegatingFPTR::operator()(const Vector & input, size_t index) const
|
||||||
{
|
{
|
||||||
return (context->*impl)(input, index);
|
return (context->*impl)(input, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* DelegatingFPTR::operator()(Vector * input, size_t index) const
|
MATRIX_API const DelegatingFPTR DelegatingFPTR::operator()(Vector * input, size_t index) const
|
||||||
{
|
{
|
||||||
return (context->*point)(input, index);
|
return (context->*point)(input, index);
|
||||||
}
|
}
|
||||||
@ -72,59 +73,59 @@ namespace CryptoCPP {
|
|||||||
delete[] columns;
|
delete[] columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_row(const Vector & row, size_t rowidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_row(const Vector & row, size_t rowidx)
|
||||||
{
|
{
|
||||||
return set_row_r(row, rowidx);
|
return set_row_r(row, rowidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_col(const Vector & col, size_t colidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_col(const Vector & col, size_t colidx)
|
||||||
{
|
{
|
||||||
return set_col_r(col, colidx);
|
return set_col_r(col, colidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_row(Vector * row, size_t rowidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_row(Vector * row, size_t rowidx)
|
||||||
{
|
{
|
||||||
return set_row_p(row, rowidx);
|
return set_row_p(row, rowidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_col(Vector * col, size_t colidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_col(Vector * col, size_t colidx)
|
||||||
{
|
{
|
||||||
return set_col_p(col, colidx);
|
return set_col_p(col, colidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_row_r(const Vector & row, size_t rowidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_row_r(const Vector & row, size_t rowidx)
|
||||||
{
|
{
|
||||||
if (rowidx >= height) throw new std::exception("Row index out of bounds");
|
if (rowidx >= height) throw new std::exception(); // Index out of bounds
|
||||||
size_t min = row.count < width ? row.count : width;
|
size_t min = row.count < width ? row.count : width;
|
||||||
for (size_t t = 0; t < min; ++t) columns[t]->at(rowidx, row.at(t));
|
for (size_t t = 0; t < min; ++t) columns[t]->at(rowidx, row.at(t));
|
||||||
return ar;
|
return *ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_col_r(const Vector & col, size_t colidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_col_r(const Vector & col, size_t colidx)
|
||||||
{
|
{
|
||||||
if (colidx >= width) throw new std::exception("Column index out of bounds");
|
if (colidx >= width) throw new std::exception(); // Index out of bounds
|
||||||
size_t min = col.count < height ? col.count : height;
|
size_t min = col.count < height ? col.count : height;
|
||||||
for (size_t t = 0; t < height; ++t) columns[colidx]->at(t, col.at(t));
|
for (size_t t = 0; t < height; ++t) columns[colidx]->at(t, col.at(t));
|
||||||
return ac;
|
return *ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_row_p(Vector * row, size_t rowidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_row_p(Vector * row, size_t rowidx)
|
||||||
{
|
{
|
||||||
const DelegatingFPTR * chain = set_row((const Vector&) *row, rowidx);
|
const DelegatingFPTR chain = set_row((const Vector&) *row, rowidx);
|
||||||
delete row;
|
delete row;
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* Matrix::set_col_p(Vector * col, size_t colidx)
|
MATRIX_API const DelegatingFPTR Matrix::set_col_p(Vector * col, size_t colidx)
|
||||||
{
|
{
|
||||||
const DelegatingFPTR * chain = set_col((const Vector&) *col, colidx);
|
const DelegatingFPTR chain = set_col((const Vector&) *col, colidx);
|
||||||
delete col;
|
delete col;
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API long long Matrix::set_at(size_t col, size_t row, long long value)
|
MATRIX_API long long Matrix::set_at(size_t col, size_t row, long long value)
|
||||||
{
|
{
|
||||||
if (col < 0 || col >= width || row < 0 || row >= height) throw new std::exception("Index out of bounds");
|
if (col < 0 || col >= width || row < 0 || row >= height) throw new std::exception(); // Index out of bounds
|
||||||
return columns[col]->at(row, value);
|
return columns[col]->at(row, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +136,7 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
MATRIX_API Vector * Matrix::at_row(size_t index) const
|
MATRIX_API Vector * Matrix::at_row(size_t index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= height) throw new std::exception("Index out of bounds");
|
if (index < 0 || index >= height) throw new std::exception(); // Index out of bounds
|
||||||
Vector * collect = new Vector(width);
|
Vector * collect = new Vector(width);
|
||||||
for (size_t t = 0; t < width; ++t)
|
for (size_t t = 0; t < width; ++t)
|
||||||
collect->at(t, columns[t]->at(index));
|
collect->at(t, columns[t]->at(index));
|
||||||
@ -144,7 +145,7 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
MATRIX_API Vector * Matrix::at_col(size_t index) const
|
MATRIX_API Vector * Matrix::at_col(size_t index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= width) throw new std::exception("Index out of bounds");
|
if (index < 0 || index >= width) throw new std::exception(); // Index out of bounds
|
||||||
Vector * collect = new Vector(height);
|
Vector * collect = new Vector(height);
|
||||||
for (size_t t = 0; t < height; ++t)
|
for (size_t t = 0; t < height; ++t)
|
||||||
collect->at(t, columns[index]->at(t));
|
collect->at(t, columns[index]->at(t));
|
||||||
@ -153,7 +154,7 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
MATRIX_API long long Matrix::at(size_t col, size_t row) const
|
MATRIX_API long long Matrix::at(size_t col, size_t row) const
|
||||||
{
|
{
|
||||||
if (col < 0 || col >= width || row < 0 || row >= height) throw new std::exception("Index out of bounds");
|
if (col < 0 || col >= width || row < 0 || row >= height) throw new std::exception(); // Index out of bounds
|
||||||
return columns[col]->at(row);
|
return columns[col]->at(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +165,7 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
MATRIX_API Matrix * Matrix::mul(const Matrix & factor) const
|
MATRIX_API Matrix * Matrix::mul(const Matrix & factor) const
|
||||||
{
|
{
|
||||||
if (factor.height != width) throw new std::exception("Mismatched dimensions");
|
if (factor.height != width) throw new std::exception(); // Index out of bounds
|
||||||
Matrix* result = new Matrix(height, factor.width);
|
Matrix* result = new Matrix(height, factor.width);
|
||||||
for (size_t i = 0; i < factor.width; ++i)
|
for (size_t i = 0; i < factor.width; ++i)
|
||||||
for (size_t j = 0; j < height; ++j)
|
for (size_t j = 0; j < height; ++j)
|
||||||
@ -197,10 +198,10 @@ namespace CryptoCPP {
|
|||||||
return mul(scalar);
|
return mul(scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
MATRIX_API Matrix * Matrix::minor(size_t row, size_t col) const
|
MATRIX_API Matrix * Matrix::get_minor(size_t row, size_t col) const
|
||||||
{
|
{
|
||||||
if (height == 0 || width == 0) return new Matrix(0, 0);
|
if (height == 0 || width == 0) return new Matrix(0, 0);
|
||||||
if (row >= height || col >= width) throw new std::exception("Index out of bounds");
|
if (row >= height || col >= width) throw new std::exception(); // Index out of bounds
|
||||||
Matrix* result = new Matrix(height - 1, width - 1);
|
Matrix* result = new Matrix(height - 1, width - 1);
|
||||||
for (size_t i = 0; i < width; ++i) {
|
for (size_t i = 0; i < width; ++i) {
|
||||||
if (i == col) continue;
|
if (i == col) continue;
|
||||||
@ -215,8 +216,8 @@ namespace CryptoCPP {
|
|||||||
MATRIX_API long long Matrix::det() const
|
MATRIX_API long long Matrix::det() const
|
||||||
{
|
{
|
||||||
// Matrix safety checks
|
// Matrix safety checks
|
||||||
if (height != width) throw new std::exception("Matrix must be square to compute the determinant");
|
if (height != width) throw new std::exception(); // Only square matrices have determinants
|
||||||
if (!height) throw new std::exception("Zero-matrix does not have a determinant");
|
if (!height) throw new std::exception(); // Zero-matrix doesn't have a determinant
|
||||||
|
|
||||||
// Compute determinant for 1x1 matrix
|
// Compute determinant for 1x1 matrix
|
||||||
if (height == 1) return columns[0]->at(0);
|
if (height == 1) return columns[0]->at(0);
|
||||||
@ -224,7 +225,7 @@ namespace CryptoCPP {
|
|||||||
// Compute determinant for higher-order matrices
|
// Compute determinant for higher-order matrices
|
||||||
long long result = 0;
|
long long result = 0;
|
||||||
for (size_t t = 0; t < width; ++t) {
|
for (size_t t = 0; t < width; ++t) {
|
||||||
Matrix * smaller = minor(0, t); // Compute minor
|
Matrix * smaller = get_minor(0, t); // Compute minor
|
||||||
result += smaller->det() * columns[t]->at(0) * (long long)((t % 2) ? -1 : 1); // Compute partial determinant for the given minor
|
result += smaller->det() * columns[t]->at(0) * (long long)((t % 2) ? -1 : 1); // Compute partial determinant for the given minor
|
||||||
delete smaller; // Delete allocated minor
|
delete smaller; // Delete allocated minor
|
||||||
}
|
}
|
||||||
@ -232,4 +233,4 @@ namespace CryptoCPP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,25 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef MATRIX_API
|
#if defined(__MINGW32__) || defined(_WIN32)
|
||||||
#define MATRIX_API __declspec(dllexport)
|
|
||||||
#else
|
#if defined(MATRIX_API)
|
||||||
#define MATRIX_API __declspec(dllimport)
|
#define MATRIX_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define MATRIX_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MATRIX_API
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define MATRIX_API __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
#define MATRIX_API
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define WITH ->operator()
|
#define WITH ->operator()
|
||||||
|
|
||||||
namespace CryptoCPP {
|
namespace CryptoCPP {
|
||||||
@ -32,16 +45,15 @@ namespace CryptoCPP {
|
|||||||
|
|
||||||
|
|
||||||
class DelegatingFPTR;
|
class DelegatingFPTR;
|
||||||
typedef const DelegatingFPTR*(Matrix::*Delegate)(const Vector & input, size_t at);
|
typedef const DelegatingFPTR(Matrix::*Delegate)(const Vector & input, size_t at);
|
||||||
typedef const DelegatingFPTR*(Matrix::*PDelegate)(const Vector * input, size_t at);
|
typedef const DelegatingFPTR(Matrix::*PDelegate)(const Vector * input, size_t at);
|
||||||
|
|
||||||
class DelegatingFPTR {
|
class DelegatingFPTR {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DelegatingFPTR(Delegate impl, PDelegate point, Matrix* context);
|
DelegatingFPTR(Delegate impl, PDelegate point, Matrix* context);
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* operator()(const Vector & input, size_t index) const;
|
MATRIX_API const DelegatingFPTR operator()(const Vector & input, size_t index) const;
|
||||||
MATRIX_API const DelegatingFPTR* operator()(Vector * input, size_t index) const;
|
MATRIX_API const DelegatingFPTR operator()(Vector * input, size_t index) const;
|
||||||
protected:
|
protected:
|
||||||
Delegate impl;
|
Delegate impl;
|
||||||
PDelegate point;
|
PDelegate point;
|
||||||
@ -55,15 +67,15 @@ namespace CryptoCPP {
|
|||||||
MATRIX_API Matrix(const Matrix & copy);
|
MATRIX_API Matrix(const Matrix & copy);
|
||||||
MATRIX_API ~Matrix();
|
MATRIX_API ~Matrix();
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* set_row(const Vector & row, size_t rowidx);
|
MATRIX_API const DelegatingFPTR set_row(const Vector & row, size_t rowidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_col(const Vector & col, size_t colidx);
|
MATRIX_API const DelegatingFPTR set_col(const Vector & col, size_t colidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_row(Vector * row, size_t rowidx);
|
MATRIX_API const DelegatingFPTR set_row(Vector * row, size_t rowidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_col(Vector * col, size_t colidx);
|
MATRIX_API const DelegatingFPTR set_col(Vector * col, size_t colidx);
|
||||||
|
|
||||||
MATRIX_API const DelegatingFPTR* set_row_r(const Vector & row, size_t rowidx);
|
MATRIX_API const DelegatingFPTR set_row_r(const Vector & row, size_t rowidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_col_r(const Vector & col, size_t colidx);
|
MATRIX_API const DelegatingFPTR set_col_r(const Vector & col, size_t colidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_row_p(Vector * row, size_t rowidx);
|
MATRIX_API const DelegatingFPTR set_row_p(Vector * row, size_t rowidx);
|
||||||
MATRIX_API const DelegatingFPTR* set_col_p(Vector * col, size_t colidx);
|
MATRIX_API const DelegatingFPTR set_col_p(Vector * col, size_t colidx);
|
||||||
MATRIX_API long long set_at(size_t col, size_t row, long long value);
|
MATRIX_API long long set_at(size_t col, size_t row, long long value);
|
||||||
MATRIX_API long long set_at(size_t index, bool rowMajor, long long value);
|
MATRIX_API long long set_at(size_t index, bool rowMajor, long long value);
|
||||||
|
|
||||||
@ -79,7 +91,7 @@ namespace CryptoCPP {
|
|||||||
MATRIX_API Matrix* operator*(const Matrix * factor) const;
|
MATRIX_API Matrix* operator*(const Matrix * factor) const;
|
||||||
MATRIX_API Matrix* operator*(long long scalar) const;
|
MATRIX_API Matrix* operator*(long long scalar) const;
|
||||||
|
|
||||||
MATRIX_API Matrix* minor(size_t row, size_t col) const;
|
MATRIX_API Matrix* get_minor(size_t row, size_t col) const;
|
||||||
MATRIX_API long long det() const;
|
MATRIX_API long long det() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -90,4 +102,4 @@ namespace CryptoCPP {
|
|||||||
const size_t width;
|
const size_t width;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="BigInteger.cpp" />
|
<ClCompile Include="BigInteger.cpp" />
|
||||||
|
<ClCompile Include="Galois.cpp" />
|
||||||
<ClCompile Include="Matrix.cpp" />
|
<ClCompile Include="Matrix.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
<ClCompile Include="Matrix.cpp">
|
<ClCompile Include="Matrix.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Galois.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="BigInteger.h">
|
<ClInclude Include="BigInteger.h">
|
||||||
|
18
makefile
Normal file
18
makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
start:
|
||||||
|
$(info No recipe specified!)
|
||||||
|
|
||||||
|
xmath:
|
||||||
|
mkdir -p build/include
|
||||||
|
mkdir -p build/lib
|
||||||
|
mkdir -p XMath/intermediate
|
||||||
|
g++ -c XMath/BigInteger.cpp -o XMath/intermediate/BigInteger.o
|
||||||
|
g++ -c XMath/Matrix.cpp -o XMath/intermediate/Matrix.o
|
||||||
|
ar rcs build/lib/libxmath.a XMath/intermediate/*
|
||||||
|
cp XMath/*.h* build/include/
|
||||||
|
rm -r XMath/intermediate/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
mkdir -p build
|
||||||
|
rm -r build
|
||||||
|
mkdir -p XMath/intermediate
|
||||||
|
rm -r XMath/intermediate
|
Loading…
x
Reference in New Issue
Block a user