Updated Matrix class

- Implemented determinant function
  - Added more function overloads for convenience
  - Fixed some typing issues
  - Added semi-proper function chaining
Changed how Vectors handle recieving arrays
Fixed small issue with namespaces not being used
Started structuring Galois class
This commit is contained in:
Gabriel Tofvesson 2018-02-26 23:26:05 +01:00
parent fa54698850
commit 521cbe335f
5 changed files with 150 additions and 23 deletions

View File

@ -1,7 +1,41 @@
#include <iostream> #include <iostream>
#include "BigInteger.h" #include "BigInteger.h"
#include "Matrix.h"
using namespace CryptoCPP::Math;
int main() int main()
{ {
// Create a 2x2 matrix
// |1 2|
// |3 4|
Matrix * m = new Matrix(2, 2);
m->set_row
(new Vector(2, new long long[2]{ 1, 2 }), 0) WITH
(new Vector(2, new long long[2]{ 3, 4 }), 1);
// Create a 2x2 matrix
// |5 6|
// |7 8|
Matrix * m1 = new Matrix(2, 2);
m1->set_row
(new Vector(2, new long long[2]{ 5, 6 }), 0) WITH
(new Vector(2, new long long[2]{ 7, 8 }), 1);
// Multiply matrices
Matrix * res = (*m) * m1;
std::cout << "Matrix 'm':" << std::endl;
for (size_t t = 0; t < 4; ++t) std::cout << m->at(t, true) << ((t % 2) ? '\n' : ' ');
std::cout << "\nMatrix 'm1':" << std::endl;
for (size_t t = 0; t < 4; ++t) std::cout << m1->at(t, true) << ((t % 2) ? '\n' : ' ');
// Print result
std::cout << "\nMatrix 'res':" << std::endl;
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::cin.ignore();
return 0; return 0;
} }

View File

@ -11,11 +11,19 @@ namespace CryptoCPP {
Galois * sub(const Galois * value) const; // Subtract Galois * sub(const Galois * value) const; // Subtract
Galois * mul(const Galois * value) const; // Multiply Galois * mul(const Galois * value) const; // Multiply
Galois * inv(const Galois * value) const; // Inverse multiply Galois * inv(const Galois * value) const; // Inverse multiply
protected: protected:
size_t characteristic, exponent, irreducible; size_t characteristic, exponent, irreducible;
// Reduce the value of this galois to one that fits the field parameters // Reduce the value of this galois to one that fits the field parameters
void reduce(); void reduce();
// Self-mutable operations
void iadd(const Galois * value);
void isub(const Galois * value);
void imul(const Galois * value);
void iinv(const Galois * value);
}; };
} }
} }

View File

@ -9,9 +9,8 @@ namespace CryptoCPP {
memset(valueSet, 0, count * sizeof(long long)); memset(valueSet, 0, count * sizeof(long long));
} }
MATRIX_API Vector::Vector(size_t count, long long * values) : count(count), valueSet(new long long[count]) MATRIX_API Vector::Vector(size_t count, long long * values) : count(count), valueSet(values)
{ {
memcpy(valueSet, values, count * sizeof(long long));
} }
MATRIX_API Vector::~Vector() MATRIX_API Vector::~Vector()
@ -34,17 +33,22 @@ namespace CryptoCPP {
} }
DelegatingFPTR::DelegatingFPTR(Delegate impl, Matrix* context) DelegatingFPTR::DelegatingFPTR(Delegate impl, PDelegate point, Matrix* context)
{ {
this->impl = impl; this->impl = impl;
this->point = point;
this->context = context; this->context = context;
} }
MATRIX_API const DelegatingFPTR* DelegatingFPTR::operator()(const Vector & input, size_t index) 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
{
return (context->*point)(input, index);
}
Matrix::Matrix(size_t height, size_t width) : columns(new Vector*[width]), width(width), height(height) Matrix::Matrix(size_t height, size_t width) : columns(new Vector*[width]), width(width), height(height)
{ {
@ -66,26 +70,62 @@ namespace CryptoCPP {
for (size_t t = 0; t < width; ++t) for (size_t t = 0; t < width; ++t)
delete columns[t]; delete columns[t];
delete[] columns; delete[] columns;
// TODO: Add other deletions
} }
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)
{ {
if (rowidx < 0 || rowidx >= height) throw new std::exception("Index out of bounds"); return set_row_r(row, rowidx);
}
MATRIX_API const DelegatingFPTR* Matrix::set_col(const Vector & col, size_t colidx)
{
return set_col_r(col, colidx);
}
MATRIX_API const DelegatingFPTR* Matrix::set_row(Vector * row, size_t rowidx)
{
return set_row_p(row, rowidx);
}
MATRIX_API const DelegatingFPTR* Matrix::set_col(Vector * col, size_t colidx)
{
return set_col_p(col, colidx);
}
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");
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(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");
size_t min = col.count < height ? col.count : height;
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)
{
const DelegatingFPTR * chain = set_row((const Vector&) *row, rowidx);
delete row;
return chain;
}
MATRIX_API const DelegatingFPTR* Matrix::set_col_p(Vector * col, size_t colidx)
{
const DelegatingFPTR * chain = set_col((const Vector&) *col, colidx);
delete col;
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");
columns[col]->at(row, value); return columns[col]->at(row, value);
} }
MATRIX_API long long Matrix::set_at(size_t index, bool rowMajor, long long value) MATRIX_API long long Matrix::set_at(size_t index, bool rowMajor, long long value)
@ -126,9 +166,9 @@ namespace CryptoCPP {
{ {
if (factor.height != width) throw new std::exception("Mismatched dimensions"); if (factor.height != width) throw new std::exception("Mismatched dimensions");
Matrix* result = new Matrix(height, factor.width); Matrix* result = new Matrix(height, factor.width);
for (int i = 0; i < factor.width; ++i) for (size_t i = 0; i < factor.width; ++i)
for (int j = 0; j < height; ++j) for (size_t j = 0; j < height; ++j)
for (int k = 0; k < width; ++k) for (size_t k = 0; k < width; ++k)
result->columns[i]->at(j, result->columns[i]->at(j) + (factor.columns[i]->at(k) * columns[k]->at(j))); result->columns[i]->at(j, result->columns[i]->at(j) + (factor.columns[i]->at(k) * columns[k]->at(j)));
return result; return result;
} }
@ -142,12 +182,29 @@ namespace CryptoCPP {
return m; return m;
} }
MATRIX_API Matrix* Matrix::operator*(const Matrix & factor) const
{
return mul(factor);
}
MATRIX_API Matrix* Matrix::operator*(const Matrix * factor) const
{
return mul(*factor);
}
MATRIX_API Matrix* Matrix::operator*(long long scalar) const
{
return mul(scalar);
}
MATRIX_API Matrix * Matrix::minor(size_t row, size_t col) const MATRIX_API Matrix * Matrix::minor(size_t row, size_t col) const
{ {
if (height == 0 || width == 0) return new Matrix(0, 0);
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 (int i = 0; i < width; ++i) { for (size_t i = 0; i < width; ++i) {
if (i == col) continue; if (i == col) continue;
for (int j = 0; j < height; ++j) { for (size_t j = 0; j < height; ++j) {
if (j == row) continue; if (j == row) continue;
result->columns[i + ((i > col) ? -1 : 0)]->at(j + ((j > row) ? -1 : 0), columns[i]->at(j)); result->columns[i + ((i > col) ? -1 : 0)]->at(j + ((j > row) ? -1 : 0), columns[i]->at(j));
} }
@ -157,7 +214,21 @@ namespace CryptoCPP {
MATRIX_API long long Matrix::det() const MATRIX_API long long Matrix::det() const
{ {
return 0; // Matrix safety checks
if (height != width) throw new std::exception("Matrix must be square to compute the determinant");
if (!height) throw new std::exception("Zero-matrix does not have a determinant");
// Compute determinant for 1x1 matrix
if (height == 1) return columns[0]->at(0);
// Compute determinant for higher-order matrices
long long result = 0;
for (size_t t = 0; t < width; ++t) {
Matrix * smaller = 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
delete smaller; // Delete allocated minor
}
return result;
} }
} }

View File

@ -8,6 +8,7 @@
#define MATRIX_API __declspec(dllimport) #define MATRIX_API __declspec(dllimport)
#endif #endif
#define WITH ->operator()
namespace CryptoCPP { namespace CryptoCPP {
namespace Math { namespace Math {
@ -29,24 +30,26 @@ namespace CryptoCPP {
long long * const valueSet; long long * const valueSet;
}; };
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);
class DelegatingFPTR { class DelegatingFPTR {
public: public:
DelegatingFPTR(Delegate impl, Matrix* context); DelegatingFPTR(Delegate impl, PDelegate point, Matrix* context);
MATRIX_API const DelegatingFPTR* operator()(const Vector & input, size_t index); MATRIX_API const DelegatingFPTR* operator()(const 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;
Matrix* context; Matrix* context;
}; };
class Matrix class Matrix
{ {
friend class Vector;
friend class DelegatingFPTR;
public: public:
MATRIX_API Matrix(size_t height, size_t width); MATRIX_API Matrix(size_t height, size_t width);
MATRIX_API Matrix(const Matrix & copy); MATRIX_API Matrix(const Matrix & copy);
@ -54,6 +57,13 @@ namespace CryptoCPP {
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_col(Vector * col, size_t colidx);
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_row_p(Vector * row, size_t rowidx);
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);
@ -65,12 +75,16 @@ namespace CryptoCPP {
MATRIX_API Matrix* mul(const Matrix & factor) const; MATRIX_API Matrix* mul(const Matrix & factor) const;
MATRIX_API Matrix* mul(long long scalar) const; MATRIX_API Matrix* mul(long long scalar) const;
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* minor(size_t row, size_t col) const; MATRIX_API Matrix* minor(size_t row, size_t col) const;
MATRIX_API long long det() const; MATRIX_API long long det() const;
protected: protected:
const DelegatingFPTR* ar = new DelegatingFPTR(add_row, this); const DelegatingFPTR* ar = new DelegatingFPTR((Delegate)&Matrix::set_row_r, (PDelegate)&Matrix::set_row_p, this);
const DelegatingFPTR* ac = new DelegatingFPTR(add_col, this); const DelegatingFPTR* ac = new DelegatingFPTR((Delegate)&Matrix::set_col_r, (PDelegate)&Matrix::set_col_p, this);
Vector * * const columns; Vector * * const columns;
const size_t height; const size_t height;
const size_t width; const size_t width;

View File

@ -4,9 +4,9 @@
namespace CryptoCPP { namespace CryptoCPP {
namespace Primes { namespace Primes {
bool fermat_prime_test(const BigInteger & value, size_t certainty); bool fermat_prime_test(const Math::BigInteger & value, size_t certainty);
bool miller_rabin_prime_test(const BigInteger & value, size_t certainty); bool miller_rabin_prime_test(const Math::BigInteger & value, size_t certainty);
BigInteger * generate_prime(size_t byteCount, size_t certainty); Math::BigInteger * generate_prime(size_t byteCount, size_t certainty);
} }
} }