Commit e0420400 authored by JustinKang's avatar JustinKang
Browse files

Add new file

parent 66888c31
Loading
Loading
Loading
Loading

integerP.cpp

0 → 100644
+313 −0
Original line number Diff line number Diff line
#ifndef INITEGERP_H
#define INITEGERP_H
#include <vector>  
#include <string>   

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<int> &pBasis) 
    {
        _primePowers = pBasis;
    }

    static IntegerP valueOf(const unsigned long lnum) 
    {
        return IntegerP(lnum);
    }

    static IntegerP valueOf(const std::vector<int> &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<int>& primePowers() const noexcept { return _primePowers; }

protected:
    std::vector<int> _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