diff --git a/.gitignore b/.gitignore
index 3c4efe2..e941d87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ bld/
 [Bb]in/
 [Oo]bj/
 [Ll]og/
+build/
 
 # Visual Studio 2015 cache/options directory
 .vs/
@@ -258,4 +259,4 @@ paket-files/
 
 # Python Tools for Visual Studio (PTVS)
 __pycache__/
-*.pyc
\ No newline at end of file
+*.pyc
diff --git a/Crypto/Start.cpp b/Crypto/Start.cpp
index ab5390c..c7a8376 100644
--- a/Crypto/Start.cpp
+++ b/Crypto/Start.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include "BigInteger.h"
 #include "Matrix.h"
+#include "Galois.h"
 
 using namespace CryptoCPP::Math;
 
@@ -11,7 +12,7 @@ int main()
 	// |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]{ 1, 2 }), 0)
 	(new Vector(2, new long long[2]{ 3, 4 }), 1);
 
 	// Create a 2x2 matrix
@@ -19,7 +20,7 @@ int main()
 	// |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]{ 5, 6 }), 0)
 	(new Vector(2, new long long[2]{ 7, 8 }), 1);
 
 	// Multiply matrices
@@ -36,6 +37,10 @@ int main()
 	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;
+
+	Galois * g1 = new Galois(2, 0b100011011, 0b10);
+	Galois * g2 = new Galois(2, 0b100011011, 0b11);
+	Galois * g3 = g1->mul(g2);
 	std::cin.ignore();
 	return 0;
 }
\ No newline at end of file
diff --git a/XMath/BigInteger.cpp b/XMath/BigInteger.cpp
index e733ca1..854bd62 100644
--- a/XMath/BigInteger.cpp
+++ b/XMath/BigInteger.cpp
@@ -2,14 +2,15 @@
 
 #include "BigInteger.h"
 
+
 namespace CryptoCPP {
 	namespace Math {
-		BIGINT_API BigInteger::BigInteger(int64_t initialValue)
+		BIGINT_API BigInteger::BigInteger(long long initialValue)
 		{
 			data = new std::vector<BYTE>();
 
 			// 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);
 
 			sign = false;
@@ -93,14 +94,14 @@ namespace CryptoCPP {
 			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);
 			create->ishl(shiftcount);
 			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);
 			create->ishr(shiftcount);
@@ -157,13 +158,13 @@ namespace CryptoCPP {
 			return this;
 		}
 
-		BIGINT_API BigInteger* BigInteger::operator<<=(uint64_t shiftcount)
+		BIGINT_API BigInteger* BigInteger::operator<<=(size_t shiftcount)
 		{
 			ishl(shiftcount);
 			return this;
 		}
 
-		BIGINT_API BigInteger* BigInteger::operator>>=(uint64_t shiftcount)
+		BIGINT_API BigInteger* BigInteger::operator>>=(size_t shiftcount)
 		{
 			ishr(shiftcount);
 			return this;
@@ -338,7 +339,7 @@ namespace CryptoCPP {
 
 		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 quot = BigInteger(0);
 
@@ -403,7 +404,7 @@ namespace CryptoCPP {
 			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;
 			char sub = shift % 8;
@@ -430,7 +431,7 @@ namespace CryptoCPP {
 			clip_zeroes();
 		}
 
-		BIGINT_API void BigInteger::ishr(uint64_t shift)
+		BIGINT_API void BigInteger::ishr(size_t shift)
 		{
 			size_t offset = shift / 8;
 			char sub = shift % 8;
@@ -491,10 +492,10 @@ namespace CryptoCPP {
 			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;
-			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;
 		}
 
@@ -547,4 +548,5 @@ namespace CryptoCPP {
 		}
 
 	}
-}
\ No newline at end of file
+}
+
diff --git a/XMath/BigInteger.h b/XMath/BigInteger.h
index 97b495b..36f2739 100644
--- a/XMath/BigInteger.h
+++ b/XMath/BigInteger.h
@@ -2,11 +2,23 @@
 
 #include <vector>
 
-#ifdef BIGINT_API
-#define BIGINT_API __declspec(dllexport)   
-#else  
-#define BIGINT_API __declspec(dllimport)   
-#endif  
+#if defined(__MINGW32__) || defined(_WIN32)
+
+#if defined(BIGINT_API)
+#define BIGINT_API __declspec(dllexport)
+#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
 
@@ -16,7 +28,7 @@ namespace CryptoCPP {
 		class BigInteger
 		{
 		public:
-			BIGINT_API BigInteger(int64_t initialValue);
+			BIGINT_API BigInteger(long long initialValue);
 			BIGINT_API BigInteger(const BigInteger& initialvalue);
 
 			// 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;
-			BIGINT_API BigInteger* operator<<(uint64_t shiftcount) const;
-			BIGINT_API BigInteger* operator>>(uint64_t shiftcount) const;
+			BIGINT_API BigInteger* operator<<(size_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);
@@ -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<<=(uint64_t shiftcount);
-			BIGINT_API BigInteger* operator>>=(uint64_t shiftcount);
+			BIGINT_API BigInteger* operator<<=(size_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;
@@ -66,8 +78,8 @@ namespace CryptoCPP {
 			BIGINT_API void iand(const BigInteger& val, bool swaptarget);
 			BIGINT_API void ior(const BigInteger& val, bool swaptarget);
 			BIGINT_API void inot();
-			BIGINT_API void ishl(uint64_t shift);
-			BIGINT_API void ishr(uint64_t shift);
+			BIGINT_API void ishl(size_t shift);
+			BIGINT_API void ishr(size_t shift);
 			BIGINT_API void twos_complement();
 			BIGINT_API void set_bit(size_t index, bool value);
 			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;
 
 			// 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
 			BIGINT_API void clip_zeroes();
@@ -85,4 +97,5 @@ namespace CryptoCPP {
 			BIGINT_API bool is_zero() const;
 		};
 	}
-}
\ No newline at end of file
+}
+
diff --git a/XMath/Galois.cpp b/XMath/Galois.cpp
new file mode 100644
index 0000000..880290a
--- /dev/null
+++ b/XMath/Galois.cpp
@@ -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;
+		}
+	}
+}
diff --git a/XMath/Galois.h b/XMath/Galois.h
index d238355..6db5968 100644
--- a/XMath/Galois.h
+++ b/XMath/Galois.h
@@ -1,29 +1,86 @@
 #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 Math {
 		class Galois
 		{
 		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
-			Galois * sub(const Galois * value) const; // Subtract
-			Galois * mul(const Galois * value) const; // Multiply
-			Galois * inv(const Galois * value) const; // Inverse multiply
+			// Addition
+			GALOIS_API Galois * add(const Galois * value) const;
 
+			// 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:
-			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
-			void iadd(const Galois * value);
-			void isub(const Galois * value);
-			void imul(const Galois * value);
-			void iinv(const Galois * value);
+			struct ModResult {
+				BLOCK * div;
+				size_t div_size;
+				BLOCK * mod;
+				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);
 		};
 	}
-}
\ No newline at end of file
+}
diff --git a/XMath/Matrix.cpp b/XMath/Matrix.cpp
index cba4dbb..b8f7355 100644
--- a/XMath/Matrix.cpp
+++ b/XMath/Matrix.cpp
@@ -1,5 +1,6 @@
 #define MATRIX_API
 #include "Matrix.h"
+#include <string.h>
 
 namespace CryptoCPP {
 	namespace Math {
@@ -20,13 +21,13 @@ namespace CryptoCPP {
 
 		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];
 		}
 
 		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];
 			valueSet[index] = newval;
 			return l;
@@ -40,12 +41,12 @@ namespace CryptoCPP {
 			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);
 		}
 
-		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);
 		}
@@ -72,59 +73,59 @@ namespace CryptoCPP {
 			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);
 		}
 
-		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);
 		}
 
-		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);
 		}
 
-		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);
 		}
 
-		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;
 			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;
 			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;
 			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;
 			return chain;
 		}
 
 		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);
 		}
 
@@ -135,7 +136,7 @@ namespace CryptoCPP {
 
 		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);
 			for (size_t t = 0; t < width; ++t)
 				collect->at(t, columns[t]->at(index));
@@ -144,7 +145,7 @@ namespace CryptoCPP {
 
 		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);
 			for (size_t t = 0; t < height; ++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
 		{
-			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);
 		}
 
@@ -164,7 +165,7 @@ namespace CryptoCPP {
 
 		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);
 			for (size_t i = 0; i < factor.width; ++i)
 				for (size_t j = 0; j < height; ++j)
@@ -197,10 +198,10 @@ namespace CryptoCPP {
 			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 (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);
 			for (size_t i = 0; i < width; ++i) {
 				if (i == col) continue;
@@ -215,8 +216,8 @@ namespace CryptoCPP {
 		MATRIX_API long long Matrix::det() const
 		{
 			// 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");
+			if (height != width) throw new std::exception(); // Only square matrices have determinants
+			if (!height) throw new std::exception(); // Zero-matrix doesn't have a determinant
 
 			// Compute determinant for 1x1 matrix
 			if (height == 1) return columns[0]->at(0);
@@ -224,7 +225,7 @@ namespace CryptoCPP {
 			// 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
+				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
 				delete smaller;																	// Delete allocated minor
 			}
@@ -232,4 +233,4 @@ namespace CryptoCPP {
 		}
 
 	}
-}
\ No newline at end of file
+}
diff --git a/XMath/Matrix.h b/XMath/Matrix.h
index 370e7cc..ddde0bd 100644
--- a/XMath/Matrix.h
+++ b/XMath/Matrix.h
@@ -2,12 +2,25 @@
 
 #include <vector>
 
-#ifdef MATRIX_API
-#define MATRIX_API __declspec(dllexport)   
-#else  
-#define MATRIX_API __declspec(dllimport)   
+#if defined(__MINGW32__) || defined(_WIN32)
+
+#if defined(MATRIX_API)
+#define MATRIX_API __declspec(dllexport)
+#else
+#define MATRIX_API __declspec(dllimport)
 #endif
 
+#endif
+
+#ifndef MATRIX_API
+  #if __GNUC__ >= 4
+    #define MATRIX_API __attribute__ ((visibility ("default")))
+  #else
+    #define MATRIX_API
+  #endif
+#endif
+
+
 #define WITH ->operator()
 
 namespace CryptoCPP {
@@ -32,16 +45,15 @@ namespace CryptoCPP {
 
 
 		class DelegatingFPTR;
-		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::*Delegate)(const Vector & input, size_t at);
+		typedef const DelegatingFPTR(Matrix::*PDelegate)(const Vector * input, size_t at);
 
 		class DelegatingFPTR {
 		public:
-
 			DelegatingFPTR(Delegate impl, PDelegate point, Matrix* context);
 
-			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()(const Vector & input, size_t index) const;
+			MATRIX_API const DelegatingFPTR operator()(Vector * input, size_t index) const;
 		protected:
 			Delegate impl;
 			PDelegate point;
@@ -55,15 +67,15 @@ namespace CryptoCPP {
 			MATRIX_API Matrix(const Matrix & copy);
 			MATRIX_API ~Matrix();
 
-			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_row(Vector * row, size_t rowidx);
-			MATRIX_API const DelegatingFPTR* set_col(Vector * col, size_t colidx);
+			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_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 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 index, bool rowMajor, long long value);
 
@@ -79,7 +91,7 @@ namespace CryptoCPP {
 			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* get_minor(size_t row, size_t col) const;
 			MATRIX_API long long det() const;
 
 		protected:
@@ -90,4 +102,4 @@ namespace CryptoCPP {
 			const size_t width;
 		};
 	}
-}
\ No newline at end of file
+}
diff --git a/XMath/XMath.vcxproj b/XMath/XMath.vcxproj
index 03c7612..bc65f77 100644
--- a/XMath/XMath.vcxproj
+++ b/XMath/XMath.vcxproj
@@ -122,6 +122,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="BigInteger.cpp" />
+    <ClCompile Include="Galois.cpp" />
     <ClCompile Include="Matrix.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/XMath/XMath.vcxproj.filters b/XMath/XMath.vcxproj.filters
index f72a80e..c80218e 100644
--- a/XMath/XMath.vcxproj.filters
+++ b/XMath/XMath.vcxproj.filters
@@ -21,6 +21,9 @@
     <ClCompile Include="Matrix.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Galois.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="BigInteger.h">
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..a6e0a85
--- /dev/null
+++ b/makefile
@@ -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