From 539540b74bf0ddfc86ce6e26cc8a6eabda3aa29f Mon Sep 17 00:00:00 2001 From: Rayan Syed Date: Tue, 3 Feb 2026 16:13:15 -0500 Subject: [PATCH] ci & tests for hw1 --- ci_cd/gitlab-ci.yml | 11 +++ ci_cd/problem2a.yml | 47 ++++++++++ ci_cd/problem2b.yml | 47 ++++++++++ tests/BigNum.cpp | 191 ++++++++++++++++++++++++++++++++++++++++ tests/BigNum.h | 111 +++++++++++++++++++++++ tests/IntegerP.cpp | 171 +++++++++++++++++++++++++++++++++++ tests/IntegerP.h | 127 ++++++++++++++++++++++++++ tests/IntegerPP.h | 51 +++++++++++ tests/Makefile | 38 ++++++++ tests/testBinPrime.cpp | 90 +++++++++++++++++++ tests/testIntegerPP.cpp | 59 +++++++++++++ 11 files changed, 943 insertions(+) create mode 100644 ci_cd/gitlab-ci.yml create mode 100644 ci_cd/problem2a.yml create mode 100644 ci_cd/problem2b.yml create mode 100644 tests/BigNum.cpp create mode 100644 tests/BigNum.h create mode 100644 tests/IntegerP.cpp create mode 100644 tests/IntegerP.h create mode 100644 tests/IntegerPP.h create mode 100644 tests/Makefile create mode 100644 tests/testBinPrime.cpp create mode 100644 tests/testIntegerPP.cpp diff --git a/ci_cd/gitlab-ci.yml b/ci_cd/gitlab-ci.yml new file mode 100644 index 0000000..6479db8 --- /dev/null +++ b/ci_cd/gitlab-ci.yml @@ -0,0 +1,11 @@ +stages: + - prebuild + - compile + - test + +include: + - local: 'ci_cd/problem2a.yml' # IntegerPP + - local: 'ci_cd/problem2b.yml' # binPrime + +default: + timeout: 5m diff --git a/ci_cd/problem2a.yml b/ci_cd/problem2a.yml new file mode 100644 index 0000000..c095422 --- /dev/null +++ b/ci_cd/problem2a.yml @@ -0,0 +1,47 @@ +prebuild_problem_2a: + stage: prebuild + script: + - | + # Check if source files exist + if [ ! -f "IntegerPP.cpp" ]; then + echo "IntegerPP.cpp does not exist"; + exit 1; + fi + - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworkone.git hw1 + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2a"' + tags: [c++-17] + +compile_problem_2a: + stage: compile + needs: + - job: prebuild_problem_2a + artifacts: true + script: + - cp IntegerPP.cpp hw1/tests/ + - cd hw1/tests + - make problem2a + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2a"' + tags: [c++-17] + +exec_problem_2a: + stage: test + needs: + - job: compile_problem_2a + artifacts: true + script: + - cd hw1/tests + - ./problem2a + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2a"' + tags: [c++-17] diff --git a/ci_cd/problem2b.yml b/ci_cd/problem2b.yml new file mode 100644 index 0000000..e4433cf --- /dev/null +++ b/ci_cd/problem2b.yml @@ -0,0 +1,47 @@ +prebuild_problem_2b: + stage: prebuild + script: + - | + # Check if source files exist + if [ ! -f "binPrime.cpp" ]; then + echo "binPrime.cpp does not exist"; + exit 1; + fi + - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworkone.git hw1 + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2b"' + tags: [c++-17] + +compile_problem_2b: + stage: compile + needs: + - job: prebuild_problem_2b + artifacts: true + script: + - cp binPrime.cpp hw1/tests/ + - cd hw1/tests + - make problem2b + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2b"' + tags: [c++-17] + +exec_problem_2b: + stage: test + needs: + - job: compile_problem_2b + artifacts: true + script: + - cd hw1/tests + - ./problem2b + artifacts: + paths: + - hw1/ + rules: + - if: '$CI_COMMIT_REF_NAME == "problem2b"' + tags: [c++-17] diff --git a/tests/BigNum.cpp b/tests/BigNum.cpp new file mode 100644 index 0000000..25fdfbe --- /dev/null +++ b/tests/BigNum.cpp @@ -0,0 +1,191 @@ +// +// Created by Ari Trachtenberg on 1/30/17. +// + +#include +#include +#include "BigNum.h" + +// IMPLEMENTATION + +BigNum::BigNum(const string &num) { + bool leading = true; // used to ignore leading zeroes + for (int ii = 0; ii < num.length(); ii++) + if (leading && num[ii] == '0') + continue; + else { + leading = false; + digits.insert(digits.begin(), num[ii] - '0'); + } +} + +BigNum::BigNum(const unsigned long num) { + stringstream ss; ss< result(new BigNum("0")); + if (digits.size() > addor.digits.size()) { + first = addor; + second = *this; + } else { + first = *this; + second = addor; + } + + int ii; + int carry = 0; + for (ii = 0; ii < first.digits.size(); ii++) { + const int sum = first.digits[ii] + second.digits[ii]; + result->digits.push_back((sum + carry) % base); + if (sum + carry > (base - 1)) { + carry = 1; + } else { + carry = 0; + } + } + + // finish up with the larger number + for (; ii < second.digits.size(); ii++) + if (carry) { + const int dig = (second.digits[ii] + carry); + result->digits.push_back(dig % base); + carry = (dig > (base - 1) ? dig / base : 0); + } else + result->digits.push_back(second.digits[ii]); + if (carry) + result->digits.push_back(carry); + + *this = *result; + return *this; +} + +BigNum &BigNum::operator*=(const int cc) { + // multiplies by small number cc + int carry = 0; + const unique_ptr result(new BigNum()); + + for (int digit : digits) { + const int prod = digit * cc + carry; + result->digits.push_back(prod % base); + if (prod > (base - 1)) + carry = prod / base; + else + carry = 0; + } + + while (carry) { + result->digits.push_back(carry % base); + carry /= base; + } + + *this=*result; + return *this; +} + +BigNum &BigNum::operator*=(const BigNum& multiplicator) { + const unique_ptr sum(new BigNum()); + for (int ii = 0; ii < multiplicator.digits.size(); ii++) { + BigNum smallProd = *this * multiplicator.digits[ii]; + smallProd << ii; + *sum += smallProd; + } + *this = *sum; + return *this; +} + +BigNum &BigNum::operator/=(const BigNum& divisor) { + // pretty naive algorithm that is easy to implement + const unique_ptr guess(new BigNum()); + for (int ii = digits.size() - 1; ii >= 0; ii--) { + int dig; + BigNum trial(""); + for (dig = 9; dig > 0; dig--) { + BigNum num("1"); + num << ii; + trial = (num * dig); + if ((*guess + trial) * divisor <= *this) + break; + } + if (dig != 0) + *guess = *guess + trial; + } + if (guess->digits.size() == 1 && guess->digits[0] == 0) + guess->digits.pop_back(); // make it the empty representation + *this = *guess; + return *this; +} + +bool BigNum::operator==(const BigNum& otherNum) const { + if (digits.size() != otherNum.digits.size()) { + return false; + } + for (int ii = 0; ii < digits.size(); ii++) + if (digits[ii] != otherNum.digits[ii]) + return false; + return true; +} + +bool BigNum::operator<=(const BigNum& otherNum) const { + if (digits.size() > otherNum.digits.size()) + return false; + if (digits.size() < otherNum.digits.size()) + return true; + // same number of digits + for (int ii = digits.size() - 1; ii >= 0; ii--) + if (digits[ii] < otherNum.digits[ii]) + return true; + else if (digits[ii] > otherNum.digits[ii]) + return false; + return true; // they are equal +} + +void BigNum::operator<<(const int cc) { + digits.insert(digits.begin(), cc, 0); +} + +BigNum BigNum::operator*(const int cc) const { + BigNum *result = new BigNum(*this); + *result *= cc; + return *result; +} + +BigNum BigNum::operator+(const BigNum &addor) const { + BigNum result(*this); + result += addor; + return result; +} + +BigNum BigNum::operator*(const BigNum& multiplicator) const { + BigNum result(*this); + result *= multiplicator; + return result; +} + +BigNum BigNum::operator/(const BigNum& divisor) const { + BigNum result(*this); + result /= divisor; + return result; +} + +// friends and helpers +std::ostream & operator<<(std::ostream& stream, const BigNum& num) { + if (num.digits.size() == 0) + stream << "[0]"; + else + for (int ii = num.digits.size() - 1; ii >= 0; ii--) + stream << num.digits[ii]; + return stream; +} + diff --git a/tests/BigNum.h b/tests/BigNum.h new file mode 100644 index 0000000..19778b0 --- /dev/null +++ b/tests/BigNum.h @@ -0,0 +1,111 @@ +// +// Originally written by Ari Trachtenberg on 1/30/17. +// Adapted for EC330. +// + +#ifndef HW1_BIGNUM_H +#define HW1_BIGNUM_H + +#include +#include +#include +using namespace std; + +/** + * A class to represent arbitrarily large non-negative integers. + */ +class BigNum { +public: + + // CONSTRUCTORS + + /** + * Constructs a bigNum from a given non-negative int + */ + BigNum(unsigned long num); + + /** + * Constructs a bigNum from a given string. + * @param num contains only characters 0-9 and represents a positive integer >= 0 + */ + explicit BigNum(const string &num = ""); + + /** + * Constructs a copy of {@code otherNum} + */ + BigNum(const BigNum& otherNum); + + // OPERATORS + /** + * @return true iff this bigNum is exactly numerically equal to otherNum + */ + bool operator==(const BigNum& otherNum) const; + + /** + * + * @param otherNum + * @return true iff this number is numerically less than or equal to other number + */ + bool operator<=(const BigNum& otherNum) const; + + /** + * This bigNum becomes the same as otherNum + * @return the (new) version of this bigNum + */ + BigNum& operator=(const BigNum& otherNum); + + /** + * @return the [index]-th least-significant digit of the number + */ + int operator[](const size_t index) const { return digits.at(index); } + + /** + * + * @return The number of significant digits in the number + */ + size_t numDigits() const { return digits.size(); } + + /** + * Arithmetic + */ + BigNum operator+(const BigNum& addor) const; + BigNum operator*(const BigNum& multiplicator) const; + BigNum operator/(const BigNum& divisor) const; + + /** + * Optimized multiplication of a bigNum by an int + * @param cc > 0 is assumed + * @return the product of this number and cc + */ + BigNum operator*(int cc) const; + + /** + * ARITHMETIC ASSIGNMENT OPERATORS + */ + BigNum& operator+=(const BigNum& addor); + BigNum& operator*=(int cc); + BigNum& operator*=(const BigNum& multiplicator); + BigNum& operator/=(const BigNum& divisor); + +protected: + vector digits; /** stores the digits of the current number */ + + /** + * @param cc > 0 + * @return shifts the number to the left cc digits; + * equivalent to multiplying the current number by base^cc + */ + void operator<<(int cc); + +private: + // Constants + constexpr static int base = 10; // the base of the number + + // FRIENDS + /** + * Prints a human-readable version of bigNum [num] + * onto a given output stream + */ + friend std::ostream & operator<<(std::ostream& stream, const BigNum& num); +}; +#endif //HW1_BIGNUM_H diff --git a/tests/IntegerP.cpp b/tests/IntegerP.cpp new file mode 100644 index 0000000..c3a834d --- /dev/null +++ b/tests/IntegerP.cpp @@ -0,0 +1,171 @@ +#include + +#include "IntegerP.h" + +#include +#include +#include + +using namespace std; + +// helpers +/** + * @return true iff n is prime + */ +bool isPrime(const int n) { + if (n <= 1) + return false; + + for (int i = 2; i * i <= n; i++) { + if (n % i == 0) { + return false; + } + } + + return true; +} + +/** + * @return The i-th prime, starting with i-thPrime(0)==2. + */ +unsigned int ithPrime(const size_t ii) { + static auto memoized = vector(); + if (memoized.size()>ii && memoized[ii]!=0u) // i.e., already memoized + return memoized[ii]; + + int prime=2; + size_t ii_search=ii; + while (ii_search!=0) { + if (isPrime(++prime)) + ii_search--; + } + + memoized.resize(ii+1); + memoized[ii]=prime; + return prime; +} + +/** + * @return {@code v[i]} if {@code i} is within the range of {@code v}, or, {@code def} otherwise. + * @thanks ChatGPT + */ +template +T getOrDef(const std::vector& v, std::size_t i, T def = T{}) { + return i < v.size() ? v[i] : def; +} + +/** + * Computes a positive integer power of an integer, using square-and-multiply. + * @param base The base. + * @param exp The exponent + * @return base ^ exp + * @requires exp>=0 + * @thanks ChatGPT + */ +long ipow(int base, int exp) { + long result = 1; + + while (exp > 0) { + if (exp & 1) + result *= base; + base *= base; + exp >>= 1; + } + + return result; +} + +IntegerP::IntegerP(unsigned long lnum) { + int ii=-1; + while (lnum>1) { + ii++; + if (lnum % ithPrime(ii)==0) { + if (_primePowers.size()<=(size_t) ii) // make sure that space is allocated + _primePowers.resize(ii+1); + _primePowers[ii]++; + lnum/=ithPrime(ii); + ii--; + } + } +} +IntegerP::IntegerP(const initializer_list pBasis):_primePowers(pBasis) { +} +IntegerP::IntegerP():IntegerP(1) { +} +// IntegerP IntegerP::operator+(const IntegerP &addend) { +// +// } +// IntegerP IntegerP::operator-(const IntegerP &subtrahend) { +// } +IntegerP IntegerP::operator*(const IntegerP &multiplicand) const { + const auto numIndices = static_cast(max(_primePowers.size(),multiplicand._primePowers.size())); + IntegerP result; + for (int ii=0; ii(max(_primePowers.size(),divisor._primePowers.size())); + IntegerP result; + int max_index=0; // the maximum significant index + for (int ii=0; ii log(LONG_MAX)) + return LONG_MAX; + + // size is ok + long result=1; + for (size_t ii=0; ii<_primePowers.size(); ii++) + result*=ipow((int) ithPrime(ii),_primePowers[ii]); + return result; +} + +bool IntegerP::divisibleBy(const IntegerP &divisor) const { + const IntegerP result = operator/(divisor); + for (const int exp:result._primePowers) + if (exp<0) + return false; + return true; +} +std::string IntegerP::toString() const { + ostringstream result; + + if (_primePowers.empty() || (_primePowers.size()==1 && _primePowers[0]==0)) + result << "1"; + else { + for (size_t ii=0; ii<_primePowers.size(); ii++) + if (_primePowers[ii]!=0) { + result << ithPrime(ii); + if (_primePowers[ii]!=1) + result << "^" << _primePowers[ii]; + if (ii<_primePowers.size()-1) + result << " * "; + } + } + return result.str(); +} diff --git a/tests/IntegerP.h b/tests/IntegerP.h new file mode 100644 index 0000000..98f5719 --- /dev/null +++ b/tests/IntegerP.h @@ -0,0 +1,127 @@ +// +// Created by Ari Trachtenberg on 1/23/26. +// + +#ifndef INITEGERP_H +#define INITEGERP_H +#include +#include + +/** + * Represents a multi-precision, positive Integer, in a manner suitable + * for efficiently multiplying and dividing large powers of small integers, + * such as 6^1000 and 10^512. + */ +class IntegerP { + public: + // CONSTRUCTORS + /** + * Constructs the Integer 1. + */ + IntegerP(); + + /** + * Constructs an {@link IntegerP} representation of num. + * @requires num>0 + */ + IntegerP(unsigned long lnum); + + /** + * Constructs a representation of an integer in the prime basis. + * Specifically, the number produced is: + * product over all i of (prime(i)^basis[i]), + * where prime(i) is the i-th prime number (2 being the 0-th prime), and + * basis[i] is the i-th element of parameter {@code pBasis}. + * @param pBasis A list representing the powers of primes generating this {@link IntegerP}. + * @requires pBasis[i]>=0 for all i + * @example IntegerP ({1}) represents the number 2 = 2^1 + * @example IntegerP ({1,1}) represents the number 6 = 2^1 * 3^1 + * @example IntegerP ({1,0,0,1}) represents the number 14 = 2^1 * 3^0 * 5^0 * 7^1 + * @example IntegerP ({0,2,0,1,1}) represents the number 693 = 3^2 * 7 * 11 + */ + IntegerP(std::initializer_list pBasis); + + /** + * Static factory method based on {@link #IntegerP(unsigned long)}. + * @example IntegerP::valueOf(3) returns an IntegerP representing 3 = 3^1. + */ + static IntegerP valueOf(const unsigned long lnum) { + return IntegerP(lnum); + } + + /** + * Static factory method based on {@link #IntegerP(std::initializer_list)}. + * @example IntegerP::valueOf({1}) represents the number 2 = 2^1 + * @example IntegerP::valueOf({1,1}) represents the number 6 = 2^1 * 3^1 + * @example IntegerP::valueOf({1,0,0,1}) represents the number 14 = 2^1 * 3^0 * 5^0 * 7^1 + * @example IntegerP::valueOf({0,2,0,1,1}) represents the number 693 = 3^2 * 7 * 11 + */ + static IntegerP valueOf(const std::initializer_list pBasis) { + return IntegerP(pBasis); + } + + // OPERATORS + /** + * Multiplies this {@link IntegerP} by {@code multiplicand} and returns the product. + * @param multiplicand The number to multiply by this object. + * @return The product of this object and {@code multiplicand}. + * @example IntegerP::valueOf(10) * Integer::valueOf(5) = Integer::valueOf(50) + * @example IntegerP::valueOf({1,1}) * IntegerP::valueOf({1,0,0,1}) = IntegerP::valueOf({2,1,0,1}) + * (2*3) * (2*7) = (2^2 * 3 * 7) + * 6 * 14 = 84 + */ + IntegerP operator*(const IntegerP &multiplicand) const; + + /** + * Divides this {@link IntegerP} by {@code divisor} and returns the quotient. + * @param divisor The number into which to divide this object. + * @return The division of this object and {@code divisor}. If this object is not + * evenly divisible by {@code divisor}, the result is not specified. + * @example IntegerP::valueOf(14) / IntegerP::valueOf(2) = IntegerP::valueOf(7) + */ + IntegerP operator/(const IntegerP &divisor) const; + + /** + * @return true iff {@code other} is *identical* to this number + * @example IntegerP::valueOf(14)==Integer::valueOf({1,0,0,1}) returns true + */ + bool operator==(const IntegerP &other) const; + + // INFORMATIONAL + /** + * @return A truncation of this object to a {@code long}, or + * LONG_MAX if the object represents a number that is too big + * to fit in a {@code long}. + * @example IntegerP::valueOf(14).trunc() returns 14 + * @example IntegerP::valueOf({2,1,0,1}).trunc() returns 84 + * @example IntegerP::valueOf({20,3,5,10}).trunc() retunrs LONG_MAX (=9223372036854775807) + */ + long trunc() const; + + /** + * @param divisor The divisor to check for divisibility + * @return true iff this object is evenly divisible by {@code divisor}. + * @example IntegerP::valueOf(14).divisibleBy(IntegerP::valueOf(2)) returns true + * @example IntegerP::valueOf(14).divisibleBy(IntegerP::valueOf(3)) returns false + */ + bool divisibleBy(const IntegerP &divisor) const; + + /** + * @return A human-readable representation of this object. + * @example IntegerP::valueOf(2928).toString() may return "2^4 * 3 * 61" + */ + std::string toString() const; + + /** + * Safe getter method for the {@link #_primePowers} field. + * @return A read-only version of {@link #_primePowers}. + */ + const std::vector& primePowers() const noexcept { return _primePowers; } + + protected: + /** + * the i-th entry contains the power of i-th prime in the product that generates this object. + */ + std::vector _primePowers; +}; +#endif //IntegerP_H diff --git a/tests/IntegerPP.h b/tests/IntegerPP.h new file mode 100644 index 0000000..8324dcf --- /dev/null +++ b/tests/IntegerPP.h @@ -0,0 +1,51 @@ +// +// Created by Ari on 1/31/26. +// + +#ifndef HW1_INTEGERPLUS_H +#define HW1_INTEGERPLUS_H +#include "IntegerP.h" +#include "BigNum.h" + +class IntegerPP: public IntegerP { + public: + /** + * All modeled after {@link IntegerP}. + */ + IntegerPP(); + IntegerPP(unsigned long n); + IntegerPP(std::initializer_list pBasis); + IntegerPP(const IntegerP& other); + + + /** + * Constructs an IntegerPlus from a BigNum + * @param num The BigNum from which to construct the IntegerPlus. + */ + explicit IntegerPP(BigNum num); + + /** + * Adds this {@link IntegerPP} by {@code addor} and returns the sum. + * @param addor The number to add to this object. + * @return The sum of this object and {@code addor}. + * @example (IntegerPP(10) + IntegerPP(5) == IntegerPP(15)) + * @example (IntegerPP({1,1}) + IntegerPP({1,0,0,1}) == IntegerPP({2,0,1})) + * (2*3) + (2*7) = (2^2 * 5) + * 6 + 14 = 20 + */ + IntegerPP operator+(const IntegerPP &addor) const; + + /** + * Assigns the {@link rhs} to this object. + * @param rhs The element to assign. + * @return this object. + */ + IntegerPP& operator=(const IntegerPP& rhs); + + /** + * Converts this IntegerPP into a BigNum. + */ + explicit operator BigNum() const; +}; + +#endif //HW1_INTEGERPLUS_H \ No newline at end of file diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..4439336 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,38 @@ +# Makefile, generated with support of ChatGPT + +# Compiler and flags +CXX = g++ -O2 +CXXFLAGS = -std=c++17 + +# Source files +PROBLEM0_SRCS = testIntegerPP.cpp IntegerPP.cpp IntegerP.cpp BigNum.cpp +PROBLEM1_SRCS = testBinPrime.cpp binPrime.cpp IntegerPP.cpp IntegerP.cpp BigNum.cpp +SRCS = $(PROBLEM0_SRCS) $(PROBLEM1_SRCS) + +# Object files +PROBLEM0_OBJS = testIntegerPP.o IntegerPP.o IntegerP.o BigNum.o +PROBLEM1_OBJS = testBinPrime.o binPrime.o IntegerPP.o IntegerP.o BigNum.o +OBJS = $(PROBLEM0_OBJS) $(PROBLEM1_OBJS) + +# Executable names +PROBLEM0_EXEC = problem2a +PROBLEM1_EXEC = problem2b +EXECS = $(PROBLEM0_EXEC) $(PROBLEM1_EXEC) + +# Default target to build the executable +all: $(PROBLEM0_EXEC) $(PROBLEM1_EXEC) + +# Rule to build the executable from object files +$(PROBLEM0_EXEC): $(PROBLEM0_OBJS) Makefile + $(CXX) $(CXXFLAGS) -o $(PROBLEM0_EXEC) $(PROBLEM0_OBJS) +$(PROBLEM1_EXEC): $(PROBLEM1_OBJS) Makefile + $(CXX) $(CXXFLAGS) -o $(PROBLEM1_EXEC) $(PROBLEM1_OBJS) + +# Rules to build object files from source files, with dependency on the Common.h header +%.o: %.cpp Makefile + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Clean target to remove compiled files +clean: + rm -f $(OBJS) $(EXECS) + diff --git a/tests/testBinPrime.cpp b/tests/testBinPrime.cpp new file mode 100644 index 0000000..81aef3d --- /dev/null +++ b/tests/testBinPrime.cpp @@ -0,0 +1,90 @@ +// +// Created by Rayan on 2/3/26. Adapted from Ari's tests for IntegerP. +// +#include +#include +#include +#include + +#include "BigNum.h" +using namespace std; + +BigNum binPrime(const int pascalRow); + +// helper function +bool failExample(const char* testName, const std::string& msg, string expected, string got) { + std::cerr << "[" << testName << " FAILED] " << msg << ": expected " << expected << ", got " << got << "\n"; + return false; +} + +// Assisted by ChatGPT +// -------------------- binPrime() -------------------- +bool test_0() { + const char* T = "binPrime examples"; + + { + // @example binPrime(2) = (2 choose 2) = 1. + BigNum got = binPrime(2); + BigNum expected(1UL); + if (!(got == expected)) { + std::ostringstream oss; + oss << got; + return failExample(T, "binPrime(2)", "1", oss.str()); + } + } + + return true; +} + +bool test_1() { + const char* T = "binPrime examples"; + + { + // @example binPrime(4) = (4 choose 2) + (4 choose 3) = 6 + 4 = 10 + BigNum got = binPrime(4); + BigNum expected(10UL); + if (!(got == expected)) { + std::ostringstream oss; + oss << got; + return failExample(T, "binPrime(4)", "10", oss.str()); + } + } + + return true; +} + +bool test_2() { + const char* T = "binPrime examples"; + + { + // @example binPrime(7) = ... = 78 + BigNum got = binPrime(7); + BigNum expected(78UL); + if (!(got == expected)) { + std::ostringstream oss; + oss << got; + return failExample(T, "binPrime(7)", "78", oss.str()); + } + } + + return true; +} + +int main() { + bool results[] = { test_0(), test_1(), test_2() }; + + bool allPassed = true; + for (size_t ii=0; ii +#include +#include + +#include "IntegerPP.h" +using namespace std; + + +// helper function +bool failExample(const char* testName, const std::string& msg, string expected, string got) { + std::cerr << "[" << testName << " FAILED] " << msg << ": expected " << expected << ", got " << got << "\n"; + return false; +} + +// Assisted by ChatGPT +// -------------------- operator+ -------------------- +bool test_0() { + const char* T = "IntegerPP::operator+ examples"; + + { + // @example (IntegerPP(10) + IntegerPP(5) == IntegerPP(15)) + IntegerPP got = IntegerPP(10) + IntegerPP(5); + IntegerPP expected = IntegerPP(15); + if (!(got == expected)) return failExample(T, "IntegerPP(10) + IntegerPP(5) == IntegerPP(15)","true","false"); + } + + { + // @example (IntegerPP({1,1}) + IntegerPP({1,0,0,1}) == IntegerPP({2,0,1})) + // (2*3) + (2*7) = (2^2 * 5) + // 6 + 14 = 20 + IntegerPP got = IntegerPP({1,1}) + IntegerPP({1,0,0,1}); + IntegerPP expected = IntegerPP({2,0,1}); + if (!(got == expected)) return failExample(T, "IntegerPP({1,1}) + IntegerPP({1,0,0,1}) == IntegerPP({2,0,1})","true","false"); + } + + return true; +} + +int main() { + bool results[] = { test_0() }; + + bool allPassed = true; + for (size_t ii=0; ii