From 1448af586deb9c0d58fbf89f4ff93f90f1cb82c6 Mon Sep 17 00:00:00 2001
From: GabrielTofvesson <gabriel.tofvesson@gmail.com>
Date: Mon, 26 Feb 2018 01:30:53 +0100
Subject: [PATCH] Implemented BigInteger (semi-tested)   - Added operator
 overloads for all operations   - Added internal functions that modify the
 value is is called on, as opposed to creating a new object Changed some
 settings

---
 AES/AES.vcxproj             |   2 +-
 Crypto/Crypto.vcxproj       |   6 +
 Crypto/Start.cpp            |   2 +
 RSA/RSA.vcxproj             |   2 +-
 SHA1/SHA1.vcxproj           |   2 +-
 XMath/BigInteger.cpp        | 475 +++++++++++++++++++++++++++++++++---
 XMath/BigInteger.h          |  89 +++++--
 XMath/XMath.vcxproj         |   2 +-
 XMath/XMath.vcxproj.filters |  10 +-
 9 files changed, 518 insertions(+), 72 deletions(-)

diff --git a/AES/AES.vcxproj b/AES/AES.vcxproj
index d5d7bb0..3f9fe5e 100644
--- a/AES/AES.vcxproj
+++ b/AES/AES.vcxproj
@@ -26,7 +26,7 @@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
diff --git a/Crypto/Crypto.vcxproj b/Crypto/Crypto.vcxproj
index 4c56918..42e9a96 100644
--- a/Crypto/Crypto.vcxproj
+++ b/Crypto/Crypto.vcxproj
@@ -77,6 +77,7 @@
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
       <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>C:\Users\Lenovo\source\repos\Crypto\XMath;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -118,6 +119,11 @@
   <ItemGroup>
     <ClCompile Include="Start.cpp" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\XMath\XMath.vcxproj">
+      <Project>{5f9ad03f-b1f0-4db3-b39a-49b66895774c}</Project>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
diff --git a/Crypto/Start.cpp b/Crypto/Start.cpp
index 3997abd..6024f33 100644
--- a/Crypto/Start.cpp
+++ b/Crypto/Start.cpp
@@ -1,6 +1,8 @@
 #include <iostream>
+#include "BigInteger.h"
 
 int main()
 {
+
 	return 0;
 }
\ No newline at end of file
diff --git a/RSA/RSA.vcxproj b/RSA/RSA.vcxproj
index bbfc7ae..1535b66 100644
--- a/RSA/RSA.vcxproj
+++ b/RSA/RSA.vcxproj
@@ -26,7 +26,7 @@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
diff --git a/SHA1/SHA1.vcxproj b/SHA1/SHA1.vcxproj
index 82395bd..71239a8 100644
--- a/SHA1/SHA1.vcxproj
+++ b/SHA1/SHA1.vcxproj
@@ -26,7 +26,7 @@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
diff --git a/XMath/BigInteger.cpp b/XMath/BigInteger.cpp
index 6913d09..b2761a0 100644
--- a/XMath/BigInteger.cpp
+++ b/XMath/BigInteger.cpp
@@ -1,122 +1,521 @@
+#define BIGINT_API
+
 #include "BigInteger.h"
 
-BigInteger::BigInteger(int64_t initialValue)
+BIGINT_API BigInteger::BigInteger(int64_t initialValue)
 {
-	data = new std::vector<char>();
+	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);
 	for (size_t t = 0; t < bytes; ++t) data->push_back((initialValue >> (t * 8)) & 255);
+
+	sign = false;
+
+	if (initialValue < 0) {
+		sign = 1;
+		twos_complement();  // Compute two's complement of this value
+	}
+
+	clip_zeroes();
 }
 
-BigInteger::BigInteger(BigInteger & initialvalue)
+BIGINT_API BigInteger::BigInteger(const BigInteger & initialvalue)
 {
 	size_t size = initialvalue.data->size();
-	data = new std::vector<char>(size);
-	for (size_t t = 0; t < size; ++t) data->push_back(initialvalue.data->at(t));
+	data = new std::vector<BYTE>(size);
+	for (size_t t = 0; t < size; ++t) (*data)[t] = (*initialvalue.data)[t];
 	sign = initialvalue.sign;
 }
 
-BigInteger * BigInteger::operator+(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator+(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->iadd(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator*(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator-(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->isub(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator/(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator*(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->imul(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator^(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator/(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->idiv(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator&(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator%(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->imod(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator|(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator^(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->ixor(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator~()
+BIGINT_API BigInteger * BigInteger::operator&(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->iand(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator<<(int64_t shiftcount)
+BIGINT_API BigInteger * BigInteger::operator|(const BigInteger & val) const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->ior(val, false);
+	return create;
 }
 
-BigInteger * BigInteger::operator>>(int64_t shiftcount)
+BIGINT_API BigInteger * BigInteger::operator~() const
 {
-	return nullptr;
+	BigInteger* create = new BigInteger(*this);
+	create->inot();
+	return create;
 }
 
-void BigInteger::iadd(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator<<(uint64_t shiftcount) const
 {
+	BigInteger* create = new BigInteger(*this);
+	create->ishl(shiftcount);
+	return create;
 }
 
-void BigInteger::isub(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator>>(uint64_t shiftcount) const
 {
+	BigInteger* create = new BigInteger(*this);
+	create->ishr(shiftcount);
+	return create;
 }
 
-void BigInteger::imul(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator+(const BigInteger * val) const
 {
+	return operator+(*val);
 }
 
-void BigInteger::idiv(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator-(const BigInteger * val) const
 {
+	return operator-(*val);
 }
 
-void BigInteger::ixor(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator*(const BigInteger * val) const
 {
+	return operator*(*val);
 }
 
-void BigInteger::iand(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator/(const BigInteger * val) const
 {
+	return operator/(*val);
 }
 
-void BigInteger::ior(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator%(const BigInteger * val) const
 {
+	return operator%(*val);
 }
 
-void BigInteger::inot(const BigInteger & val)
+BIGINT_API BigInteger * BigInteger::operator^(const BigInteger * val) const
 {
+	return operator^(*val);
 }
 
-void BigInteger::ishl(int64_t shift)
+BIGINT_API BigInteger * BigInteger::operator&(const BigInteger * val) const
 {
+	return operator&(*val);
 }
 
-void BigInteger::ishr(int64_t shift)
+BIGINT_API BigInteger * BigInteger::operator|(const BigInteger * val) const
 {
+	return operator|(*val);
+}
+
+BIGINT_API bool BigInteger::operator<(const BigInteger& val) const
+{
+	return cmp(val, false) == 1;
+}
+
+BIGINT_API bool BigInteger::operator>(const BigInteger& val) const
+{
+	return cmp(val, true) == 1;
+}
+
+BIGINT_API bool BigInteger::operator<=(const BigInteger& val) const
+{
+	return cmp(val, false) != 0;
+}
+
+BIGINT_API bool BigInteger::operator>=(const BigInteger& val) const
+{
+	return cmp(val, true) != 0;
+}
+
+BIGINT_API bool BigInteger::operator==(const BigInteger& val) const
+{
+	if (sign != val.sign || data->size() != val.data->size()) return false;
+	for (size_t i = 0; i < data->size(); ++i) if ((*data)[i] != (*val.data)[i]) return false;
+	return true;
+}
+
+BIGINT_API bool BigInteger::operator!=(const BigInteger& val) const
+{
+	return !(*this == val);
+}
+
+
+BIGINT_API char* BigInteger::toString()
+{
+	char* string = new char[data->size()*2 + 3];
+	string[0] = '0';
+	string[1] = 'x';
+	string[data->size() * 2 + 2] = 0;
+	for (size_t t = 0; t < data->size(); ++t) {
+		string[(data->size() - 1 - t) * 2 + 3] = (data->at(t) & 15) + ((data->at(t)  & 15) > 9 ? 87 : 48);
+		string[(data->size() - 1 - t) * 2 + 2] = (data->at(t) >> 4) + ((data->at(t) >> 4) > 9 ? 87 : 48);
+	}
+	return string;
+}
+
+
+void BigInteger::iadd(const BigInteger & other, bool swaptarget)
+{
+	if ((other.sign != sign) ^ swaptarget)
+	{
+		if (other.sign ^ swaptarget)
+		{
+			isub(other, true);
+		}
+		else
+		{
+			BigInteger tmp = BigInteger(other);
+			tmp.isub(*this, false);
+			cpy(tmp, true);
+		}
+		return;
+	}
+	bool carry = false;
+	bool greater = other.data->size() > data->size();
+	size_t min = greater ? data->size() : other.data->size();
+	const BigInteger* larger = greater ? &other : other.data->size() < data->size() ? this : nullptr;
+
+	for (size_t i = 0; i<min; ++i)
+	{
+		int res = (*data)[i] + (*other.data)[i] + (carry ? 1 : 0);
+		carry = res > 255;
+		(*data)[i] = (res % 256);
+	}
+	if (larger == &other)
+	{
+		for (size_t i = min; i<larger->data->size(); ++i)
+		{
+			int res = larger->data->at(i) + (carry ? 1 : 0);
+			carry = res < larger->data->at(i);
+			data->push_back(res % 256);
+		}
+	}
+	else
+	{
+		int at = min;
+		while (carry)
+		{
+			if (at == data->size())
+			{
+				data->push_back(1);
+				break;
+			}
+			int res = data->at(at) + 1;
+			carry = res == 256;
+			(*data)[at] = res % 256;
+			++at;
+		}
+	}
+	clip_zeroes();
+	if (!data->size()) data->push_back(0);
+}
+
+void BigInteger::isub(const BigInteger & other, bool swaptarget)
+{
+	if (other.sign ^ sign ^ swaptarget) // this - (-other) = this + other
+	{
+		bool swap = !sign;
+		sign = false;
+		iadd(other, swap);
+		sign = !swap;
+		return;
+	}
+	if (sign) // -this - (-other) = -this + other = other - this
+	{
+		BigInteger res = BigInteger(other);
+		res.sign = false;
+		sign = false;
+		res.isub(*this, false);
+		cpy(res, true);
+	}
+	else if ((*this) < other) // this - other (where other>this)
+	{
+		BigInteger res = BigInteger(other);
+		res.isub(*this, false);
+		sign = true;
+		cpy(res, false);
+	}
+	else // this - other (where other<=this)
+	{
+		// Get two's complement of the other value
+		BigInteger tc = BigInteger(other);
+		tc.twos_complement();
+		tc.iadd(*this, false);
+		bool hb;
+		size_t idx = tc.nth_set_bit(0, false, &hb);
+		if (hb) (*tc.data)[idx / 8] &= ~(1 << (int)(idx % 8));
+		tc.clip_zeroes();
+		cpy(tc, false);
+	}
+	if (!data->size()) data->push_back(0);
+}
+
+void BigInteger::imul(const BigInteger & val, bool swaptarget)
+{
+	bool hb, passed = false;
+	size_t track = -1;
+	size_t bit, prev = 0;
+
+	BigInteger tmp = BigInteger(*this);
+
+	data->clear();
+
+Loop:
+	bit = val.nth_set_bit(++track, true, &hb);
+	if (!hb || (passed && track == 0)) return;
+	passed = true;
+	
+	tmp.ishl(bit - prev);
+	iadd(tmp, false);
+
+	prev = bit;
+	goto Loop;
+}
+
+BigInteger* BigInteger::idiv(const BigInteger & val, bool swaptarget)
+{
+	if (val.is_zero()) throw new std::exception("Divide by zero!");
+	BigInteger* rem = new BigInteger(0);
+	BigInteger quot = BigInteger(0);
+
+	rem->data->push_back(0);
+	bool hb;
+	for (size_t t = highest_set_bit(&hb) + 1; hb && t > 0; --t)
+	{
+		rem->ishl(1);
+		(*rem->data)[0] |= ((*data)[(t - 1) /8] >> ((t - 1) % 8)) & 1;
+		
+		if (*rem >= val)
+		{
+			rem->isub(val, false);
+			quot.set_bit((t - 1), 1);
+		}
+	}
+	cpy(quot, false);
+	sign = val.sign ^ sign ^ swaptarget;
+	if (!data->size()) data->push_back(0);
+	return rem;
+}
+
+void BigInteger::imod(const BigInteger & val, bool swaptarget)
+{
+	BigInteger* modres = idiv(val, swaptarget);
+	cpy(*modres, true);
+	delete modres;
+}
+
+void BigInteger::ixor(const BigInteger & val, bool swaptarget)
+{
+	size_t s1 = val.data->size(), s2 = data->size();
+	for (size_t t = 0; t < s1; ++t)
+		if (t < s2)
+			(*data)[t] ^= val.data->at(t);
+		else
+			data->push_back(val.data->at(t));
+}
+
+void BigInteger::iand(const BigInteger & val, bool swaptarget)
+{
+	size_t s1 = data->size(), s2 = val.data->size();
+	for (size_t t = 0; t < s1; ++t)
+		if (t < s2)
+			(*data)[t] &= val.data->at(t);
+		else
+			break;
+}
+
+void BigInteger::ior(const BigInteger & val, bool swaptarget)
+{
+	size_t s1 = val.data->size(), s2 = data->size();
+	for (size_t t = 0; t < s1; ++t)
+		if (t < s2)
+			(*data)[t] |= val.data->at(t);
+		else
+			data->push_back(val.data->at(t));
+}
+
+void BigInteger::inot()
+{
+	for (size_t t = 0; t < data->size(); ++t) (*data)[t] = ~(*data)[t];
+}
+
+void BigInteger::ishl(uint64_t shift)
+{
+	size_t set = shift / 8;
+	char sub = shift % 8;
+	BYTE bm = shift_mask(sub, true);
+	BYTE ibm = ~bm;
+	BYTE carry = 0;
+	bool hb;
+	size_t fsb1 = highest_set_bit(&hb);
+	if (!hb) return;
+	BYTE fsb = (fsb1 % 8);
+	size_t cl = data->size() + set + ((fsb + sub) % 8 == 0 ? 0 : 1);
+	BYTE* create = new BYTE[cl];
+	create[cl - 1] = 0;
+	for (size_t i = set; i - set < data->size(); ++i)
+	{
+		create[i] = ((((*data)[i - set] & ibm) << sub) | carry);
+		carry = (((*data)[i - set] & bm) >> (8 - sub));
+	}
+	create[cl - 1] |= carry;
+	data->clear();
+	data->resize(set);
+	for (size_t t = 0; t < cl; ++t) data->push_back(create[t]);
+	delete[] create;
+	clip_zeroes();
+}
+
+void BigInteger::ishr(uint64_t shift)
+{
+	size_t offset = shift / 8;
+	char sub = shift % 8;
+	BYTE bm = shift_mask(sub, false);
+	BYTE ibm = ~bm;
+	bool hb;
+	size_t fsb1 = highest_set_bit(&hb);
+	if (hb) return;
+	BYTE carry = 0;
+
+	std::vector<BYTE> collect = std::vector<BYTE>();
+	for (size_t t = 0; t < data->size() - offset; ++t) collect.push_back(data->at(t + offset));
+	if (collect.at(collect.size() - 1) == 0) collect.pop_back();
+	data->clear();
+	data->resize(collect.size());
+
+	for (size_t t = 0; t < collect.size(); ++t)
+	{
+		(*data)[t] = (collect[t] >> sub);
+		if (t+1 < collect.size()) (*data)[t] |= (collect[t + 1] & bm) << (8 - sub);
+	}
+	if (!data->size()) data->push_back(0);
+}
+
+void BigInteger::twos_complement()
+{
+	for (size_t i = 0; i < data->size(); ++i) (*data)[i] = ~(*data)[i];
+	iadd(BigInteger(1), false);
+}
+
+void BigInteger::set_bit(size_t index, bool value)
+{
+	BYTE fill = sign ? 0xFF : 0x00;
+	while (index >= data->size() * 8) data->push_back(fill);
+	(*data)[index / 8] = ((*data)[index / 8] & ~(1 << (index % 8))) | ((value ? 1 : 0) << (index % 8));
+}
+
+void BigInteger::cpy(const BigInteger& val, bool withsign)
+{
+	if(withsign) sign = val.sign;
+	data->clear();
+	for (BYTE b : *val.data) data->push_back(b);
+}
+
+char BigInteger::cmp(const BigInteger & other, bool grt) const
+{
+	// If the other number is less than zero and this is a positive number, this number is larger and vice versa
+	if (other.sign && !sign && other.data->size() != 0) return grt ? 1 : 0;
+	if (sign && !other.sign && data->size() != 0) return grt ? 0 : 1;
+	size_t l1, l2;
+	size_t idx = 0;
+	bool hb1, hb2;
+	while ((l1 = nth_set_bit(idx, false, &hb1)) == (l2 = other.nth_set_bit(idx, false, &hb2))) {
+		++idx;
+		if (hb1 ^ hb2) return hb2 ^ grt ? 1 : 0;
+		if (!hb1) return 2;
+	}
+	return ((l1 > l2 && (!sign == grt)) || ((sign == grt) && l1 < l2)) ? 1 : 0;
 }
 
 char BigInteger::shift_mask(int64_t shift, bool left)
 {
-	return 0;
+	BYTE res = 0;
+	for (uint64_t i = shift; i > 0; --i) res = left ? (res >> 1) | 128 : (res << 1) | 1;
+	return res;
 }
 
 void BigInteger::clip_zeroes()
 {
+	while (data->size()>1 && !data->at(data->size()-1)) data->pop_back();
 }
 
-size_t BigInteger::highest_set_bit(bool & hasbits)
+size_t BigInteger::highest_set_bit(bool * hasbits) const
 {
-	return size_t();
+	*hasbits = true;
+	for (size_t t = data->size(); t > 0; --t)
+		if (data->at(t-1))
+			for (size_t t1 = 8; t1 > 0; --t1)
+				if (data->at(t-1) & (1 << (t1 - 1)))
+					return (t1 - 1) + ((t - 1) * 8);
+	*hasbits = false;
+	return 0;
 }
 
-size_t BigInteger::lowest_set_bit(bool & hasbits)
+size_t BigInteger::lowest_set_bit(bool * hasbits) const
 {
-	return size_t();
+	*hasbits = true;
+	for (size_t t = 0; t < data->size(); ++t)
+		if (data->at(t))
+			for (size_t t1 = 0; t1 < 8; ++t1)
+				if (data->at(t1) & (1 << t1))
+					return t1 + (t * 8);
+	*hasbits = false;
+	return 0;
 }
+
+size_t BigInteger::nth_set_bit(size_t index, bool minfirst, bool * hasbits) const
+{
+	*hasbits = true;
+	size_t target = index + 1;
+	for (size_t l = minfirst ? 1 : (data->size() * 8); (minfirst && l<=data->size() * 8) || (!minfirst && l > 0); l += minfirst ? 1 : -1)
+		if (((*data)[(int)((l-1) / 8)] & (1 << (int)((l-1) % 8))) && --target == 0)
+			return l - 1;
+	*hasbits = false;
+	return 0;
+}
+
+bool BigInteger::is_zero() const
+{
+	for (size_t t = 0; t < data->size(); ++t)
+		if (data->at(t))
+			return false;
+	return true;
+}
\ No newline at end of file
diff --git a/XMath/BigInteger.h b/XMath/BigInteger.h
index 7a5baa7..0f20024 100644
--- a/XMath/BigInteger.h
+++ b/XMath/BigInteger.h
@@ -1,45 +1,84 @@
 #pragma once
 
 #include <vector>
+#include <queue>
+
+#ifdef BIGINT_API
+#define BIGINT_API __declspec(dllexport)   
+#else  
+#define BIGINT_API __declspec(dllimport)   
+#endif  
+
+#define BYTE unsigned char
+
 
 class BigInteger {
 public:
-	BigInteger(int64_t initialValue);
-	BigInteger(BigInteger& initialvalue);
+	BIGINT_API BigInteger(int64_t initialValue);
+	BIGINT_API BigInteger(const BigInteger& initialvalue);
 
 	// These should just create a new bigint and call the internal functions on it
-	BigInteger* operator+(const BigInteger& val);
-	BigInteger* operator-(const BigInteger& val);
-	BigInteger* operator*(const BigInteger& val);
-	BigInteger* operator/(const BigInteger& val);
-	BigInteger* operator^(const BigInteger& val);
-	BigInteger* operator&(const BigInteger& val);
-	BigInteger* operator|(const BigInteger& val);
-	BigInteger* operator~();
-	BigInteger* operator<<(int64_t shiftcount);
-	BigInteger* operator>>(int64_t shiftcount);
+	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 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<<(uint64_t shiftcount) const;
+	BIGINT_API BigInteger* operator>>(uint64_t shiftcount) 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 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 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;
+	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 char* toString();
 
 protected:
-	std::vector<char>* data;
+	std::vector<BYTE>* data;
 	bool sign;
 
 	// Internal functions: manipulate the object they are called on
-	void iadd(const BigInteger& val);
-	void isub(const BigInteger& val);
-	void imul(const BigInteger& val);
-	void idiv(const BigInteger& val);
-	void ixor(const BigInteger& val);
-	void iand(const BigInteger& val);
-	void ior(const BigInteger& val);
-	void inot(const BigInteger& val);
-	void ishl(int64_t shift);
-	void ishr(int64_t shift);
+	void iadd(const BigInteger& val, bool swaptarget);
+	void isub(const BigInteger& val, bool swaptarget);
+	void imul(const BigInteger& val, bool swaptarget);
+	BigInteger* idiv(const BigInteger& val, bool swaptarget);
+	void imod(const BigInteger& val, bool swaptarget);
+	void ixor(const BigInteger& val, bool swaptarget);
+	void iand(const BigInteger& val, bool swaptarget);
+	void ior(const BigInteger& val, bool swaptarget);
+	void inot();
+	void ishl(uint64_t shift);
+	void ishr(uint64_t shift);
+	void twos_complement();
+	void set_bit(size_t index, bool value);
+	void cpy(const BigInteger& val, bool withsign);
+
+	char cmp(const BigInteger& other, bool grt) const;
 
 	// Math helper functions
 	char shift_mask(int64_t shift, bool left);
 
 	// For sorting and whatnot
 	void clip_zeroes();
-	size_t highest_set_bit(bool& hasbits);
-	size_t lowest_set_bit(bool& hasbits);
+	size_t highest_set_bit(bool* hasbits) const;
+	size_t lowest_set_bit(bool* hasbits) const;
+	size_t nth_set_bit(size_t index, bool minfirst, bool* hasbits) const;
+	bool is_zero() const;
 };
\ No newline at end of file
diff --git a/XMath/XMath.vcxproj b/XMath/XMath.vcxproj
index 8a47aae..18057fb 100644
--- a/XMath/XMath.vcxproj
+++ b/XMath/XMath.vcxproj
@@ -26,7 +26,7 @@
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
diff --git a/XMath/XMath.vcxproj.filters b/XMath/XMath.vcxproj.filters
index a5351ad..2454276 100644
--- a/XMath/XMath.vcxproj.filters
+++ b/XMath/XMath.vcxproj.filters
@@ -14,14 +14,14 @@
       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
     </Filter>
   </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="BigInteger.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
   <ItemGroup>
     <ClCompile Include="BigInteger.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="BigInteger.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>
\ No newline at end of file