[mathicgb] 202/393: Added a PrimeField class along with tests. This class is supposed to take over the coefficient code in PolyRing.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:00 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 f86a4b2287fa2b896563ecb5cdde98910c705d27
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Fri Mar 22 21:53:24 2013 +0100
Added a PrimeField class along with tests. This class is supposed to take over the coefficient code in PolyRing.
---
Makefile.am | 104 +++++------
build/vs12/mathicgb-lib/mathicgb-lib.vcxproj | 2 +
.../vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters | 6 +
build/vs12/mathicgb-test/mathicgb-test.vcxproj | 1 +
.../mathicgb-test/mathicgb-test.vcxproj.filters | 3 +
src/mathicgb/PrimeField.hpp | 199 +++++++++++++++++++++
src/test/PrimeField.cpp | 173 ++++++++++++++++++
7 files changed, 436 insertions(+), 52 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index f3f66ca..1b8e407 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,58 +17,58 @@ libmathicgb_la_LIBADD= $(DEPS_LIBS)
# the sources that are built to make libmathicgb. Listing the headers in
# sources ensure that those files are included in distributions.
-libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp \
+libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp \
src/mathicgb/BjarkeGeobucket2.hpp src/mathicgb/BjarkeGeobucket.cpp \
- src/mathicgb/BjarkeGeobucket.hpp src/mathicgb/BuchbergerAlg.cpp \
- src/mathicgb/BuchbergerAlg.hpp src/mathicgb/ChainedHashTable.cpp \
- src/mathicgb/ChainedHashTable.hpp src/mathicgb/DivisorLookup.hpp \
- src/mathicgb/DivisorLookup.cpp src/mathicgb/DivLookup.hpp \
- src/mathicgb/FreeModuleOrder.cpp src/mathicgb/FreeModuleOrder.hpp \
- src/mathicgb/GroebnerBasis.cpp src/mathicgb/GroebnerBasis.hpp \
- src/mathicgb/HashTourReducer.cpp src/mathicgb/HashTourReducer.hpp \
- src/mathicgb/Ideal.cpp src/mathicgb/Ideal.hpp \
- src/mathicgb/io-util.cpp src/mathicgb/io-util.hpp \
- src/mathicgb/KoszulQueue.cpp src/mathicgb/KoszulQueue.hpp \
- src/mathicgb/MonomialHashTable.hpp \
- src/mathicgb/MonTableDivList.hpp src/mathicgb/MonTableKDTree.hpp \
- src/mathicgb/MonTableNaive.cpp src/mathicgb/MonTableNaive.hpp \
- src/mathicgb/MTArray.cpp src/mathicgb/MTArray.hpp \
- src/mathicgb/PairTriangle.cpp src/mathicgb/PairTriangle.hpp \
- src/mathicgb/Poly.cpp src/mathicgb/Poly.hpp \
- src/mathicgb/PolyBasis.cpp src/mathicgb/PolyBasis.hpp \
- src/mathicgb/PolyGeoBucket.cpp src/mathicgb/PolyGeoBucket.hpp \
- src/mathicgb/PolyHashReducer.cpp src/mathicgb/PolyHashReducer.hpp \
- src/mathicgb/PolyHashTable.cpp src/mathicgb/PolyHashTable.hpp \
- src/mathicgb/PolyHeap.cpp src/mathicgb/PolyHeap.hpp \
- src/mathicgb/PolyReducer.cpp src/mathicgb/PolyReducer.hpp \
- src/mathicgb/PolyRing.cpp src/mathicgb/PolyRing.hpp \
- src/mathicgb/Reducer.cpp src/mathicgb/Reducer.hpp \
- src/mathicgb/ReducerDedup.hpp src/mathicgb/ReducerHash.hpp \
- src/mathicgb/ReducerHashPack.hpp src/mathicgb/ReducerHelper.hpp \
- src/mathicgb/ReducerNoDedup.hpp src/mathicgb/ReducerPack.hpp \
- src/mathicgb/ReducerPackDedup.hpp src/mathicgb/SignatureGB.cpp \
- src/mathicgb/SignatureGB.hpp src/mathicgb/SigSPairs.cpp \
- src/mathicgb/SigSPairs.hpp src/mathicgb/SPairs.cpp \
- src/mathicgb/SPairs.hpp src/mathicgb/stdinc.h \
- src/mathicgb/TournamentReducer.cpp \
- src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp \
- src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp \
- src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp \
- src/mathicgb/QuadMatrixBuilder.cpp src/mathicgb/TypicalReducer.cpp\
- src/mathicgb/TypicalReducer.cpp src/mathicgb/F4Reducer.hpp \
- src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp \
- src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp \
- src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp \
- src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp \
- src/mathicgb/RawVector.hpp src/mathicgb/Atomic.hpp \
- src/mathicgb/FixedSizeMonomialMap.hpp src/mathicgb/CFile.hpp \
- src/mathicgb/CFile.cpp src/mathicgb/LogDomain.hpp \
- src/mathicgb/LogDomain.cpp src/mathicgb/LogDomainSet.hpp \
- src/mathicgb/F4MatrixBuilder2.hpp src/mathicgb/F4MatrixBuilder2.cpp \
- src/mathicgb/LogDomainSet.cpp src/mathicgb/F4ProtoMatrix.hpp \
- src/mathicgb/F4ProtoMatrix.cpp src/mathicgb/F4MatrixProject.hpp \
- src/mathicgb/F4MatrixProjection.cpp src/mathicgb/ScopeExit.hpp \
- src/mathicgb.cpp src/mathicgb.h src/mathicgb/mtbb.hpp
+ src/mathicgb/BjarkeGeobucket.hpp src/mathicgb/BuchbergerAlg.cpp \
+ src/mathicgb/BuchbergerAlg.hpp src/mathicgb/ChainedHashTable.cpp \
+ src/mathicgb/ChainedHashTable.hpp src/mathicgb/DivisorLookup.hpp \
+ src/mathicgb/DivisorLookup.cpp src/mathicgb/DivLookup.hpp \
+ src/mathicgb/FreeModuleOrder.cpp src/mathicgb/FreeModuleOrder.hpp \
+ src/mathicgb/GroebnerBasis.cpp src/mathicgb/GroebnerBasis.hpp \
+ src/mathicgb/HashTourReducer.cpp src/mathicgb/HashTourReducer.hpp \
+ src/mathicgb/Ideal.cpp src/mathicgb/Ideal.hpp \
+ src/mathicgb/io-util.cpp src/mathicgb/io-util.hpp \
+ src/mathicgb/KoszulQueue.cpp src/mathicgb/KoszulQueue.hpp \
+ src/mathicgb/MonomialHashTable.hpp src/mathicgb/MonTableDivList.hpp \
+ src/mathicgb/MonTableKDTree.hpp src/mathicgb/MonTableNaive.cpp \
+ src/mathicgb/MonTableNaive.hpp src/mathicgb/MTArray.cpp \
+ src/mathicgb/MTArray.hpp src/mathicgb/PairTriangle.cpp \
+ src/mathicgb/PairTriangle.hpp src/mathicgb/Poly.cpp \
+ src/mathicgb/Poly.hpp src/mathicgb/PolyBasis.cpp \
+ src/mathicgb/PolyBasis.hpp src/mathicgb/PolyGeoBucket.cpp \
+ src/mathicgb/PolyGeoBucket.hpp src/mathicgb/PolyHashReducer.cpp \
+ src/mathicgb/PolyHashReducer.hpp src/mathicgb/PolyHashTable.cpp \
+ src/mathicgb/PolyHashTable.hpp src/mathicgb/PolyHeap.cpp \
+ src/mathicgb/PolyHeap.hpp src/mathicgb/PolyReducer.cpp \
+ src/mathicgb/PolyReducer.hpp src/mathicgb/PolyRing.cpp \
+ src/mathicgb/PolyRing.hpp src/mathicgb/Reducer.cpp \
+ src/mathicgb/Reducer.hpp src/mathicgb/ReducerDedup.hpp \
+ src/mathicgb/ReducerHash.hpp src/mathicgb/ReducerHashPack.hpp \
+ src/mathicgb/ReducerHelper.hpp src/mathicgb/ReducerNoDedup.hpp \
+ src/mathicgb/ReducerPack.hpp src/mathicgb/ReducerPackDedup.hpp \
+ src/mathicgb/SignatureGB.cpp src/mathicgb/SignatureGB.hpp \
+ src/mathicgb/SigSPairs.cpp src/mathicgb/SigSPairs.hpp \
+ src/mathicgb/SPairs.cpp src/mathicgb/SPairs.hpp \
+ src/mathicgb/stdinc.h src/mathicgb/TournamentReducer.cpp \
+ src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp \
+ src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp \
+ src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp \
+ src/mathicgb/QuadMatrixBuilder.cpp src/mathicgb/TypicalReducer.cpp \
+ src/mathicgb/TypicalReducer.cpp src/mathicgb/F4Reducer.hpp \
+ src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp \
+ src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp \
+ src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp \
+ src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp \
+ src/mathicgb/RawVector.hpp src/mathicgb/Atomic.hpp \
+ src/mathicgb/FixedSizeMonomialMap.hpp src/mathicgb/CFile.hpp \
+ src/mathicgb/CFile.cpp src/mathicgb/LogDomain.hpp \
+ src/mathicgb/LogDomain.cpp src/mathicgb/LogDomainSet.hpp \
+ src/mathicgb/F4MatrixBuilder2.hpp src/mathicgb/F4MatrixBuilder2.cpp \
+ src/mathicgb/LogDomainSet.cpp src/mathicgb/F4ProtoMatrix.hpp \
+ src/mathicgb/F4ProtoMatrix.cpp src/mathicgb/F4MatrixProject.hpp \
+ src/mathicgb/F4MatrixProjection.cpp src/mathicgb/ScopeExit.hpp \
+ src/mathicgb.cpp src/mathicgb.h src/mathicgb/mtbb.hpp \
+ src/mathicgb/PrimeField.hpp src/mathicgb/PrimeField.cpp
# The headers that libmathicgb installs.
@@ -115,7 +115,7 @@ unittest_SOURCES=src/test/FreeModuleOrderTest.cpp \
src/test/ideals.cpp src/test/poly-test.cpp src/test/ideals.hpp \
src/test/SparseMatrix.cpp src/test/QuadMatrixBuilder.cpp \
src/test/F4MatrixBuilder.cpp src/test/F4MatrixReducer.cpp \
- src/test/mathicgb.cpp
+ src/test/mathicgb.cpp src/test/PrimeField.cpp
else
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
index 6a59c49..64901bf 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj
@@ -471,6 +471,7 @@
<ClCompile Include="..\..\..\src\mathicgb\PolyHeap.cpp" />
<ClCompile Include="..\..\..\src\mathicgb\PolyReducer.cpp" />
<ClCompile Include="..\..\..\src\mathicgb\PolyRing.cpp" />
+ <ClCompile Include="..\..\..\src\mathicgb\PrimeField.cpp" />
<ClCompile Include="..\..\..\src\mathicgb\QuadMatrix.cpp" />
<ClCompile Include="..\..\..\src\mathicgb\QuadMatrixBuilder.cpp" />
<ClCompile Include="..\..\..\src\mathicgb\Reducer.cpp" />
@@ -523,6 +524,7 @@
<ClInclude Include="..\..\..\src\mathicgb\PolyHeap.hpp" />
<ClInclude Include="..\..\..\src\mathicgb\PolyReducer.hpp" />
<ClInclude Include="..\..\..\src\mathicgb\PolyRing.hpp" />
+ <ClInclude Include="..\..\..\src\mathicgb\PrimeField.hpp" />
<ClInclude Include="..\..\..\src\mathicgb\QuadMatrix.hpp" />
<ClInclude Include="..\..\..\src\mathicgb\QuadMatrixBuilder.hpp" />
<ClInclude Include="..\..\..\src\mathicgb\RawVector.hpp" />
diff --git a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
index 7b57653..608440b 100755
--- a/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
+++ b/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters
@@ -141,6 +141,9 @@
<ClCompile Include="..\..\..\src\mathicgb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\src\mathicgb\PrimeField.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\mathicgb\BjarkeGeobucket.hpp">
@@ -323,5 +326,8 @@
<ClInclude Include="..\..\..\src\mathicgb\mtbb.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\src\mathicgb\PrimeField.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
diff --git a/build/vs12/mathicgb-test/mathicgb-test.vcxproj b/build/vs12/mathicgb-test/mathicgb-test.vcxproj
index 6c53744..3289285 100755
--- a/build/vs12/mathicgb-test/mathicgb-test.vcxproj
+++ b/build/vs12/mathicgb-test/mathicgb-test.vcxproj
@@ -404,6 +404,7 @@
<ClCompile Include="..\..\..\src\test\ideals.cpp" />
<ClCompile Include="..\..\..\src\test\mathicgb.cpp" />
<ClCompile Include="..\..\..\src\test\poly-test.cpp" />
+ <ClCompile Include="..\..\..\src\test\PrimeField.cpp" />
<ClCompile Include="..\..\..\src\test\QuadMatrixBuilder.cpp" />
<ClCompile Include="..\..\..\src\test\SparseMatrix.cpp" />
<ClCompile Include="..\..\..\src\test\testMain.cpp" />
diff --git a/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters b/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
index eb741c1..d84330d 100755
--- a/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
+++ b/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters
@@ -48,6 +48,9 @@
<ClCompile Include="..\..\..\src\test\mathicgb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\src\test\PrimeField.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\test\ideals.hpp">
diff --git a/src/mathicgb/PrimeField.hpp b/src/mathicgb/PrimeField.hpp
new file mode 100644
index 0000000..7a90c54
--- /dev/null
+++ b/src/mathicgb/PrimeField.hpp
@@ -0,0 +1,199 @@
+#ifndef MATHICGB_PRIME_FIELD_GUARD
+#define MATHICGB_PRIME_FIELD_GUARD
+
+#include <limits>
+#include <type_traits>
+#include <ostream>
+
+/// Implements arithmetic in a prime field. T must be an unsigned integer type
+/// that is used to store the elements of the field. The characteristic of the
+/// field must be a prime not exceeding std::numeric_limits<T>::max().
+template<class T>
+class PrimeField {
+public:
+ class Element {
+ public:
+ static_assert(!std::numeric_limits<T>::is_signed, "");
+ static_assert(std::numeric_limits<T>::is_integer, "");
+
+ Element(const Element& e): mValue(e.value()) {}
+
+ Element& operator=(const Element& e) {
+ mValue = e.value();
+ return *this;
+ }
+
+ bool operator==(const Element e) const {return value() == e.value();}
+ bool operator!=(const Element e) const {return !(*this == e);}
+ T value() const {return mValue;}
+
+ private:
+ friend class PrimeField;
+ Element(const T value): mValue(value) {}
+
+ friend class PrimeFile;
+ T mValue;
+ };
+
+ PrimeField(const T primeCharacteristic): mCharac(primeCharacteristic) {}
+
+ Element zero() const {return Element(0);}
+ Element one() const {return Element(1);}
+
+ bool isZero(const Element a) const {return a == zero();}
+ bool isOne(const Element a) const {return a == one();}
+
+ T charac() const {return mCharac;}
+
+ template<class Integer>
+ Element toElement(Integer&& i) const {
+ typedef typename std::remove_reference<Integer>::type NoRefInteger;
+ static_assert(std::numeric_limits<NoRefInteger>::is_integer, "");
+
+ // We need to take the modulus of i to put it into the range [0;charac()).
+ // That is more tricky to get right than it might seem.
+ //
+ // The sign of a % b is implementation defined in C++ if either of a or b
+ // are negative. We need the positive remainder so the operands have to be
+ // positive. Another reason for this is that we could not allow b to be
+ // converted to a signed integer since it might not be representable that
+ // way.
+ //
+ // If Integer is signed and i is std::numeric_limits<Integer>::min() then
+ // it is undefined behavior to evaluate the expression -i since -i is not
+ // representable, leading to a signed overflow. So we have to cast to
+ // unsigned before doing the minus.
+ typedef typename std::make_unsigned<NoRefInteger>::type Unsigned;
+ if (i < 0) {
+ // Negate i to get a positive number, then negate again to cancel out
+ // the first negation. The first cast to unsigned is to avoid
+ // undefined behavior from -i. The second is there because apparently,
+ // at least on GCC, the unary - re-introduces signed and we need to
+ // be unsigned to avoid sign extension. We need zero extension.
+ const auto unsignedNegative =
+ static_cast<Unsigned>(-static_cast<Unsigned>(i));
+ return negative(Element(unsignedNegative % charac()));
+ } else
+ return Element(static_cast<Unsigned>(i) % charac());
+ }
+
+ T toValue(Element e) const {return e.value;}
+
+ Element sum(const Element a, const Element b) const {
+ const auto s = a.value() + b.value();
+ // The sum overflowed if and only if a.value() > s. In that case
+ // subtraction of charac() will overflow again in the other direction,
+ // leaving us with the correct result.
+ if (a.value() > s || s >= charac()) {
+ MATHICGB_ASSERT(s - charac() < charac());
+ return Element(s - charac());
+ } else
+ return Element(s);
+ }
+
+ Element difference(const Element a, const Element b) const {
+ if (a.value() < b.value()) {
+ MATHICGB_ASSERT(a.value() - b.value() + charac() < charac());
+ return Element(a.value() - b.value() + charac());
+ } else
+ return Element(a.value() - b.value());
+ }
+
+ Element negative(const Element a) const {
+ if (a.value() == 0)
+ return a;
+ else
+ return negativeNonZero(a);
+ }
+
+ Element negativeNonZero(const Element a) const {
+ MATHICGB_ASSERT(!isZero(a));
+ return Element(charac() - a.value());
+ }
+
+ Element product(const Element a, const Element b) const;
+
+ /// Returns the multiplicative inverse a^-1 mod charac(). a must not be zero.
+ Element inverse(const Element a) const;
+
+private:
+ const T mCharac;
+};
+
+namespace PrimeFieldInternal {
+ template<class T>
+ struct ModularProdType {};
+ template<> struct ModularProdType<uint8> {typedef uint16 type;};
+ template<> struct ModularProdType<uint16> {typedef uint32 type;};
+ template<> struct ModularProdType<uint32> {typedef uint64 type;};
+}
+
+template<class T>
+auto PrimeField<T>::product(
+ const Element a,
+ const Element b
+) const -> Element {
+ typedef typename PrimeFieldInternal::ModularProdType<T>::type BigT;
+ BigT bigProd = static_cast<BigT>(a.value()) * b.value();
+ MATHICGB_ASSERT(a.value() == 0 || bigProd / a.value() == b.value());
+ return Element(static_cast<T>(bigProd % charac()));
+}
+
+template<class T>
+auto PrimeField<T>::inverse(const Element elementA) const -> Element {
+ // We do two turns of the extended Euclidian algorithm per
+ // loop. Usually the sign of x changes each time through the loop,
+ // but we avoid that by representing every other x as its negative,
+ // which is the value minusLastX. This way no negative values ever
+ // appear and we do not need any extra bits.
+
+ auto a = elementA.value();
+ MATHICGB_ASSERT(0 < a);
+ MATHICGB_ASSERT(a < charac());
+#ifdef MATHICGB_DEBUG
+ const auto origA = a;
+#endif
+ auto b = charac();
+ auto minusLastX = static_cast<T>(0);
+ auto x = static_cast<T>(1);
+ while (true) {
+ MATHICGB_ASSERT(x <= charac());
+ MATHICGB_ASSERT(minusLastX <= charac());
+
+ // first turn
+ if (a == 1)
+ break;
+ const auto firstQuotient = b / a;
+ b -= firstQuotient * a;
+ minusLastX += firstQuotient * x;
+
+ // second turn
+ if (b == 1) {
+ MATHICGB_ASSERT(minusLastX != 0);
+ MATHICGB_ASSERT(minusLastX < charac());
+ x = charac() - minusLastX;
+ break;
+ }
+ const auto secondQuotient = a / b;
+ a -= secondQuotient * b;
+ x += secondQuotient * minusLastX;
+ }
+ MATHICGB_ASSERT(x >= 1);
+ MATHICGB_ASSERT(x < charac());
+
+ const Element inverseElement(x);
+ MATHICGB_ASSERT(isOne(product(elementA, inverseElement)));
+ return inverseElement;
+}
+
+
+template<class T>
+std::ostream& operator<<(
+ std::ostream& out,
+ typename PrimeField<T>::Element e
+) {
+ out << e.value();
+ return out;
+}
+
+#endif
diff --git a/src/test/PrimeField.cpp b/src/test/PrimeField.cpp
new file mode 100644
index 0000000..9221c9e
--- /dev/null
+++ b/src/test/PrimeField.cpp
@@ -0,0 +1,173 @@
+#include "mathicgb/stdinc.h"
+
+#include "mathicgb/PrimeField.hpp"
+#include <gtest/gtest.h>
+#include <sstream>
+
+namespace {
+ template<class T>
+ std::string toString(T&& t) {
+ std::ostringstream out;
+ out << static_cast<uint64>(t.value());
+ return out.str();
+ }
+}
+
+TEST(PrimeField, Charac) {
+ const PrimeField<unsigned char> pf(11);
+ ASSERT_EQ(pf.charac(), 11);
+}
+
+TEST(PrimeField, OneZero) {
+ const PrimeField<unsigned char> pfChar(11);
+ ASSERT_EQ("0", toString(pfChar.zero()));
+ ASSERT_EQ("1", toString(pfChar.one()));
+ ASSERT_TRUE(pfChar.isOne(pfChar.one()));
+ ASSERT_FALSE(pfChar.isOne(pfChar.zero()));
+ ASSERT_FALSE(pfChar.isZero(pfChar.one()));
+ ASSERT_TRUE(pfChar.isZero(pfChar.zero()));
+
+ const PrimeField<unsigned long> pfLong(11);
+ ASSERT_EQ("0", toString(pfLong.zero()));
+ ASSERT_EQ("1", toString(pfLong.one()));
+ ASSERT_TRUE(pfLong.isOne(pfLong.one()));
+ ASSERT_FALSE(pfLong.isOne(pfLong.zero()));
+ ASSERT_FALSE(pfLong.isZero(pfLong.one()));
+ ASSERT_TRUE(pfLong.isZero(pfLong.zero()));
+}
+
+TEST(PrimeField, toElement) {
+ const auto max32BitUnsignedPrime = 4294967291u;
+ const PrimeField<unsigned int> pf(max32BitUnsignedPrime);
+
+ // Same number of bits (32)
+ ASSERT_EQ("0", toString(pf.toElement(0)));
+ ASSERT_EQ("1", toString(pf.toElement(1)));
+ ASSERT_EQ("4294967290", toString(pf.toElement(-1)));
+
+ ASSERT_EQ("0", toString(pf.toElement(max32BitUnsignedPrime)));
+ ASSERT_EQ("1", toString(pf.toElement(max32BitUnsignedPrime + 1u)));
+ ASSERT_EQ("4294967290", toString(pf.toElement(max32BitUnsignedPrime - 1u)));
+
+ ASSERT_EQ("4",
+ toString(pf.toElement(std::numeric_limits<unsigned int>::max())));
+ ASSERT_EQ("2147483643",
+ toString(pf.toElement(std::numeric_limits<int>::min())));
+
+ // Fewer number of bits (8)
+ ASSERT_EQ("127", toString(pf.toElement(std::numeric_limits<char>::max())));
+ ASSERT_EQ("4294967163",
+ toString(pf.toElement(std::numeric_limits<char>::min())));
+
+ ASSERT_EQ("255",
+ toString(pf.toElement(std::numeric_limits<unsigned char>::max())));
+ ASSERT_EQ("0",
+ toString(pf.toElement(std::numeric_limits<unsigned char>::min())));
+
+ // More bits (64)
+ ASSERT_EQ("24", toString(pf.toElement(std::numeric_limits<uint64>::max())));
+ ASSERT_EQ("2147483657",
+ toString(pf.toElement(std::numeric_limits<int64>::max())));
+ ASSERT_EQ("2147483633",
+ toString(pf.toElement(std::numeric_limits<int64>::min())));
+}
+
+TEST(PrimeField, Sum) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.zero(), pf2.sum(pf2.zero(), pf2.zero()));
+ ASSERT_EQ(pf2.one(), pf2.sum(pf2.one(), pf2.zero()));
+ ASSERT_EQ(pf2.one(), pf2.sum(pf2.zero(), pf2.one()));
+ ASSERT_EQ(pf2.zero(), pf2.sum(pf2.one(), pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.one(), pf251.sum(pf251.zero(), pf251.one()));
+ ASSERT_EQ(pf251.toElement(-3),
+ pf251.sum(pf251.toElement(-1), pf251.toElement(-2)));
+
+ const PrimeField<unsigned char> pf101(101);
+ ASSERT_EQ(pf101.toElement(100),
+ pf101.sum(pf101.toElement(40), pf101.toElement(60)));
+ ASSERT_EQ(pf101.toElement(9),
+ pf101.sum(pf101.toElement(50), pf101.toElement(60)));
+}
+
+TEST(PrimeField, Negative) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.zero(), pf2.negative(pf2.zero()));
+ ASSERT_EQ(pf2.one(), pf2.negative(pf2.one()));
+ ASSERT_EQ(pf2.one(), pf2.negativeNonZero(pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.zero(), pf251.negative(pf251.zero()));
+ ASSERT_EQ(pf251.toElement(100), pf251.negative(pf251.toElement(151)));
+ ASSERT_EQ(pf251.toElement(100), pf251.negativeNonZero(pf251.toElement(151)));
+}
+
+TEST(PrimeField, Difference) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.zero(), pf2.difference(pf2.zero(), pf2.zero()));
+ ASSERT_EQ(pf2.one(), pf2.difference(pf2.one(), pf2.zero()));
+ ASSERT_EQ(pf2.one(), pf2.difference(pf2.zero(), pf2.one()));
+ ASSERT_EQ(pf2.zero(), pf2.difference(pf2.one(), pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.one(), pf251.difference(pf251.one(), pf251.zero()));
+ ASSERT_EQ(pf251.toElement(-3),
+ pf251.difference(pf251.toElement(1), pf251.toElement(4)));
+
+ const PrimeField<unsigned char> pf101(101);
+ ASSERT_EQ(pf101.toElement(20),
+ pf101.difference(pf101.toElement(60), pf101.toElement(40)));
+ ASSERT_EQ(pf101.toElement(-20),
+ pf101.difference(pf101.toElement(40), pf101.toElement(60)));
+}
+
+TEST(PrimeField, Product) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.zero(), pf2.product(pf2.zero(), pf2.zero()));
+ ASSERT_EQ(pf2.zero(), pf2.product(pf2.one(), pf2.zero()));
+ ASSERT_EQ(pf2.zero(), pf2.product(pf2.zero(), pf2.one()));
+ ASSERT_EQ(pf2.one(), pf2.product(pf2.one(), pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.zero(), pf251.product(pf251.one(), pf251.zero()));
+ ASSERT_EQ(pf251.one(), pf251.product(pf251.one(), pf251.one()));
+ ASSERT_EQ(pf251.one(),
+ pf251.product(pf251.toElement(-1), pf251.toElement(-1)));
+ ASSERT_EQ(pf251.one(),
+ pf251.product(pf251.toElement(2), pf251.toElement(126)));
+
+ const PrimeField<unsigned char> pf101(101);
+ ASSERT_EQ(pf101.toElement(20),
+ pf101.product(pf101.toElement(5), pf101.toElement(4)));
+ ASSERT_EQ(pf101.toElement(-20),
+ pf101.product(pf101.toElement(-2), pf101.toElement(10)));
+
+ const PrimeField<uint16> pf16(65521);
+ ASSERT_EQ(pf16.toElement(-20),
+ pf16.product(pf16.toElement(-2), pf16.toElement(10)));
+
+ const PrimeField<uint32> pf32(4294967291u);
+ ASSERT_EQ(pf32.toElement(-20),
+ pf32.product(pf32.toElement(-2), pf32.toElement(10)));
+}
+
+TEST(PrimeField, Inverse) {
+ const PrimeField<unsigned char> pf2(2);
+ ASSERT_EQ(pf2.one(), pf2.inverse(pf2.one()));
+
+ const PrimeField<unsigned char> pf251(251);
+ ASSERT_EQ(pf251.one(), pf2.inverse(pf251.one()));
+ ASSERT_EQ(pf251.toElement(-1), pf251.inverse(pf251.toElement(-1)));
+ ASSERT_EQ(pf251.toElement(235), pf251.inverse(pf251.toElement(47)));
+
+ const PrimeField<uint16> pf16(65521);
+ ASSERT_EQ(pf16.one(), pf16.inverse(pf16.one()));
+ ASSERT_EQ(pf16.toElement(-1), pf16.inverse(pf16.toElement(-1)));
+ ASSERT_EQ(pf16.toElement(43216), pf16.inverse(pf16.toElement(47)));
+
+ const PrimeField<uint32> pf32(4294967291u);
+ ASSERT_EQ(pf32.one(), pf32.inverse(pf32.one()));
+ ASSERT_EQ(pf32.toElement(-1), pf32.inverse(pf32.toElement(-1)));
+ ASSERT_EQ(pf32.toElement(3015615332u), pf32.inverse(pf32.toElement(47)));
+}
--
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