diff --git a/.gitignore b/.gitignore index 32dcdee..aa8a0be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ .vs +.vscode out +build +3rdparty *.json \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 33ce1c4..70d2db3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,34 @@ -# CMakeList.txt : Top-level CMake project file, do global configuration -# and include sub-projects here. -# -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required (VERSION 3.8) -project ("GMP++") +project ("gm3p" CXX) + +set(GMP_INCLUDE_DIR "" CACHE PATH "Path to the directory containing 'gmp.h'") + +if(CMAKE_BUILD_TYPE EQUAL "DEBUG") + set(GMP_LIBRARY "" CACHE FILEPATH "Path to the gmp library") +else(CMAKE_BUILD_TYPE EQUAL "RELEASE") + set(GMP_LIBRARY "" CACHE FILEPATH "Path to the gmpDebug library") +endif() + +set(ENABLE_TEST_PROJ FALSE CACHE BOOL "Enable the testing project (usually not needed)") + +add_library(gm3p STATIC + "include/gm3p_int.hpp" "src/gm3p_int.cpp" +) + +target_include_directories(gm3p PUBLIC + include + ${GMP_INCLUDE_DIR} +) + +target_link_libraries(gm3p PUBLIC + ${GMP_LIBRARY} +) # Include sub-projects. -add_subdirectory ("GMP++") +if(ENABLE_TEST_PROJ) + add_subdirectory(testapp) +endif() + +install(TARGETS gm3p DESTINATION lib) +install(DIRECTORY include DESTINATION .) \ No newline at end of file diff --git a/include/gm3p.hpp b/include/gm3p.hpp new file mode 100644 index 0000000..629eb65 --- /dev/null +++ b/include/gm3p.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "gm3p_int.hpp" \ No newline at end of file diff --git a/include/gm3p_int.hpp b/include/gm3p_int.hpp new file mode 100644 index 0000000..f974cdf --- /dev/null +++ b/include/gm3p_int.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "gmp.h" + +namespace gm3p +{ + /** + * A wrapper for mpz_t + */ + class gInt + { + public: + // CONSTRUCTORS + gInt(); + gInt(mpz_t init); + gInt(mpq_t init); + gInt(mpf_t init); + gInt(long int init); + gInt(const char* init, int base = 10); + + // DESTRUCTOR + ~gInt(); + + // ASSIGNMENT/COPY OPERATORS + gInt& operator=(const gInt& other); + gInt(const gInt& other); + gInt(gInt&& other); + + // ARITHMETIC OPERATORS + friend gInt operator-(const gInt& value); + + friend gInt operator+(const gInt& left, const gInt& right); + friend gInt operator-(const gInt& left, const gInt& right); + friend gInt operator*(const gInt& left, const gInt& right); + friend gInt operator/(const gInt& left, const gInt& right); + + gInt& operator+=(const gInt& right); + gInt& operator-=(const gInt& right); + gInt& operator*=(const gInt& right); + gInt& operator/=(const gInt& right); + + friend gInt Mul2Exp(const gInt& value, const mp_bitcnt_t& exp); + friend gInt Neg(const gInt& value); + friend gInt Abs(const gInt& value); + + // CONVERSION OPERATORS + operator long int() const; + operator mpz_t&(); + + unsigned long int ToUnsigned() const; + char* ToString(char* buf, int base) const; + double ToDouble() const; + double ToDouble(long int* exp) const; + + // STDIO OPERATORS + friend std::ostream& operator<<(std::ostream& os, const gInt& value); + + private: + mpz_t value; + }; +} \ No newline at end of file diff --git a/src/gm3p_int.cpp b/src/gm3p_int.cpp new file mode 100644 index 0000000..91b528e --- /dev/null +++ b/src/gm3p_int.cpp @@ -0,0 +1,178 @@ +#include "gm3p.hpp" + +namespace gm3p +{ + gInt::gInt() + { + mpz_init(value); + } + + gInt::gInt(mpz_t init) + { + mpz_init_set(value, init); + } + + gInt::gInt(mpq_t init) + { + mpz_init(value); + mpz_set_q(value, init); + } + + gInt::gInt(mpf_t init) + { + mpz_init(value); + mpz_set_f(value, init); + } + + gInt::gInt(long int init) : + gInt::gInt() + { + mpz_init_set_si(value, init); + } + + gInt::gInt(const char* init, int base) : + gInt::gInt() + { + mpz_init_set_str(value, init, base); + } + + gInt::~gInt() + { + mpz_clear(value); + } + + gInt& gInt::operator=(const gInt& other) + { + mpz_set(*this, const_cast(other)); + return *this; + } + + gInt::gInt(const gInt& other) + { + mpz_set(*this, const_cast(other)); + } + + gInt::gInt(gInt&& other) + { + mpz_set(*this, const_cast(other)); + } + + gInt operator-(const gInt& value) + { + return Neg(value); + } + + gInt operator+(const gInt& left, const gInt& right) + { + gInt ret; + mpz_add(ret, const_cast(left), const_cast(right)); + return ret; + } + + gInt operator-(const gInt& left, const gInt& right) + { + gInt ret; + mpz_sub(ret, const_cast(left), const_cast(right)); + return ret; + } + + gInt operator*(const gInt& left, const gInt& right) + { + gInt ret; + mpz_mul(ret, const_cast(left), const_cast(right)); + return ret; + } + + gInt operator/(const gInt& left, const gInt& right) + { + gInt ret; + mpz_div(ret, const_cast(left), const_cast(right)); + return ret; + } + + gInt& gInt::operator+=(const gInt& right) + { + mpz_add(value, value, const_cast(right)); + return *this; + } + + gInt& gInt::operator-=(const gInt& right) + { + mpz_sub(value, value, const_cast(right)); + return *this; + } + + gInt& gInt::operator*=(const gInt& right) + { + mpz_mul(value, value, right.value); + return *this; + } + + gInt& gInt::operator/=(const gInt& right) + { + mpz_div(value, value, const_cast(right)); + return *this; + } + + gInt Mul2Exp(const gInt& value, const mp_bitcnt_t& exp) + { + gInt ret; + mpz_mul_2exp(ret, const_cast(value), exp); + return ret; + } + + gInt Neg(const gInt& value) + { + gInt ret; + mpz_neg(ret, const_cast(value)); + return ret; + } + + gInt Abs(const gInt& value) + { + gInt ret; + mpz_abs(ret, const_cast(value)); + return ret; + } + + gInt::operator long int() const + { + return mpz_get_si(value); + } + + gInt::operator mpz_t&() + { + return value; + } + + unsigned long int gInt::ToUnsigned() const + { + return mpz_get_ui(value); + } + + char* gInt::ToString(char* buf, int base) const + { + return mpz_get_str(buf, base, value); + } + + double gInt::ToDouble() const + { + return mpz_get_d(value); + } + + double gInt::ToDouble(long int* exp) const + { + return mpz_get_d_2exp(exp, value); + } + + + std::ostream& operator<<(std::ostream& os, const gInt& value) + { + os << value.ToString(NULL, + (os.flags() & std::ios_base::dec) != 0 ? 10 : + (os.flags() & std::ios_base::hex) != 0 ? 16 : + 8 + ); + return os; + } +} \ No newline at end of file diff --git a/testapp/CMakeLists.txt b/testapp/CMakeLists.txt new file mode 100644 index 0000000..970d34c --- /dev/null +++ b/testapp/CMakeLists.txt @@ -0,0 +1,13 @@ +add_executable(testapp + "main.cpp" +) + +target_include_directories(testapp PUBLIC + ${GMP_INCLUDE_DIR} + ${CMAKE_SOURCE_DIR}/include +) + +target_link_libraries(testapp PUBLIC + ${GMP_LIBRARY} + gm3p +) \ No newline at end of file diff --git a/testapp/main.cpp b/testapp/main.cpp new file mode 100644 index 0000000..409108d --- /dev/null +++ b/testapp/main.cpp @@ -0,0 +1,27 @@ +#include "gm3p.hpp" + +#include +#include + +using namespace gm3p; + +int main(int argc, char** argv) +{ + gInt a("12"); + gInt b = -5; + + gInt c = a * b; + + std::cout << c << std::endl << std::endl; + std::cout << -c << std::endl << std::endl; + + int d = Abs(c); + std::cout << d << std::endl; + std::cout << c.ToString(NULL, 2) << std::endl << std::endl; + + mpz_t& e = c; + mpz_mul_ui(e, e, 2); + std::cout << c << std::endl; + + return 0; +} \ No newline at end of file