From 0134460a9535802cac9f8953a144bee53926a4e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Radek=20Hu=C5=A1ek?= <PitelVonSacek@gmail.com>
Date: Wed, 9 Dec 2015 18:48:05 +0100
Subject: [PATCH] Add optimized versions of Mapping class

Optimized versions are off by default
---
 Makefile             |  2 +-
 compileTimeOptions.h | 14 ++++++++
 fast-array.h         | 82 ++++++++++++++++++++++++++++++++++++++++----
 group-connectivity.h |  4 +--
 4 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index 302acb9..27bc003 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 default: groupConnectivity.so clean_obj
 
-groupConnectivity.so: groupConnectivity.pyx group-connectivity.h setup.py compileTimeOptions.h rings.h parmap.py
+groupConnectivity.so: groupConnectivity.pyx group-connectivity.h setup.py compileTimeOptions.h rings.h fast-array.h parmap.py
 	python setup.py build_ext
 	cp build/lib*/groupConnectivity.so .
 
diff --git a/compileTimeOptions.h b/compileTimeOptions.h
index 6b47bc0..18f3a51 100644
--- a/compileTimeOptions.h
+++ b/compileTimeOptions.h
@@ -11,5 +11,19 @@
 #pragma message "SAVE_MEMORY off"
 #endif
 
+
+#ifndef OPTIMIZED_MAPPINGS
+#define OPTIMIZED_MAPPINGS 0
+#endif
+#if OPTIMIZED_MAPPINGS
+#pragma message "OPTIMIZED_MAPPINGS ON"
+#else
+#pragma message "OPTIMIZED_MAPPINGS off"
+#endif
+
+#ifndef MAX_EDGES
+#define MAX_EDGES 48
+#endif
+
 #endif
 
diff --git a/fast-array.h b/fast-array.h
index b9e0090..9132595 100644
--- a/fast-array.h
+++ b/fast-array.h
@@ -1,29 +1,99 @@
 #ifndef __FAST_ARRAY_H__
 #define __FAST_ARRAY_H__
 
-template < typename Ring, size_t maxSize = 0 >
+#include "rings.h"
+
+template < typename Ring >
 struct Mapping {
   typedef typename Ring::T T;
   std::vector<T> data;
 
   Mapping() {}
 
-  template < typename X >
-  Mapping(X x) : data(x.data) {}
+  Mapping(const Mapping& x) : data(x.data) {}
 
-  Mapping(size_t size = 0, T val = 0) : data(size, val) {}
+  Mapping(size_t size = 0) : data(size, 0) {}
   inline size_t size() const { return data.size(); }
 
   inline T operator[] (size_t i) const { return data[i]; }
   inline void assign(size_t i, T val) { data[i] = val; }
 
-  Mapping& combine(T beta, const Mapping& b) {
+  inline void combine(T beta, const Mapping& b) {
     size_t _size = size();
     for (size_t i = 0; i < _size; i++)
       data[i] = Ring::plus(data[i], Ring::multiply(beta, b.data[i]));
-    return *this;
   }
 };
 
+
+template < size_t i, size_t shift >
+struct Consts {
+  static const uint64_t clone = (Consts<i-1, shift>::clone << shift) | 1;
+  static const uint64_t mask = (Consts<i-1, shift>::mask << shift) | 3;
+};
+template < size_t shift >
+struct Consts<0, shift> {
+  static const uint64_t clone = 0;
+  static const uint64_t mask = 0;
+};
+
+
+template < bool isZ4 >
+struct FastArray {
+  typedef int T;
+  enum { valuesPerWord = 16 };
+  enum { words = (MAX_EDGES + valuesPerWord - 1) / valuesPerWord };
+  enum { shift = 4 };
+
+  static const uint64_t clone = Consts<valuesPerWord, shift>::clone;
+  static const uint64_t mask = Consts<valuesPerWord, shift>::mask;
+
+  size_t size_;
+  uint64_t data[words];
+
+  FastArray() {}
+
+  FastArray(const FastArray& x) : size_(x.size_) {
+    memcpy(data, x.data, sizeof(data));
+  }
+
+  FastArray(size_t size = 0) : size_(size) {
+    assert(size <= MAX_EDGES);
+    memset(data, 0, sizeof(data));
+  }
+
+  inline size_t size() const { return size_; }
+
+  inline T operator[] (size_t i) const {
+    return (data[i >> 4] >> ((i & 0xF) << 2)) & 3;
+  }
+  inline void assign(size_t i, T val) {
+    size_t w = i >> 4;
+    size_t off = i & 0xF;
+    data[w] &= ~(((uint64_t)3) << (off << 2));
+    data[w] |= (((uint64_t)val) << (off << 2));
+  }
+
+  inline void combine(T beta, const FastArray& b) {
+    for (size_t i = 0; i < words; i++) {
+      if (isZ4)
+        data[i] = (data[i] + ((beta * b.data[i]) & mask)) & mask;
+      else
+        data[i] = data[i] ^ ((clone * beta) & b.data[i]);
+    }
+  }
+};
+
+#if OPTIMIZED_MAPPINGS
+template <> struct Mapping< Ring::Z4<int> > : public FastArray<true> {
+  Mapping(const Mapping& x) : FastArray(x) {}
+  Mapping(size_t s = 0) : FastArray(s) {}
+};
+template <> struct Mapping< Ring::Z2_2<int> > : public FastArray<false> {
+  Mapping(const Mapping& x) : FastArray(x) {}
+  Mapping(size_t s = 0) : FastArray(s) {}
+};
+#endif
+
 #endif
 
diff --git a/group-connectivity.h b/group-connectivity.h
index f127f81..1ac5ae1 100644
--- a/group-connectivity.h
+++ b/group-connectivity.h
@@ -65,7 +65,7 @@ struct Tester : public AbstractTester {
       classEdges.push_back(e - 1);
 
     for (const auto& elemCycle : elementaryCycles) {
-      nonClassEdges.push_back(std::make_pair(elemCycle[0] - 1, Mapping(edges, 0)));
+      nonClassEdges.push_back(std::make_pair(elemCycle[0] - 1, Mapping(edges)));
       Mapping &map = nonClassEdges.back().second;
 
       for (auto edge : elemCycle) {
@@ -121,7 +121,7 @@ struct Tester : public AbstractTester {
 
 
   virtual bool run() {
-    Mapping forb(edges, 0);
+    Mapping forb(edges);
     
     for (size_t i = 0; i < numForb; i++)
 #if SAVE_MEMORY
-- 
GitLab