[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