diff --git a/integerP.cpp b/integerP.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7b66df39327598946afc0746eb7b319fccbaa06 --- /dev/null +++ b/integerP.cpp @@ -0,0 +1,313 @@ +#ifndef INITEGERP_H +#define INITEGERP_H +#include +#include + +class IntegerP +{ + +public: + + IntegerP() + { + + } + + IntegerP(unsigned long lnum) + { + if (lnum == 0) + { + lnum = 1; + } + unsigned long n = lnum; + unsigned long prime = 2; + while (n > 1) + { + int power = 0; // exponent of current prime at, count how many times it divides + while (n % prime == 0) + { + n = n / prime; + power += 1; + } + _primePowers.push_back(power); + + // next prime + if (prime == 2) + { + prime = 3; + } + else + { + prime = prime + 2;//odd nums + while (!isPrime(prime)) + { + prime = prime + 2;//skip non pimes + } + } + } + } + + IntegerP(const std::vector &pBasis) + { + _primePowers = pBasis; + } + + static IntegerP valueOf(const unsigned long lnum) + { + return IntegerP(lnum); + } + + static IntegerP valueOf(const std::vector &pBasis) + { + return IntegerP(pBasis); + } + + IntegerP operator*(const IntegerP &multiplicand) const //multiplies two numbers + { + IntegerP result; + unsigned long len1 = (unsigned long)_primePowers.size(); + unsigned long len2 = (unsigned long)multiplicand._primePowers.size(); + unsigned long maxLen = (len1 > len2 ? len1 : len2); + result._primePowers.resize(maxLen); //result exponents + unsigned long i = 0; + while (i < maxLen) + { + int p1 = (i < len1 ? _primePowers[i] : 0); + int p2 = (i < len2 ? multiplicand._primePowers[i] : 0); + result._primePowers[i] = p1 + p2; + i = i + 1; + } + return result; + } + + IntegerP operator/(const IntegerP &divisor) const + { + IntegerP result; + unsigned long len1 = (unsigned long)_primePowers.size(); + unsigned long len2 = (unsigned long)divisor._primePowers.size(); + unsigned long maxLen = (len1 > len2 ? len1 : len2); + result._primePowers.resize(maxLen); + unsigned long i = 0; + while (i < maxLen) + { + int p1 = (i < len1 ? _primePowers[i] : 0); + int p2 = (i < len2 ? divisor._primePowers[i] : 0); + result._primePowers[i] = p1 - p2; + i = i + 1; + } + return result; + } + + bool operator==(const IntegerP &other) const + { + IntegerP a = *this; + IntegerP b = other; + a.trimZeros(); + b.trimZeros(); //trim on copies + + if (a._primePowers.size() != b._primePowers.size()) + { + return false; + } + + unsigned long len = (unsigned long)a._primePowers.size(); + unsigned long i = 0; + while (i < len) + { + if (a._primePowers[i] != b._primePowers[i]) { + return false; + } + i = i + 1; + } + return true; + } + + long trunc() const { + long value = 1;//running product + long maxVal = 9223372036854775807L;// max for 64 bit + unsigned long prime = 2; // start at 2 and go through all primes used + unsigned long i = 0; + while (i < (unsigned long)_primePowers.size()) + { + int power = _primePowers[i]; + int k = 0; + while (k < power) + { + if (value != 0 && prime != 0) // if it goes past maxval + { + long limit = maxVal / (long)prime; + if (value > limit) { + return maxVal; + } + } + value = value * (long)prime; + k = k + 1; + } + + if (prime == 2) //next prime + { + prime = 3; + } + else + { + prime = prime + 2; + while (!isPrime(prime)) + { + prime = prime + 2; + } + } + i = i + 1; + } + return value; + } + + bool divisibleBy(const IntegerP &divisor) const + { + unsigned long len1 = (unsigned long)_primePowers.size(); + unsigned long len2 = (unsigned long)divisor._primePowers.size(); + unsigned long maxLen = (len1 > len2 ? len1 : len2); + unsigned long i = 0; + while (i < maxLen) + { + int p1 = (i < len1 ? _primePowers[i] : 0); + int p2 = (i < len2 ? divisor._primePowers[i] : 0); + if (p1 < p2) + { + return false; + } + i = i + 1; + } + return true; + } + + std::string toString() const + { + bool allZero = true;//first check if its just 1 + unsigned long idx = 0; + while (idx < (unsigned long)_primePowers.size()) + { + if (_primePowers[idx] != 0) + { + allZero = false; + break; + } + idx = idx + 1; + } + if (allZero) + { + return "1"; + } + + std::string s = ""; + bool firstTerm = true; + unsigned long prime = 2;// start with 2 + unsigned long i = 0; + while (i < (unsigned long)_primePowers.size()) + { + int power = _primePowers[i]; + if (power > 0) + { + if (!firstTerm) + { + s = s + " * "; + } + firstTerm = false; + s = s + numberToString(prime); + if (power > 1) + { + s = s + "^"; + s = s + numberToString(power); + } + } + + if (prime == 2) //next prime + { + prime = 3; + } + else + { + prime = prime + 2; + while (!isPrime(prime)) + { + prime = prime + 2; + } + } + + i = i + 1; + } + + return s; + } + + const std::vector& primePowers() const noexcept { return _primePowers; } + +protected: + std::vector _primePowers; + void trimZeros() + { + while (!_primePowers.empty() && _primePowers[_primePowers.size() - 1] == 0) { + _primePowers.pop_back(); + } + } + + bool isPrime(unsigned long n) const + { + if (n < 2) + { + return false; + } + if (n == 2) + { + return true; + } + if (n % 2 == 0) + { + return false; + } + + unsigned long i = 3; + while (i * i <= n) + { + if (n % i == 0) + { + return false; + } + i = i + 2; + } + return true; + } + std::string numberToString(long n) const + { + if (n == 0) + { + return "0"; + } + + bool negative = false; + if (n < 0) { + negative = true; + n = -n; + } + + std::string rev = ""; + while (n > 0) + { + long digit = n % 10; + char c = (char)('0' + digit); + rev.push_back(c); + n = n / 10; + } + std::string result = ""; + if (negative) { + result.push_back('-'); + } + long i = (long)rev.size() - 1; + while (i >= 0) { + result.push_back(rev[(unsigned long)i]); + i = i - 1; + } + return result; + } +}; + +#endif //INITEGERP_H