summaryrefslogtreecommitdiff
path: root/a5/imatrix.h
diff options
context:
space:
mode:
Diffstat (limited to 'a5/imatrix.h')
-rw-r--r--a5/imatrix.h204
1 files changed, 204 insertions, 0 deletions
diff --git a/a5/imatrix.h b/a5/imatrix.h
new file mode 100644
index 0000000..f96cb0c
--- /dev/null
+++ b/a5/imatrix.h
@@ -0,0 +1,204 @@
+// -*- c++ -*-
+#pragma once
+
+#include <utility>
+#include <valarray>
+#include <stdexcept>
+
+class Imatrix
+{
+public:
+ Imatrix() = default;
+
+ explicit Imatrix(std::size_t w, std::size_t h)
+ : data(0, w * h)
+ , w(w)
+ , h(h)
+ {
+ }
+
+ Imatrix(Imatrix&& other)
+ {
+ *this = std::move(other);
+ }
+
+ Imatrix(const Imatrix& other)
+ {
+ *this = other;
+ }
+
+ Imatrix& operator=(Imatrix&& other)
+ {
+ w = other.w;
+ other.w = 0;
+ h = other.h;
+ other.h = 0;
+ data = std::move(other.data);
+ return *this;
+ }
+
+ Imatrix& operator=(const Imatrix& other)
+ {
+ w = other.w;
+ h = other.h;
+ data = other.data;
+ return *this;
+ }
+
+ int& m(std::size_t x, std::size_t y)
+ {
+ if(x >= w || y >= h) throw std::out_of_range("Subscript out of range.");
+ return data[x + y * w];
+ }
+
+ const int& m(std::size_t x, std::size_t y) const
+ {
+ if(x >= w || y >= h) throw std::out_of_range("Subscript out of range.");
+ return data[x + y * w];
+ }
+
+
+ Imatrix operator+(const Imatrix& other) const
+ {
+ if(w != other.w || h != other.h)
+ throw std::invalid_argument("Dimension mismatch");
+ Imatrix m(*this);
+ m.data += other.data;
+ return m;
+ }
+
+ Imatrix operator+(int val) const
+ {
+ Imatrix m(*this);
+ m.data += val;
+ return m;
+ }
+
+ Imatrix operator-(const Imatrix& other) const
+ {
+ if(w != other.w || h != other.h)
+ throw std::invalid_argument("Dimension mismatch");
+ Imatrix m(*this);
+ m.data -= other.data;
+ return m;
+ }
+
+ Imatrix operator-(int val)
+ {
+ Imatrix m(*this);
+ m.data -= val;
+ return m;
+ }
+
+ Imatrix operator%(const Imatrix& other) const
+ {
+ if(w != other.w || h != other.h)
+ throw std::invalid_argument("Dimension mismatch");
+ Imatrix m(*this);
+ m.data %= other.data;
+ return m;
+ }
+
+ Imatrix operator%(int val) const
+ {
+ Imatrix m(*this);
+ m.data %= val;
+ return m;
+ }
+
+ Imatrix operator*(const Imatrix& other) const
+ {
+ if(w != other.h || h != other.w)
+ throw std::invalid_argument("Dimension mismatch");
+
+ Imatrix out(w, other.h);
+ for(std::size_t i = 0; i < w; ++i)
+ {
+ for(std::size_t j = 0; j < other.h; ++j)
+ {
+ out.m(i,j) = 0;
+ for(std::size_t k = 0; k < other.w; ++k)
+ {
+ out.m(i,j) += m(i, j) * other.m(k, j);
+ }
+ }
+ }
+
+ return out;
+ }
+
+ Imatrix operator*(int val) const
+ {
+ Imatrix m(*this);
+ m.data *= val;
+ return m;
+ }
+
+ Imatrix operator/(const Imatrix& other) const
+ {
+ if(w != other.h || h != other.w)
+ throw std::invalid_argument("Dimension mismatch");
+
+ Imatrix out(w, other.h);
+ for(std::size_t i = 0; i < w; ++i)
+ {
+ for(std::size_t j = 0; j < other.h; ++j)
+ {
+ out.m(i,j) = 0;
+ for(std::size_t k = 0; k < other.w; ++k)
+ {
+ out.m(i,j) += m(i, j) / other.m(k, j);
+ }
+ }
+ }
+
+ return out;
+ }
+
+ Imatrix operator/(int val) const
+ {
+ Imatrix m(*this);
+ m.data /= val;
+ return m;
+ }
+
+ struct pos_t
+ {
+ std::size_t x;
+ std::size_t y;
+ };
+
+ void Move(pos_t from, pos_t to)
+ {
+ m(to.x, to.x) = m(from.x, from.x);
+ m(from.x, from.y) = 0;
+ }
+
+ std::vector<int> Row(std::size_t n) const
+ {
+ if(n >= h) throw std::out_of_range("Subscript out of range.");
+ std::vector<int> out;
+ for(std::size_t x = 0; x < w; ++x)
+ {
+ out.push_back(m(x, n));
+ }
+ return out;
+ }
+
+ std::vector<int> Column(std::size_t n) const
+ {
+ if(n >= w) throw std::out_of_range("Subscript out of range.");
+ std::vector<int> out;
+ for(std::size_t y = 0; y < h; ++y)
+ {
+ out.push_back(m(n, y));
+ }
+ return out;
+ }
+
+private:
+ // Invariant; at all times data contains w * h initialized data members
+ std::valarray<int> data; // default initialized to empty
+ std::size_t w{}; // default initialized to 0
+ std::size_t h{}; // default initialized to 0
+};