#pragma once #include "mod.hpp" #include "matrix.hpp" #include "spin.hpp" #include "vector.hpp" typedef double Radius; typedef signed IsingSpin; template class Dimer { public: double radius; Vector relativePosition; }; template class Affine { protected: virtual Vector actV(const Vector& x) const { return t + r * x; } Affine actA(const Affine& x) const { return Affine(act(x.t), r * x.r); } public: Vector t; Matrix r; Affine() { for (unsigned i = 0; i < D; i++) { t(i) = 0; r(i, i) = 1; for (unsigned j = 1; j < D; j++) { r(i, (i + j) % D) = 0; } } } Affine(const Vector& t0, const Matrix& r0) : t(t0), r(r0) {} Affine inverse() const { return Affine(-r.transpose() * t, r.transpose()); } Vector act(const Vector& x) const { return actV(x); } Radius act(Radius r) const { return r; } IsingSpin act(IsingSpin s) const { return s; } Dimer act(const Dimer& d) const { return {.radius = d.radius, .relativePosition = r * d.relativePosition}; } template Spin act(const Spin& s) const { return {.x = act(s.x), .s = act(s.s)}; } }; template class Euclidean : public Affine { public: Euclidean(T L = 0) : Affine() {} Euclidean(const Affine& a) : Affine(a) {} Euclidean(Vector t0, Matrix r0) : Affine(t0, r0) {} Euclidean act(const Euclidean& t) const { return Euclidean(Affine::actA(t)); }; Euclidean inverse() const { return Euclidean(Affine::inverse()); } using Affine::act; }; template class TorusGroup : public Affine{ private: T L; protected: Vector actV(const Vector& s) const override { Vector s_new = Affine::actV(s); for (unsigned i = 0; i < D; i++) { s_new(i) = mod(s_new(i), L); } return s_new; } public: TorusGroup(T L) : Affine(), L(L) {} TorusGroup(T L, const Affine& t) : Affine(t), L(L) {} TorusGroup(T L, Vector t0, Matrix r0) : Affine(t0, r0), L(L) {} TorusGroup act(const TorusGroup& t) const { return TorusGroup(L, Affine::actA(t)); } TorusGroup inverse() const { return TorusGroup(L, Affine::inverse()); } using Affine::act; };