[mathicgb] 217/393: Added test to the new methods on MonoMonoid and PrimeField.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:04 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.
commit 0b8b2b6a7b3adc348ce3ad487310b4ce1ebd657c
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Mon Apr 1 00:33:52 2013 +0200
Added test to the new methods on MonoMonoid and PrimeField.
---
src/mathicgb/MonoMonoid.hpp | 203 +++++++++++++++++++-------------
src/test/MonoMonoid.cpp | 276 +++++++++++++++++++++++++++++++++++---------
src/test/PrimeField.cpp | 51 ++++++++
3 files changed, 395 insertions(+), 135 deletions(-)
diff --git a/src/mathicgb/MonoMonoid.hpp b/src/mathicgb/MonoMonoid.hpp
index 2a6b2ad..949be65 100755
--- a/src/mathicgb/MonoMonoid.hpp
+++ b/src/mathicgb/MonoMonoid.hpp
@@ -363,9 +363,12 @@ public:
bool hasAmpleCapacity(ConstMonoRef mono) const {
const auto halfMin = std::numeric_limits<Exponent>::min() / 2;
const auto halfMax = std::numeric_limits<Exponent>::max() / 2;
- for (VarIndex i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) {
+ MATHICGB_ASSERT(halfMin <= 0);
+ const auto limit = std::min(-halfMin, halfMax);
+
+ for (VarIndex i = exponentsIndexBegin(); i != orderIndexEnd(); ++i) {
const auto value = access(mono, i);
- if (!(halfMin <= value && value <= halfMax))
+ if (!(-limit <= value && value <= limit))
return false;
}
return true;
@@ -537,89 +540,10 @@ public:
/// will be parsed as two separate monomials. A suffix like <2> puts
/// the monomial in component 2, so a5<2> is a^5e_2. The default
/// component is 0.
- void parseM2(std::istream& in, MonoRef mono) const {
- setIdentity(mono);
-
- bool sawSome = false;
- while (true) {
- const char next = in.peek();
- if (!sawSome && next == '1') {
- in.get();
- break;
- }
-
- VarIndex var;
- const auto letterCount = 'z' - 'a' + 1;
- if ('a' <= next && next <= 'z')
- var = next - 'a';
- else if ('A' <= next && next <= 'Z')
- var = (next - 'A') + letterCount;
- else if (sawSome)
- break;
- else {
- mathic::reportError("Could not parse monomial.");
- return;
- }
- MATHICGB_ASSERT(var < 2 * letterCount);
- if (var >= varCount()) {
- mathic::reportError("Unknown variable.");
- return;
- }
- in.get();
- auto& exponent = access(mono, exponentsIndexBegin() + var);
- if (isdigit(in.peek()))
- in >> exponent;
- else
- exponent = 1;
- sawSome = true;
- }
-
- if (in.peek() == '<') {
- in.get();
- if (!isdigit(in.peek())) {
- mathic::reportError("Component was not integer.");
- return;
- }
- in >> access(mono, componentIndex());
- if (in.peek() != '>') {
- mathic::reportError("Component < was not matched by >.");
- return;
- }
- in.get();
- }
-
- setOrderData(mono);
- setHash(mono);
- MATHICGB_ASSERT(debugValid(mono));
- }
+ void parseM2(std::istream& in, MonoRef mono) const;
// Inverse of parseM2().
- void printM2(ConstMonoRef mono, std::ostream& out) const {
- const auto letterCount = 'z' - 'a' + 1;
-
- bool printedSome = false;
- for (VarIndex var = 0; var < varCount(); ++var) {
- if (exponent(mono, var) == 0)
- continue;
- char letter;
- if (var < letterCount)
- letter = 'a' + var;
- else if (var < 2 * letterCount)
- letter = 'A' + (var - letterCount);
- else {
- mathic::reportError("Too few letters in alphabet to print variable.");
- return;
- }
- printedSome = true;
- out << letter;
- if (exponent(mono, var) != 1)
- out << exponent(mono, var);
- }
- if (!printedSome)
- out << '1';
- if (component(mono) != 0)
- out << '<' << component(mono) << '>';
- }
+ void printM2(ConstMonoRef mono, std::ostream& out) const;
// *** Classes for holding and referring to monomials
@@ -1149,4 +1073,117 @@ private:
std::vector<Exponent> mGrading;
};
+namespace MonoMonoidHelper {
+ /// ostream and istream handle characters differently from other
+ /// integers. Use unchar to cast chars to a different type that get
+ /// handled as other integers do.
+ template<class T>
+ struct unchar {typedef int type;};
+
+ // Yes: char, signed char and unsigned char are 3 distinct types.
+ template<>
+ struct unchar<char> {typedef short type;};
+ template<>
+ struct unchar<signed char> {typedef short type;};
+ template<>
+ struct unchar<unsigned char> {typedef unsigned short type;};
+}
+
+template<class E>
+void MonoMonoid<E>::parseM2(std::istream& in, MonoRef mono) const {
+ using MonoMonoidHelper::unchar;
+ // todo: signal error on exponent overflow
+
+ setIdentity(mono);
+
+ bool sawSome = false;
+ while (true) {
+ const char next = in.peek();
+ if (!sawSome && next == '1') {
+ in.get();
+ break;
+ }
+
+ VarIndex var;
+ const auto letterCount = 'z' - 'a' + 1;
+ if ('a' <= next && next <= 'z')
+ var = next - 'a';
+ else if ('A' <= next && next <= 'Z')
+ var = (next - 'A') + letterCount;
+ else if (sawSome)
+ break;
+ else {
+ mathic::reportError("Could not parse monomial.");
+ return;
+ }
+ MATHICGB_ASSERT(var < 2 * letterCount);
+ if (var >= varCount()) {
+ mathic::reportError("Unknown variable.");
+ return;
+ }
+
+ in.get();
+ auto& exponent = access(mono, exponentsIndexBegin() + var);
+ if (isdigit(in.peek())) {
+ typename unchar<Exponent>::type e;
+ in >> e;
+ exponent = e;
+ } else
+ exponent = 1;
+ sawSome = true;
+ }
+
+ if (in.peek() == '<') {
+ in.get();
+ if (!isdigit(in.peek())) {
+ mathic::reportError("Component was not integer.");
+ return;
+ }
+ typename unchar<Exponent>::type e;
+ in >> e;
+ access(mono, componentIndex()) = e;
+ if (in.peek() != '>') {
+ mathic::reportError("Component < was not matched by >.");
+ return;
+ }
+ in.get();
+ }
+
+ setOrderData(mono);
+ setHash(mono);
+ MATHICGB_ASSERT(debugValid(mono));
+}
+
+template<class E>
+void MonoMonoid<E>::printM2(ConstMonoRef mono, std::ostream& out) const {
+ using MonoMonoidHelper::unchar;
+ const auto letterCount = 'z' - 'a' + 1;
+
+ bool printedSome = false;
+ for (VarIndex var = 0; var < varCount(); ++var) {
+ if (exponent(mono, var) == 0)
+ continue;
+ char letter;
+ if (var < letterCount)
+ letter = 'a' + var;
+ else if (var < 2 * letterCount)
+ letter = 'A' + (var - letterCount);
+ else {
+ mathic::reportError("Too few letters in alphabet to print variable.");
+ return;
+ }
+ printedSome = true;
+ out << letter;
+ if (exponent(mono, var) != 1)
+ out << static_cast<typename unchar<Exponent>::type>(exponent(mono, var));
+ }
+ if (!printedSome)
+ out << '1';
+ if (component(mono) != 0) {
+ out << '<'
+ << static_cast<typename unchar<Exponent>::type>(component(mono))
+ << '>';
+ }
+}
+
#endif
diff --git a/src/test/MonoMonoid.cpp b/src/test/MonoMonoid.cpp
index 3d036fd..96051bb 100755
--- a/src/test/MonoMonoid.cpp
+++ b/src/test/MonoMonoid.cpp
@@ -243,69 +243,78 @@ namespace {
}
}
-TEST(MonoMonoid, ParsePrintM2) {
- MonoMonoid<int32> m(100);
- const char* str = "1 a z A Z ab a2 a2b ab2 a20b30 1<1> a<2> a2<3> ab<11>\n";
- auto v2 = parseVector(m, str);
- std::ostringstream v2Out;
- v2.printM2(v2Out);
- ASSERT_EQ(str, v2Out.str());
-
- decltype(v2) v(m);
- v.push_back(); // 1
-
- v.push_back(); // a
- m.setExponent(0, 1, v.back());
+namespace {
+ template<class E>
+ void parsePrintM2Helper() {
+ MonoMonoid<E> m(100);
+ const char* str = "1 a z A Z ab a2 a2b ab2 a20b30 1<1> a<2> a2<3> ab<11>\n";
+ auto v2 = parseVector(m, str);
+ std::ostringstream v2Out;
+ v2.printM2(v2Out);
+ ASSERT_EQ(str, v2Out.str());
+
+ decltype(v2) v(m);
+ v.push_back(); // 1
+
+ v.push_back(); // a
+ m.setExponent(0, 1, v.back());
- v.push_back(); // z
- m.setExponent(25, 1, v.back());
+ v.push_back(); // z
+ m.setExponent(25, 1, v.back());
- v.push_back(); // A
- m.setExponent(26, 1, v.back());
+ v.push_back(); // A
+ m.setExponent(26, 1, v.back());
- v.push_back(); // Z
- m.setExponent(51, 1, v.back());
+ v.push_back(); // Z
+ m.setExponent(51, 1, v.back());
- v.push_back(); // ab
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 1, v.back());
+ v.push_back(); // ab
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 1, v.back());
- v.push_back(); // a2
- m.setExponent(0, 2, v.back());
+ v.push_back(); // a2
+ m.setExponent(0, 2, v.back());
- v.push_back(); // a2b
- m.setExponent(0, 2, v.back());
- m.setExponent(1, 1, v.back());
+ v.push_back(); // a2b
+ m.setExponent(0, 2, v.back());
+ m.setExponent(1, 1, v.back());
- v.push_back(); // ab2
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 2, v.back());
+ v.push_back(); // ab2
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 2, v.back());
- v.push_back(); // a20b30
- m.setExponent(0, 20, v.back());
- m.setExponent(1, 30, v.back());
+ v.push_back(); // a20b30
+ m.setExponent(0, 20, v.back());
+ m.setExponent(1, 30, v.back());
- v.push_back(); // 1<1>
- m.setComponent(1, v.back());
+ v.push_back(); // 1<1>
+ m.setComponent(1, v.back());
- v.push_back(); // a<2>
- m.setComponent(2, v.back());
- m.setExponent(0, 1, v.back());
+ v.push_back(); // a<2>
+ m.setComponent(2, v.back());
+ m.setExponent(0, 1, v.back());
- v.push_back(); // a2<3>
- m.setComponent(3, v.back());
- m.setExponent(0, 2, v.back());
+ v.push_back(); // a2<3>
+ m.setComponent(3, v.back());
+ m.setExponent(0, 2, v.back());
- v.push_back(); // ab<11>
- m.setComponent(11, v.back());
- m.setExponent(0, 1, v.back());
- m.setExponent(1, 1, v.back());
+ v.push_back(); // ab<11>
+ m.setComponent(11, v.back());
+ m.setExponent(0, 1, v.back());
+ m.setExponent(1, 1, v.back());
- std::ostringstream vOut;
- v.printM2(vOut);
- ASSERT_EQ(str, vOut.str());
+ std::ostringstream vOut;
+ v.printM2(vOut);
+ ASSERT_EQ(str, vOut.str());
- ASSERT_EQ(v, v2);
+ ASSERT_EQ(v, v2);
+ }
+}
+
+TEST(MonoMonoid, ParsePrintM2) {
+ parsePrintM2Helper<int32>();
+ parsePrintM2Helper<int16>();
+ parsePrintM2Helper<int8>();
}
TEST(MonoMonoid, MultiplyDivide) {
@@ -418,6 +427,64 @@ TEST(MonoMonoid, MultiplyDivide) {
check("abcdefghiV<7> ab2c3d4e5f6g7h8i9V11 a2b3c4d5e6f7g8h9i10V12<7>");
}
+TEST(MonoMonoid, LcmColon) {
+ typedef MonoMonoid<int32> Monoid;
+ Monoid m(49);
+ Monoid::MonoPool pool(m);
+ auto mono = pool.alloc();
+ auto mono2 = pool.alloc();
+ auto check = [&](const char* str) {
+ auto v = parseVector(m, str);
+ MATHICGB_ASSERT(v.size() == 3);
+ const auto& a = v.front();
+ const auto& b = *++v.begin();
+ const auto& lcm = v.back();
+
+ // isLcm
+ ASSERT_TRUE(m.isLcm(a, b, lcm));
+ m.copy(lcm, mono);
+ m.setExponent(1, m.exponent(mono, 1) + 1, mono);
+ ASSERT_FALSE(m.isLcm(a, b, mono));
+
+ // dividesLcm
+ ASSERT_TRUE(m.dividesLcm(lcm, a, b));
+ ASSERT_FALSE(m.dividesLcm(mono, a, b));
+ ASSERT_TRUE(m.dividesLcm(a, a, a));
+ ASSERT_TRUE(m.dividesLcm(a, a, b));
+ ASSERT_TRUE(m.dividesLcm(b, b, b));
+ ASSERT_TRUE(m.dividesLcm(b, b, a));
+
+ // lcm(a, b)
+ m.lcm(a, b, mono);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(lcm), m.hash(mono));
+
+ // lcm(b, a)
+ m.lcm(b, a, mono);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_EQ(m.hash(lcm), m.hash(mono));
+
+ // colons
+ m.colons(a, b, mono, mono2);
+ m.multiply(b, mono, mono);
+ m.multiply(a, mono2, mono2);
+ ASSERT_TRUE(m.equal(mono, lcm));
+ ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo);
+ ASSERT_TRUE(m.equal(mono2, lcm));
+ ASSERT_TRUE(m.compare(mono2, lcm) == Monoid::EqualTo);
+ };
+ check("1 1 1");
+ check("a<2> 1<2> a<2>");
+ check("1 Vx Vx");
+ check("aV bx abxV");
+ check("a a2 a2");
+ check("V<3> V2<3> V2<3>");
+ check("arlgh svug arlghsvu");
+ check("a6b7c8d9efghiV ab2c3d4e5f6g7h8i9V11 a6b7c8d9e5f6g7h8i9V11");
+}
+
TEST(MonoMonoid, Order) {
typedef MonoMonoid<int32> Monoid;
Monoid m(52);
@@ -429,9 +496,6 @@ TEST(MonoMonoid, Order) {
ASSERT_FALSE(m.lessThan(*greater, *greater));
for (auto lesser = v.begin(); lesser != greater; ++lesser) {
- //m.printM2(*lesser, std::cout); std::cout<<' ';
- //m.printM2(*greater, std::cout); std::cout<<std::endl;
-
ASSERT_FALSE(m.equal(*lesser, *greater));
ASSERT_TRUE(m.lessThan(*lesser, *greater));
ASSERT_FALSE(m.lessThan(*greater, *lesser));
@@ -440,3 +504,111 @@ TEST(MonoMonoid, Order) {
}
}
}
+
+TEST(MonoMonoid, RelativelyPrime) {
+ typedef MonoMonoid<int32> Monoid;
+ Monoid m(49);
+ Monoid::MonoPool pool(m);
+ auto mono = pool.alloc();
+ auto mono2 = pool.alloc();
+ auto check = [&](const char* str, bool relativelyPrime) {
+ auto v = parseVector(m, str);
+ MATHICGB_ASSERT(v.size() == 2);
+ ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.front(), v.back()));
+ ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.back(), v.front()));
+ };
+ check("1 1", true);
+ check("1 abcdefgh", true);
+ check("abc defgh", true);
+ check("bdfh aceg", true);
+ check("bdefh aceg", false);
+ check("abcdefgh abcdefgh", false);
+ check("fgh abcdef", false);
+}
+
+TEST(MonoMonoid, SetExponents) {
+ typedef MonoMonoid<int32> Monoid;
+ Monoid m(5);
+ auto v = parseVector(m, "a1b2c3d4e5");
+ int32 exponents[] = {1, 2, 3, 4, 5};
+ v.push_back();
+ m.setExponents(exponents, v.back());
+ ASSERT_TRUE(m.equal(v.front(), v.back()));
+}
+
+TEST(MonoMonoid, HasAmpleCapacity) {
+ // non-total-degree grading, last char is c
+ std::vector<int8> v8;
+ v8.push_back(1);
+ v8.push_back(10);
+ v8.push_back(1);
+ MonoMonoid<int8> m8(v8);
+
+ // total degree grading, last char is d.
+ MonoMonoid<int16> m16(4);
+
+ // non-total-degree grading, last char is e
+ std::vector<int32> v32;
+ v32.push_back(1);
+ v32.push_back(10);
+ v32.push_back(1);
+ v32.push_back(1);
+ v32.push_back(1);
+ MonoMonoid<int32> m32(v32);
+
+ // total degree grading, last char is n
+ MonoMonoid<int32> m32t(14);
+
+
+ // pure power, first variable
+ auto f8 = parseVector(m8, "a63 a64");
+ ASSERT_TRUE(m8.hasAmpleCapacity(f8.front()));
+ ASSERT_FALSE(m8.hasAmpleCapacity(f8.back()));
+
+ auto f16 = parseVector(m16, "a16383 a16384");
+ ASSERT_TRUE(m16.hasAmpleCapacity(f16.front()));
+ ASSERT_FALSE(m16.hasAmpleCapacity(f16.back()));
+
+ auto f32 = parseVector(m32, "a1073741823 a1073741824");
+ ASSERT_TRUE(m32.hasAmpleCapacity(f32.front()));
+ ASSERT_FALSE(m32.hasAmpleCapacity(f32.back()));
+
+ auto f32t = parseVector(m32t, "a1073741823 a1073741824");
+ ASSERT_TRUE(m32.hasAmpleCapacity(f32t.front()));
+ ASSERT_FALSE(m32.hasAmpleCapacity(f32t.back()));
+
+ // pure power, last variable
+ auto l8 = parseVector(m8, "c63 c64");
+ ASSERT_TRUE(m8.hasAmpleCapacity(l8.front()));
+ ASSERT_FALSE(m8.hasAmpleCapacity(l8.back()));
+
+ auto l16 = parseVector(m16, "d16383 d16384");
+ ASSERT_TRUE(m16.hasAmpleCapacity(l16.front()));
+ ASSERT_FALSE(m16.hasAmpleCapacity(l16.back()));
+
+ auto l32 = parseVector(m32, "e1073741823 e1073741824");
+ ASSERT_TRUE(m32.hasAmpleCapacity(l32.front()));
+ ASSERT_FALSE(m32.hasAmpleCapacity(l32.back()));
+
+ auto l32t = parseVector(m32t, "n1073741823 n1073741824");
+ ASSERT_TRUE(m32t.hasAmpleCapacity(l32t.front()));
+ ASSERT_FALSE(m32t.hasAmpleCapacity(l32t.back()));
+
+ // no exponent is too high but the degree is
+ auto d8 = parseVector(m8, "abc52 abc53");
+ ASSERT_TRUE(m8.hasAmpleCapacity(d8.front()));
+ ASSERT_FALSE(m8.hasAmpleCapacity(d8.back()));
+
+ auto d16 = parseVector(m16, "abcd16380 abcd16381");
+ ASSERT_TRUE(m16.hasAmpleCapacity(d16.front()));
+ ASSERT_FALSE(m16.hasAmpleCapacity(d16.back()));
+
+ auto d32 = parseVector(m32, "abcde1073741810 abcde1073741811");
+ ASSERT_TRUE(m32.hasAmpleCapacity(d32.front()));
+ ASSERT_FALSE(m32.hasAmpleCapacity(d32.back()));
+
+ auto d32t = parseVector
+ (m32t, "abcdefghijklmn1073741810 abcdefghijklmn1073741811");
+ ASSERT_TRUE(m32t.hasAmpleCapacity(d32t.front()));
+ ASSERT_FALSE(m32t.hasAmpleCapacity(d32t.back()));
+}
diff --git a/src/test/PrimeField.cpp b/src/test/PrimeField.cpp
old mode 100644
new mode 100755
index 9221c9e..d52418b
--- a/src/test/PrimeField.cpp
+++ b/src/test/PrimeField.cpp
@@ -171,3 +171,54 @@ TEST(PrimeField, Inverse) {
ASSERT_EQ(pf32.toElement(-1), pf32.inverse(pf32.toElement(-1)));
ASSERT_EQ(pf32.toElement(3015615332u), pf32.inverse(pf32.toElement(47)));
}
+
+TEST(PrimeField, Quotient) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.one(), pf2.quotient(pf2.one(), pf2.one()));
+ ASSERT_EQ(pf2.zero(), pf2.quotient(pf2.zero(), pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.one(), pf2.quotient(pf251.one(), pf251.one()));
+ ASSERT_EQ
+ (pf251.toElement(-1), pf251.quotient(pf251.one(), pf251.toElement(-1)));
+ ASSERT_EQ
+ (pf251.toElement(-1), pf251.quotient(pf251.toElement(-1), pf251.one()));
+ ASSERT_EQ(
+ pf251.one(),
+ pf251.quotient(pf251.toElement(-1), pf251.toElement(-1))
+ );
+ ASSERT_EQ(
+ pf251.toElement(203),
+ pf251.quotient(pf251.toElement(3), pf251.toElement(47))
+ );
+
+ const PrimeField<uint16> pf16(65521);
+ ASSERT_EQ(
+ pf16.toElement(20911),
+ pf16.quotient(pf16.toElement(2), pf16.toElement(47))
+ );
+
+ const PrimeField<uint32> pf32(4294967291u);
+ ASSERT_EQ(
+ pf32.toElement(3015615332u),
+ pf32.quotient(pf32.toElement(1), pf32.toElement(47))
+ );
+}
+
+TEST(PrimeField, PlusOne) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.zero(), pf2.plusOne(pf2.one()));
+ ASSERT_EQ(pf2.one(), pf2.plusOne(pf2.zero()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.one(), pf251.plusOne(pf251.zero()));
+ ASSERT_EQ(pf251.zero(), pf251.plusOne(pf251.toElement(-1)));
+ ASSERT_EQ(pf251.toElement(250), pf251.plusOne(pf251.toElement(249)));
+
+ const PrimeField<uint16> pf16(65521);
+ ASSERT_EQ(pf16.toElement(20911), pf16.plusOne(pf16.toElement(20910)));
+
+ const PrimeField<uint32> pf32(4294967291u);
+ ASSERT_EQ
+ (pf32.toElement(3015615332u), pf32.plusOne(pf32.toElement(3015615331u)));
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git
More information about the debian-science-commits
mailing list