abacus/tests/unit/bignum.cc
Bruno BELANYI 171ef10a6d
All checks were successful
continuous-integration/drone/push Build is passing
abacus: fix include directories
This cleans up one of my major pain points with the Meson way of doing
things.

The Meson solution to have nice includes would have been to create an
`include/<name>` directory per library I create...
2021-09-01 19:43:02 +02:00

420 lines
11 KiB
C++

#include <sstream>
#include <gtest/gtest.h>
#include "bignum/bignum.hh"
using namespace abacus::bignum;
TEST(BigNum, dump) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const minus_one = BigNum(-1);
auto const forty_two = BigNum(42);
auto const to_str = [](auto num) {
std::stringstream str;
str << num;
return str.str();
};
EXPECT_EQ(to_str(zero), "0");
EXPECT_EQ(to_str(one), "1");
EXPECT_EQ(to_str(minus_one), "-1");
EXPECT_EQ(to_str(forty_two), "42");
}
TEST(BigNum, read) {
auto const from_str = [](auto num) -> BigNum {
std::stringstream str(num);
BigNum res;
EXPECT_TRUE(str >> res);
return res;
};
EXPECT_EQ(from_str("0"), BigNum(0));
EXPECT_EQ(from_str("1"), BigNum(1));
EXPECT_EQ(from_str("-1"), BigNum(-1));
EXPECT_EQ(from_str("42"), BigNum(42));
}
TEST(BigNum, equality) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
EXPECT_EQ(zero, zero);
EXPECT_EQ(one, one);
EXPECT_NE(zero, one);
}
TEST(BigNum, comparisons) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
EXPECT_LT(zero, one);
EXPECT_LE(zero, one);
EXPECT_LE(zero, zero);
EXPECT_GT(one, zero);
EXPECT_GE(one, zero);
EXPECT_GE(one, one);
}
TEST(BigNum, comparisons_digits) {
auto const nine = BigNum(9);
auto const ten = BigNum(10);
EXPECT_LT(nine, ten);
EXPECT_GT(ten, nine);
}
TEST(BigNum, unary) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
EXPECT_EQ(zero, -zero);
EXPECT_NE(one, -one);
auto const minus_one = BigNum(-1);
EXPECT_EQ(minus_one, -one);
}
TEST(BigNum, addition_positive) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
EXPECT_EQ(zero + zero, zero);
EXPECT_EQ(zero + one, one);
EXPECT_EQ(one + zero, one);
EXPECT_EQ(one + one, two);
}
TEST(BigNum, addition_negative) {
auto const zero = BigNum(0);
auto const minus_one = BigNum(-1);
auto const minus_two = BigNum(-2);
EXPECT_EQ(zero + zero, zero);
EXPECT_EQ(zero + minus_one, minus_one);
EXPECT_EQ(minus_one + zero, minus_one);
EXPECT_EQ(minus_one + minus_one, minus_two);
}
TEST(BigNum, addition_mixed_signs) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const minus_one = BigNum(-1);
EXPECT_EQ(one + minus_one, zero);
EXPECT_EQ(minus_one + one, zero);
}
TEST(BigNum, addition_flips_sign) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const minus_one = BigNum(-1);
auto const minus_two = BigNum(-2);
EXPECT_EQ(one + minus_two, minus_one);
EXPECT_EQ(minus_two + one, minus_one);
EXPECT_EQ(minus_one + two, one);
EXPECT_EQ(two + minus_one, one);
}
TEST(BigNum, addition_carry) {
auto const one = BigNum(1);
auto const nine = BigNum(9);
auto const ten = BigNum(10);
EXPECT_EQ(one + nine, ten);
EXPECT_EQ(nine + one, ten);
}
TEST(BigNum, substraction_positive) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
EXPECT_EQ(zero - zero, zero);
EXPECT_EQ(two - zero, two);
EXPECT_EQ(two - one, one);
EXPECT_EQ(one - one, zero);
}
TEST(BigNum, substraction_negative) {
auto const zero = BigNum(0);
auto const minus_one = BigNum(-1);
auto const one = BigNum(1);
EXPECT_EQ(zero - zero, zero);
EXPECT_EQ(zero - minus_one, one);
EXPECT_EQ(zero - one, minus_one);
}
TEST(BigNum, substraction_mixed_signs) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const minus_one = BigNum(-1);
auto const minus_two = BigNum(-2);
EXPECT_EQ(one - minus_one, two);
EXPECT_EQ(minus_one - one, minus_two);
}
TEST(BigNum, substraction_flips_sign) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const minus_one = BigNum(-1);
auto const minus_two = BigNum(-2);
EXPECT_EQ(one - two, minus_one);
EXPECT_EQ(minus_one - minus_two, one);
}
TEST(BigNum, multiplication_zero) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const minus_one = BigNum(-1);
EXPECT_EQ(zero * zero, zero);
EXPECT_EQ(zero * one, zero);
EXPECT_EQ(one * zero, zero);
EXPECT_EQ(zero * minus_one, zero);
EXPECT_EQ(minus_one * zero, zero);
}
TEST(BigNum, multiplication_positive) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const four = BigNum(4);
EXPECT_EQ(one * one, one);
EXPECT_EQ(two * one, two);
EXPECT_EQ(one * two, two);
EXPECT_EQ(two * two, four);
}
TEST(BigNum, multiplication_mixed_signs) {
auto const minus_one = BigNum(-1);
auto const one = BigNum(1);
auto const minus_two = BigNum(-2);
auto const two = BigNum(2);
auto const minus_four = BigNum(-4);
auto const four = BigNum(4);
EXPECT_EQ(one * minus_one, minus_one);
EXPECT_EQ(minus_one * one, minus_one);
EXPECT_EQ(minus_one * minus_one, one);
EXPECT_EQ(two * minus_one, minus_two);
EXPECT_EQ(minus_one * two, minus_two);
EXPECT_EQ(two * minus_two, minus_four);
EXPECT_EQ(minus_two * two, minus_four);
EXPECT_EQ(minus_two * minus_two, four);
}
TEST(BigNum, division) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
EXPECT_EQ(one / one, one);
EXPECT_EQ(one / two, zero);
EXPECT_EQ(two / one, two);
}
TEST(BigNum, division_negative) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const minus_one = BigNum(-1);
auto const two = BigNum(2);
auto const minus_two = BigNum(-2);
EXPECT_EQ(one / minus_one, minus_one);
EXPECT_EQ(minus_one / one, minus_one);
EXPECT_EQ(minus_one / minus_one, one);
EXPECT_EQ(two / minus_two, minus_one);
EXPECT_EQ(minus_two / two, minus_one);
EXPECT_EQ(minus_two / minus_two, one);
EXPECT_EQ(one / minus_two, zero);
EXPECT_EQ(minus_one / two, zero);
EXPECT_EQ(one / minus_two, zero);
EXPECT_EQ(minus_one / minus_two, zero);
EXPECT_EQ(two / minus_one, minus_two);
EXPECT_EQ(minus_two / minus_one, two);
EXPECT_EQ(minus_two / one, minus_two);
}
TEST(BigNum, division_truncate) {
auto const one = BigNum(1);
auto const minus_one = BigNum(-1);
auto const three = BigNum(3);
auto const minus_three = BigNum(-3);
auto const five = BigNum(5);
auto const minus_five = BigNum(-5);
EXPECT_EQ(five / three, one);
EXPECT_EQ(five / minus_three, minus_one);
EXPECT_EQ(minus_five / three, minus_one);
EXPECT_EQ(minus_five / minus_three, one);
}
TEST(BigNum, div_mod_identity) {
auto const three = BigNum(3);
auto const minus_three = BigNum(-3);
auto const five = BigNum(5);
auto const minus_five = BigNum(-5);
EXPECT_EQ((five / three) * three + (five % three), five);
EXPECT_EQ((five / minus_three) * minus_three + (five % minus_three), five);
EXPECT_EQ((minus_five / three) * three + (minus_five % three), minus_five);
EXPECT_EQ((minus_five / minus_three) * minus_three
+ (minus_five % minus_three),
minus_five);
}
TEST(BigNum, pow_negative_exponent) {
auto const zero = BigNum(0);
auto const minus_one = BigNum(-1);
auto const three = BigNum(3);
EXPECT_EQ(pow(three, minus_one), zero);
}
TEST(BigNum, pow_zero) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const three = BigNum(3);
EXPECT_EQ(pow(three, zero), one);
EXPECT_EQ(pow(zero, three), zero);
EXPECT_EQ(pow(zero, zero), one); // unclear mathematically
}
TEST(BigNum, pow_one) {
auto const one = BigNum(1);
auto const three = BigNum(3);
EXPECT_EQ(pow(one, one), one);
EXPECT_EQ(pow(one, three), one);
EXPECT_EQ(pow(three, one), three);
}
TEST(BigNum, pow) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const three = BigNum(3);
auto const four = BigNum(4);
auto const eight = BigNum(8);
auto const nine = BigNum(9);
auto const twenty_seven = BigNum(27);
auto const eighty_one = BigNum(81);
EXPECT_EQ(pow(two, two), four);
EXPECT_EQ(pow(two, three), eight);
EXPECT_EQ(pow(three, two), nine);
EXPECT_EQ(pow(three, three), twenty_seven);
EXPECT_EQ(pow(three, four), eighty_one);
}
TEST(BigNum, pow_negative) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const minus_two = BigNum(-2);
auto const three = BigNum(3);
auto const minus_three = BigNum(-3);
auto const four = BigNum(4);
auto const minus_eight = BigNum(-8);
auto const nine = BigNum(9);
auto const minus_twenty_seven = BigNum(-27);
auto const eighty_one = BigNum(81);
EXPECT_EQ(pow(minus_two, two), four);
EXPECT_EQ(pow(minus_two, three), minus_eight);
EXPECT_EQ(pow(minus_three, two), nine);
EXPECT_EQ(pow(minus_three, three), minus_twenty_seven);
EXPECT_EQ(pow(three, four), eighty_one);
}
TEST(BigNum, sqrt_zero) {
auto const zero = BigNum(0);
EXPECT_EQ(sqrt(zero), zero);
}
TEST(BigNum, sqrt_one) {
auto const one = BigNum(1);
EXPECT_EQ(sqrt(one), one);
}
TEST(BigNum, sqrt_truncation) {
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const three = BigNum(3);
EXPECT_EQ(sqrt(two), one);
EXPECT_EQ(sqrt(three), one);
}
TEST(BigNum, sqrt) {
auto const two = BigNum(2);
auto const three = BigNum(3);
auto const four = BigNum(4);
auto const nine = BigNum(9);
auto const ten = BigNum(10);
auto const eighty_one = BigNum(81);
auto const ninety_nine = BigNum(99);
auto const hundred = BigNum(100);
EXPECT_EQ(sqrt(four), two);
EXPECT_EQ(sqrt(nine), three);
EXPECT_EQ(sqrt(eighty_one), nine);
EXPECT_EQ(sqrt(ninety_nine), nine);
EXPECT_EQ(sqrt(hundred), ten);
}
TEST(BigNum, log2) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const three = BigNum(3);
auto const four = BigNum(4);
auto const five = BigNum(5);
auto const seven = BigNum(7);
auto const eight = BigNum(8);
auto const nine = BigNum(9);
EXPECT_EQ(log2(one), zero);
EXPECT_EQ(log2(two), one);
EXPECT_EQ(log2(three), one);
EXPECT_EQ(log2(four), two);
EXPECT_EQ(log2(five), two);
EXPECT_EQ(log2(seven), two);
EXPECT_EQ(log2(eight), three);
EXPECT_EQ(log2(nine), three);
}
TEST(BigNum, log10) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const nine = BigNum(9);
auto const ten = BigNum(10);
auto const eleven = BigNum(11);
auto const ninety_nine = BigNum(99);
auto const hundred = BigNum(100);
auto const hundred_one = BigNum(101);
EXPECT_EQ(log10(one), zero);
EXPECT_EQ(log10(nine), zero);
EXPECT_EQ(log10(ten), one);
EXPECT_EQ(log10(eleven), one);
EXPECT_EQ(log10(ninety_nine), one);
EXPECT_EQ(log10(hundred), two);
EXPECT_EQ(log10(hundred_one), two);
}