From dfa63996ed24b8f6ad02e63bd40c659cf9f3765e Mon Sep 17 00:00:00 2001 From: SR71 Date: Thu, 2 Jul 2015 19:06:47 +0200 Subject: [PATCH] common_type used in operators --- Makefile | 16 + aga2.hpp | 730 +++++++++++++++++++++++++++++--------------- safe_cast.h | 19 ++ sc.py | 268 ++++++++++++---- tests/test_aga2.cpp | 112 ++++++- 5 files changed, 821 insertions(+), 324 deletions(-) create mode 100644 Makefile create mode 100644 safe_cast.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..caca7dc --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +# $@ -- The file name of the target of the rule. +# $* -- The stem with which an implicit rule matches +# $< -- The name of the first prerequisite. +# $^ -- The names of all the prerequisites +# $(VARS:%.cpp=%.o) -- pattern replace + +CC:=g++-4.9 + +OPTS:=-std=c++14 -fmax-errors=5 -g -O0 -Wsign-compare -Wreturn-type -Wparentheses -Wpedantic -Wconversion-null + + +test_aga2: tests/test_aga2.cpp aga2.hpp + ${CC} -o test_aga2 tests/test_aga2.cpp ${OPTS} + +clean: + rm -rf b/* bin/* diff --git a/aga2.hpp b/aga2.hpp index 0b962b1..1dcf59e 100644 --- a/aga2.hpp +++ b/aga2.hpp @@ -5,6 +5,8 @@ #include #include +#include "safe_cast.h" + namespace aga2 { using uint = unsigned int; @@ -26,15 +28,26 @@ class Mv0 { using difference_type = typename Array::difference_type; using size_type = typename Array::size_type; + using scalar_type = R; + Array arr; + // cast constructor from scalar type Mv0(R const& a00) { arr[0] = a00; } + // null constructor Mv0() { } + // explicit cast constructor + template + explicit + Mv0(Mv0 const& other) { + arr[0] = R(other[0]); + } + operator R() const { return arr[0]; } @@ -44,11 +57,6 @@ class Mv0 { return arr[d]; } - template - Mv0 cast() const { - return Mv0(F(arr[0])); - } - const R& operator[](uint const& d) const { assert(d < size()); return arr[d]; @@ -58,6 +66,15 @@ class Mv0 { return 1; } + // operator= + template ::type* = nullptr> + void operator=(Mv0 const& x) { + + (*this)[0] = x[0]; + } + + R norm2() const { auto& x = *this; @@ -65,6 +82,7 @@ class Mv0 { } + Mv0 rev() const { auto& x = *this; @@ -72,6 +90,7 @@ class Mv0 { } + Mv0 inv() const { auto& x = *this; @@ -79,6 +98,7 @@ class Mv0 { } + Mv0 operator-() const { auto& x = *this; @@ -122,7 +142,6 @@ class Mv0 { } }; -template class Mv0; template class Mv1 { @@ -139,26 +158,33 @@ class Mv1 { using difference_type = typename Array::difference_type; using size_type = typename Array::size_type; + using scalar_type = R; + Array arr; + // cast constructor from scalar type Mv1(R const& a10, R const& a11) { arr[0] = a10; arr[1] = a11; } + // null constructor Mv1() { } + // explicit cast constructor + template + explicit + Mv1(Mv1 const& other) { + arr[0] = R(other[0]); + arr[1] = R(other[1]); + } + R& operator[](uint const& d) { assert(d < size()); return arr[d]; } - template - Mv1 cast() const { - return Mv1(F(arr[0]), F(arr[1])); - } - const R& operator[](uint const& d) const { assert(d < size()); return arr[d]; @@ -168,6 +194,15 @@ class Mv1 { return 2; } + // operator= + template ::type* = nullptr> + void operator=(Mv1 const& x) { + + (*this)[0] = x[0]; + } + + R norm2() const { auto& x = *this; @@ -175,6 +210,7 @@ class Mv1 { } + Mv1 rev() const { auto& x = *this; @@ -182,6 +218,7 @@ class Mv1 { } + Mv1 inv() const { auto& x = *this; @@ -189,6 +226,7 @@ class Mv1 { } + Mv1 operator-() const { auto& x = *this; @@ -232,7 +270,6 @@ class Mv1 { } }; -template class Mv1; template class Mv2 { @@ -249,15 +286,26 @@ class Mv2 { using difference_type = typename Array::difference_type; using size_type = typename Array::size_type; + using scalar_type = R; + Array arr; - explicit Mv2(R const& a20) { + // cast constructor from scalar type + explicit Mv2(R const& a20) { arr[0] = a20; } + // null constructor Mv2() { } + // explicit cast constructor + template + explicit + Mv2(Mv2 const& other) { + arr[0] = R(other[0]); + } + explicit operator R() const { return arr[0]; } @@ -267,11 +315,6 @@ class Mv2 { return arr[d]; } - template - Mv2 cast() const { - return Mv2(F(arr[0])); - } - const R& operator[](uint const& d) const { assert(d < size()); return arr[d]; @@ -281,6 +324,15 @@ class Mv2 { return 1; } + // operator= + template ::type* = nullptr> + void operator=(Mv2 const& x) { + + (*this)[0] = x[0]; + } + + R norm2() const { auto& x = *this; @@ -288,6 +340,7 @@ class Mv2 { } + Mv2 rev() const { auto& x = *this; @@ -295,6 +348,7 @@ class Mv2 { } + Mv2 inv() const { auto& x = *this; @@ -302,6 +356,7 @@ class Mv2 { } + Mv2 operator-() const { auto& x = *this; @@ -345,7 +400,6 @@ class Mv2 { } }; -template class Mv2; template class Mv02 { @@ -362,26 +416,33 @@ class Mv02 { using difference_type = typename Array::difference_type; using size_type = typename Array::size_type; + using scalar_type = R; + Array arr; + // cast constructor from scalar type Mv02(R const& a00, R const& a20) { arr[0] = a00; arr[1] = a20; } + // null constructor Mv02() { } + // explicit cast constructor + template + explicit + Mv02(Mv02 const& other) { + arr[0] = R(other[0]); + arr[1] = R(other[1]); + } + R& operator[](uint const& d) { assert(d < size()); return arr[d]; } - template - Mv02 cast() const { - return Mv02(F(arr[0]), F(arr[1])); - } - const R& operator[](uint const& d) const { assert(d < size()); return arr[d]; @@ -391,6 +452,16 @@ class Mv02 { return 2; } + // operator= + template ::type* = nullptr> + void operator=(Mv02 const& x) { + + (*this)[0] = x[0]; + (*this)[1] = x[1]; + } + + R norm2() const { auto& x = *this; @@ -398,6 +469,7 @@ class Mv02 { } + Mv02 rev() const { auto& x = *this; @@ -405,6 +477,7 @@ class Mv02 { } + Mv02 inv() const { auto& x = *this; @@ -412,6 +485,7 @@ class Mv02 { } + Mv02 operator-() const { auto& x = *this; @@ -455,7 +529,6 @@ class Mv02 { } }; -template class Mv02; // eq template @@ -508,244 +581,359 @@ bool operator!=(Mv02 const& x, Mv02 const& y) { } // mul -template -Mv0 operator*(Mv0 const& x, Mv0 const& y) { - assert(&x != &y); +template::type> + +Mv0 operator*(Mv0 const& x, Mv0 const& y) { - return Mv0((x[0] * y[0])); + return Mv0((x[0] * y[0])); } -template -Mv1 operator*(Mv0 const& x, Mv1 const& y) { +template::type> + +Mv1 operator*(Mv0 const& x, Mv1 const& y) { - return Mv1((x[0] * y[0]), (x[0] * y[1])); + return Mv1((x[0] * y[0]), (x[0] * y[1])); } -template -Mv2 operator*(Mv0 const& x, Mv2 const& y) { +template::type> + +Mv2 operator*(Mv0 const& x, Mv2 const& y) { - return Mv2((x[0] * y[0])); + return Mv2((x[0] * y[0])); } -template -Mv02 operator*(Mv0 const& x, Mv02 const& y) { +template::type> + +Mv02 operator*(Mv0 const& x, Mv02 const& y) { - return Mv02((x[0] * y[0]), (x[0] * y[1])); + return Mv02((x[0] * y[0]), (x[0] * y[1])); } -template -Mv1 operator*(Mv1 const& x, Mv0 const& y) { +template::type> - return Mv1((x[0] * y[0]), (x[1] * y[0])); +Mv1 operator*(Mv1 const& x, Mv0 const& y) { + + return Mv1((x[0] * y[0]), (x[1] * y[0])); } -template -Mv02 operator*(Mv1 const& x, Mv1 const& y) { - assert(&x != &y); +template::type> + +Mv02 operator*(Mv1 const& x, Mv1 const& y) { - return Mv02(((x[0] * y[0]) + (x[1] * y[1])), ((-1 * x[1] * y[0]) + (x[0] * y[1]))); + return Mv02(((x[0] * y[0]) + (x[1] * y[1])), ((-1 * x[1] * y[0]) + (x[0] * y[1]))); } -template -Mv1 operator*(Mv1 const& x, Mv2 const& y) { +template::type> + +Mv1 operator*(Mv1 const& x, Mv2 const& y) { - return Mv1((-1 * x[1] * y[0]), (x[0] * y[0])); + return Mv1((-1 * x[1] * y[0]), (x[0] * y[0])); } -template -Mv1 operator*(Mv1 const& x, Mv02 const& y) { +template::type> - return Mv1(((x[0] * y[0]) + (-1 * x[1] * y[1])), ((x[0] * y[1]) + (x[1] * y[0]))); +Mv1 operator*(Mv1 const& x, Mv02 const& y) { + + return Mv1(((x[0] * y[0]) + (-1 * x[1] * y[1])), ((x[0] * y[1]) + (x[1] * y[0]))); } -template -Mv2 operator*(Mv2 const& x, Mv0 const& y) { +template::type> - return Mv2((x[0] * y[0])); +Mv2 operator*(Mv2 const& x, Mv0 const& y) { + + return Mv2((x[0] * y[0])); } -template -Mv1 operator*(Mv2 const& x, Mv1 const& y) { +template::type> - return Mv1((x[0] * y[1]), (-1 * x[0] * y[0])); +Mv1 operator*(Mv2 const& x, Mv1 const& y) { + + return Mv1((x[0] * y[1]), (-1 * x[0] * y[0])); } -template -Mv0 operator*(Mv2 const& x, Mv2 const& y) { - assert(&x != &y); +template::type> + +Mv0 operator*(Mv2 const& x, Mv2 const& y) { - return Mv0((-1 * x[0] * y[0])); + return Mv0((-1 * x[0] * y[0])); } -template -Mv02 operator*(Mv2 const& x, Mv02 const& y) { +template::type> + +Mv02 operator*(Mv2 const& x, Mv02 const& y) { - return Mv02((-1 * x[0] * y[1]), (x[0] * y[0])); + return Mv02((-1 * x[0] * y[1]), (x[0] * y[0])); } -template -Mv02 operator*(Mv02 const& x, Mv0 const& y) { +template::type> - return Mv02((x[0] * y[0]), (x[1] * y[0])); +Mv02 operator*(Mv02 const& x, Mv0 const& y) { + + return Mv02((x[0] * y[0]), (x[1] * y[0])); } -template -Mv1 operator*(Mv02 const& x, Mv1 const& y) { +template::type> + +Mv1 operator*(Mv02 const& x, Mv1 const& y) { - return Mv1(((x[0] * y[0]) + (x[1] * y[1])), ((-1 * x[1] * y[0]) + (x[0] * y[1]))); + return Mv1(((x[0] * y[0]) + (x[1] * y[1])), ((-1 * x[1] * y[0]) + (x[0] * y[1]))); } -template -Mv02 operator*(Mv02 const& x, Mv2 const& y) { +template::type> + +Mv02 operator*(Mv02 const& x, Mv2 const& y) { - return Mv02((-1 * x[1] * y[0]), (x[0] * y[0])); + return Mv02((-1 * x[1] * y[0]), (x[0] * y[0])); } -template -Mv02 operator*(Mv02 const& x, Mv02 const& y) { - assert(&x != &y); +template::type> + +Mv02 operator*(Mv02 const& x, Mv02 const& y) { - return Mv02(((x[0] * y[0]) + (-1 * x[1] * y[1])), ((x[0] * y[1]) + (x[1] * y[0]))); + return Mv02(((x[0] * y[0]) + (-1 * x[1] * y[1])), ((x[0] * y[1]) + (x[1] * y[0]))); +} + +// mul when one arg is Scalar +template::type> + +Mv1 operator*(A const& x, Mv1 const& y) { + + return Mv1((x * y[0]), (x * y[1])); +} + +template::type> + +Mv2 operator*(A const& x, Mv2 const& y) { + + return Mv2((x * y[0])); +} + +template::type> + +Mv02 operator*(A const& x, Mv02 const& y) { + + return Mv02((x * y), (x * y[1])); +} + +template::type> + +Mv1 operator*(Mv1 const& x, B const& y) { + + return Mv1((x[0] * y), (x[1] * y)); +} + +template::type> + +Mv2 operator*(Mv2 const& x, B const& y) { + + return Mv2((x[0] * y)); +} + +template::type> + +Mv02 operator*(Mv02 const& x, B const& y) { + + return Mv02((x * y), (x[1] * y)); } // inner product -template -Mv0 operator|(Mv1 const& x, Mv1 const& y) { - assert(&x != &y); +template::type> - return Mv0(((x[0] * y[0]) + (x[1] * y[1]))); +Mv0 operator|(Mv1 const& x, Mv1 const& y) { + + return Mv0(((x[0] * y[0]) + (x[1] * y[1]))); } -template -Mv1 operator|(Mv1 const& x, Mv2 const& y) { +template::type> + +Mv1 operator|(Mv1 const& x, Mv2 const& y) { - return Mv1((-1 * x[1] * y[0]), (x[0] * y[0])); + return Mv1((-1 * x[1] * y[0]), (x[0] * y[0])); } -template -Mv1 operator|(Mv1 const& x, Mv02 const& y) { +template::type> + +Mv1 operator|(Mv1 const& x, Mv02 const& y) { - return Mv1((-1 * x[1] * y[1]), (x[0] * y[1])); + return Mv1((-1 * x[1] * y[1]), (x[0] * y[1])); } -template -Mv1 operator|(Mv2 const& x, Mv1 const& y) { +template::type> - return Mv1((x[0] * y[1]), (-1 * x[0] * y[0])); +Mv1 operator|(Mv2 const& x, Mv1 const& y) { + + return Mv1((x[0] * y[1]), (-1 * x[0] * y[0])); } -template -Mv0 operator|(Mv2 const& x, Mv2 const& y) { - assert(&x != &y); +template::type> + +Mv0 operator|(Mv2 const& x, Mv2 const& y) { - return Mv0((-1 * x[0] * y[0])); + return Mv0((-1 * x[0] * y[0])); } -template -Mv0 operator|(Mv2 const& x, Mv02 const& y) { +template::type> + +Mv0 operator|(Mv2 const& x, Mv02 const& y) { - return Mv0((-1 * x[0] * y[1])); + return Mv0((-1 * x[0] * y[1])); } -template -Mv1 operator|(Mv02 const& x, Mv1 const& y) { +template::type> + +Mv1 operator|(Mv02 const& x, Mv1 const& y) { - return Mv1((x[1] * y[1]), (-1 * x[1] * y[0])); + return Mv1((x[1] * y[1]), (-1 * x[1] * y[0])); } -template -Mv0 operator|(Mv02 const& x, Mv2 const& y) { +template::type> + +Mv0 operator|(Mv02 const& x, Mv2 const& y) { - return Mv0((-1 * x[1] * y[0])); + return Mv0((-1 * x[1] * y[0])); } -template -Mv0 operator|(Mv02 const& x, Mv02 const& y) { - assert(&x != &y); +template::type> - return Mv0((-1 * x[1] * y[1])); +Mv0 operator|(Mv02 const& x, Mv02 const& y) { + + return Mv0((-1 * x[1] * y[1])); } // outer product -template -Mv0 operator^(Mv0 const& x, Mv0 const& y) { - assert(&x != &y); +template::type> + +Mv0 operator^(Mv0 const& x, Mv0 const& y) { - return Mv0((x[0] * y[0])); + return Mv0((x[0] * y[0])); } -template -Mv1 operator^(Mv0 const& x, Mv1 const& y) { +template::type> + +Mv1 operator^(Mv0 const& x, Mv1 const& y) { - return Mv1((x[0] * y[0]), (x[0] * y[1])); + return Mv1((x[0] * y[0]), (x[0] * y[1])); } -template -Mv2 operator^(Mv0 const& x, Mv2 const& y) { +template::type> - return Mv2((x[0] * y[0])); +Mv2 operator^(Mv0 const& x, Mv2 const& y) { + + return Mv2((x[0] * y[0])); } -template -Mv02 operator^(Mv0 const& x, Mv02 const& y) { +template::type> - return Mv02((x[0] * y[0]), (x[0] * y[1])); +Mv02 operator^(Mv0 const& x, Mv02 const& y) { + + return Mv02((x[0] * y[0]), (x[0] * y[1])); } -template -Mv1 operator^(Mv1 const& x, Mv0 const& y) { +template::type> - return Mv1((x[0] * y[0]), (x[1] * y[0])); +Mv1 operator^(Mv1 const& x, Mv0 const& y) { + + return Mv1((x[0] * y[0]), (x[1] * y[0])); } -template -Mv2 operator^(Mv1 const& x, Mv1 const& y) { - assert(&x != &y); +template::type> + +Mv2 operator^(Mv1 const& x, Mv1 const& y) { - return Mv2(((-1 * x[1] * y[0]) + (x[0] * y[1]))); + return Mv2(((-1 * x[1] * y[0]) + (x[0] * y[1]))); } -template -Mv1 operator^(Mv1 const& x, Mv02 const& y) { +template::type> + +Mv1 operator^(Mv1 const& x, Mv02 const& y) { - return Mv1((x[0] * y[0]), (x[1] * y[0])); + return Mv1((x[0] * y[0]), (x[1] * y[0])); } -template -Mv2 operator^(Mv2 const& x, Mv0 const& y) { +template::type> - return Mv2((x[0] * y[0])); +Mv2 operator^(Mv2 const& x, Mv0 const& y) { + + return Mv2((x[0] * y[0])); } -template -Mv2 operator^(Mv2 const& x, Mv02 const& y) { +template::type> + +Mv2 operator^(Mv2 const& x, Mv02 const& y) { - return Mv2((x[0] * y[0])); + return Mv2((x[0] * y[0])); } -template -Mv02 operator^(Mv02 const& x, Mv0 const& y) { +template::type> + +Mv02 operator^(Mv02 const& x, Mv0 const& y) { - return Mv02((x[0] * y[0]), (x[1] * y[0])); + return Mv02((x[0] * y[0]), (x[1] * y[0])); } -template -Mv1 operator^(Mv02 const& x, Mv1 const& y) { +template::type> - return Mv1((x[0] * y[0]), (x[0] * y[1])); +Mv1 operator^(Mv02 const& x, Mv1 const& y) { + + return Mv1((x[0] * y[0]), (x[0] * y[1])); } -template -Mv2 operator^(Mv02 const& x, Mv2 const& y) { +template::type> + +Mv2 operator^(Mv02 const& x, Mv2 const& y) { - return Mv2((x[0] * y[0])); + return Mv2((x[0] * y[0])); } -template -Mv02 operator^(Mv02 const& x, Mv02 const& y) { - assert(&x != &y); +template::type> + +Mv02 operator^(Mv02 const& x, Mv02 const& y) { - return Mv02((x[0] * y[0]), ((x[0] * y[1]) + (x[1] * y[0]))); + return Mv02((x[0] * y[0]), ((x[0] * y[1]) + (x[1] * y[0]))); } // inn2 @@ -768,212 +956,258 @@ Mv0 inn2(Mv02 const& x) { } // add -template -Mv0 operator+(Mv0 const& x, Mv0 const& y) { - assert(&x != &y); +template::type> - return Mv0((x[0] + y[0])); +Mv0 operator+(Mv0 const& x, Mv0 const& y) { + + return Mv0((x[0] + y[0])); } -template -void operator+=(Mv0 & x, Mv0 const& y) { +template ::type* = nullptr> +void operator+=(Mv0 & x, Mv0 const& y) { x = x + y; } -template -Mv02 operator+(Mv0 const& x, Mv2 const& y) { +template::type> - return Mv02(x[0], y[0]); +Mv02 operator+(Mv0 const& x, Mv2 const& y) { + + return Mv02(x[0], y[0]); } -template -Mv02 operator+(Mv0 const& x, Mv02 const& y) { +template::type> - return Mv02((x[0] + y[0]), y[1]); +Mv02 operator+(Mv0 const& x, Mv02 const& y) { + + return Mv02((x[0] + y[0]), y[1]); } -template -Mv1 operator+(Mv1 const& x, Mv1 const& y) { - assert(&x != &y); +template::type> - return Mv1((x[0] + y[0]), (x[1] + y[1])); +Mv1 operator+(Mv1 const& x, Mv1 const& y) { + + return Mv1((x[0] + y[0]), (x[1] + y[1])); } -template -void operator+=(Mv1 & x, Mv1 const& y) { +template ::type* = nullptr> +void operator+=(Mv1 & x, Mv1 const& y) { x = x + y; } -template -Mv02 operator+(Mv2 const& x, Mv0 const& y) { +template::type> - return Mv02(y[0], x[0]); +Mv02 operator+(Mv2 const& x, Mv0 const& y) { + + return Mv02(y[0], x[0]); } -template -Mv2 operator+(Mv2 const& x, Mv2 const& y) { - assert(&x != &y); +template::type> + +Mv2 operator+(Mv2 const& x, Mv2 const& y) { - return Mv2((x[0] + y[0])); + return Mv2((x[0] + y[0])); } -template -void operator+=(Mv2 & x, Mv2 const& y) { +template ::type* = nullptr> +void operator+=(Mv2 & x, Mv2 const& y) { x = x + y; } -template -Mv02 operator+(Mv2 const& x, Mv02 const& y) { +template::type> + +Mv02 operator+(Mv2 const& x, Mv02 const& y) { - return Mv02(y[0], (x[0] + y[1])); + return Mv02(y[0], (x[0] + y[1])); } -template -Mv02 operator+(Mv02 const& x, Mv0 const& y) { +template::type> + +Mv02 operator+(Mv02 const& x, Mv0 const& y) { - return Mv02((x[0] + y[0]), x[1]); + return Mv02((x[0] + y[0]), x[1]); } -template -void operator+=(Mv02 & x, Mv0 const& y) { +template ::type* = nullptr> +void operator+=(Mv02 & x, Mv0 const& y) { x = x + y; } -template -Mv02 operator+(Mv02 const& x, Mv2 const& y) { +template::type> + +Mv02 operator+(Mv02 const& x, Mv2 const& y) { - return Mv02(x[0], (x[1] + y[0])); + return Mv02(x[0], (x[1] + y[0])); } -template -void operator+=(Mv02 & x, Mv2 const& y) { +template ::type* = nullptr> +void operator+=(Mv02 & x, Mv2 const& y) { x = x + y; } -template -Mv02 operator+(Mv02 const& x, Mv02 const& y) { - assert(&x != &y); +template::type> + +Mv02 operator+(Mv02 const& x, Mv02 const& y) { - return Mv02((x[0] + y[0]), (x[1] + y[1])); + return Mv02((x[0] + y[0]), (x[1] + y[1])); } -template -void operator+=(Mv02 & x, Mv02 const& y) { +template ::type* = nullptr> +void operator+=(Mv02 & x, Mv02 const& y) { x = x + y; } // sub -template -Mv0 operator-(Mv0 const& x, Mv0 const& y) { - assert(&x != &y); +template::type> + +Mv0 operator-(Mv0 const& x, Mv0 const& y) { - return Mv0(((-y[0]) + x[0])); + return Mv0(((-y[0]) + x[0])); } -template -void operator-=(Mv0 & x, Mv0 const& y) { +template ::type* = nullptr> +void operator-=(Mv0 & x, Mv0 const& y) { x = x - y; } -template -Mv02 operator-(Mv0 const& x, Mv2 const& y) { +template::type> + +Mv02 operator-(Mv0 const& x, Mv2 const& y) { - return Mv02(x[0], (-y[0])); + return Mv02(x[0], (-y[0])); } -template -Mv02 operator-(Mv0 const& x, Mv02 const& y) { +template::type> + +Mv02 operator-(Mv0 const& x, Mv02 const& y) { - return Mv02(((-y[0]) + x[0]), (-y[1])); + return Mv02(((-y[0]) + x[0]), (-y[1])); } -template -Mv1 operator-(Mv1 const& x, Mv1 const& y) { - assert(&x != &y); +template::type> + +Mv1 operator-(Mv1 const& x, Mv1 const& y) { - return Mv1(((-y[0]) + x[0]), (x[1] + (-y[1]))); + return Mv1(((-y[0]) + x[0]), (x[1] + (-y[1]))); } -template -void operator-=(Mv1 & x, Mv1 const& y) { +template ::type* = nullptr> +void operator-=(Mv1 & x, Mv1 const& y) { x = x - y; } -template -Mv02 operator-(Mv2 const& x, Mv0 const& y) { +template::type> + +Mv02 operator-(Mv2 const& x, Mv0 const& y) { - return Mv02((-y[0]), x[0]); + return Mv02((-y[0]), x[0]); } -template -Mv2 operator-(Mv2 const& x, Mv2 const& y) { - assert(&x != &y); +template::type> - return Mv2(((-y[0]) + x[0])); +Mv2 operator-(Mv2 const& x, Mv2 const& y) { + + return Mv2(((-y[0]) + x[0])); } -template -void operator-=(Mv2 & x, Mv2 const& y) { +template ::type* = nullptr> +void operator-=(Mv2 & x, Mv2 const& y) { x = x - y; } -template -Mv02 operator-(Mv2 const& x, Mv02 const& y) { +template::type> - return Mv02((-y[0]), (x[0] + (-y[1]))); +Mv02 operator-(Mv2 const& x, Mv02 const& y) { + + return Mv02((-y[0]), (x[0] + (-y[1]))); } -template -Mv02 operator-(Mv02 const& x, Mv0 const& y) { +template::type> + +Mv02 operator-(Mv02 const& x, Mv0 const& y) { - return Mv02(((-y[0]) + x[0]), x[1]); + return Mv02(((-y[0]) + x[0]), x[1]); } -template -void operator-=(Mv02 & x, Mv0 const& y) { +template ::type* = nullptr> +void operator-=(Mv02 & x, Mv0 const& y) { x = x - y; } -template -Mv02 operator-(Mv02 const& x, Mv2 const& y) { +template::type> + +Mv02 operator-(Mv02 const& x, Mv2 const& y) { - return Mv02(x[0], ((-y[0]) + x[1])); + return Mv02(x[0], ((-y[0]) + x[1])); } -template -void operator-=(Mv02 & x, Mv2 const& y) { +template ::type* = nullptr> +void operator-=(Mv02 & x, Mv2 const& y) { x = x - y; } -template -Mv02 operator-(Mv02 const& x, Mv02 const& y) { - assert(&x != &y); +template::type> + +Mv02 operator-(Mv02 const& x, Mv02 const& y) { - return Mv02(((-y[0]) + x[0]), (x[1] + (-y[1]))); + return Mv02(((-y[0]) + x[0]), (x[1] + (-y[1]))); } -template -void operator-=(Mv02 & x, Mv02 const& y) { +template ::type* = nullptr> +void operator-=(Mv02 & x, Mv02 const& y) { x = x - y; } // rotated -template -Mv1 rotated(Mv1 const& x, Mv02 const& y) { +template::type> + +Mv1 rotated(Mv1 const& x, Mv02 const& y) { - return Mv1(((2 * x[1] * y[0] * y[1]) + (x[0] * pow(y[0], 2)) + (-1 * x[0] * pow(y[1], 2))), ((-2 * x[0] * y[0] * y[1]) + (x[1] * pow(y[0], 2)) + (-1 * x[1] * pow(y[1], 2)))); + return Mv1(((2 * x[1] * y[0] * y[1]) + (x[0] * pow(y[0], 2)) + (-1 * x[0] * pow(y[1], 2))), ((-2 * x[0] * y[0] * y[1]) + (x[1] * pow(y[0], 2)) + (-1 * x[1] * pow(y[1], 2)))); } // ostream @@ -1002,10 +1236,10 @@ std::ostream& operator<<(std::ostream& t, const Mv02& x) { } // const -auto const _1 = Mv0<>(1); -auto const e0 = Mv1<>(1,0); -auto const e1 = Mv1<>(0,1); -auto const I = Mv2<>(1); +auto const _1 = Mv0(1); +auto const e0 = Mv1(1,0); +auto const e1 = Mv1(0,1); +auto const I = Mv2(1); // misc /* diff --git a/safe_cast.h b/safe_cast.h new file mode 100644 index 0000000..3c7af51 --- /dev/null +++ b/safe_cast.h @@ -0,0 +1,19 @@ +#ifndef SAFE_CAST238573_H +#define SAFE_CAST238573_H + +#include + + +template +using is_safe_cast = std::is_same< + typename std::common_type::type, + To +>; + +template +using enable_if_safe_cast = std::enable_if< + is_safe_cast::value +>; + + +#endif diff --git a/sc.py b/sc.py index 21dcbef..e356ef3 100644 --- a/sc.py +++ b/sc.py @@ -7,6 +7,14 @@ from string import join import sys +""" +from sympy.galgebra.ga import * +from sympy import * + +x0,x1,x2 = symbols('x0 x1 x2') +e0,e1,e2,grad = MV.setup('e0 e1 e2',metric='[1,1,1]',coords=(x0,x1,x2)) +""" + if len(sys.argv) != 2: print "Usage: python sc.py 2 > aga2.hpp && astyle aga2.hpp" sys.exit(0) @@ -16,13 +24,13 @@ n = int(sys.argv[1]) N = 2**n -def get_metric(n): +def get_metric(ms): """ Return metric passable to setup proc ex. n=2 -> "[1,1]" n=3 -> "[1,1,1]" """ - return '['+','.join(['1']*n)+']' + return '['+','.join(str(m) for m in ms)+']' def get_basis(n): @@ -56,7 +64,9 @@ def get_flat_bases(): # get basis multivectors -e = MV.setup(get_basis(n), get_metric(n)) +ms = n*['1'] +e = MV.setup(get_basis(n), get_metric(ms)) + def get_bases(): @@ -135,6 +145,8 @@ def prelude(): '#include ', '#include ', '', + '#include "safe_cast.h"', + '', 'namespace aga{n} {{'.format(n = n), '', 'using uint = unsigned int;', @@ -180,7 +192,7 @@ def csize(grades): -def produce_obj(name, grades): +def produce_obj(name, grades, wrap_scalar=True): """ Return sympy mv object with symbolic coeffs name grades @@ -189,12 +201,17 @@ def produce_obj(name, grades): """ + + mv = ZERO i = 0 for g in grades: - for base_mv in bases[g]: - coef = symbols('{}[{}]'.format(name, i)) # name[i] + for base_mv in bases[g]: + if not wrap_scalar and g == 0: + coef = symbols('{}'.format(name)) # name + else: + coef = symbols('{}[{}]'.format(name, i)) # name[i] mv += coef * base_mv i += 1 @@ -207,7 +224,7 @@ def _comb(n,k): -def name_cls(grades, *template_args): +def name_cls(grades, template_args=(), wrap_scalar=True): """ Return c++ multivector template class name ex rotor inst. @@ -219,6 +236,11 @@ def name_cls(grades, *template_args): ex vector decl. grades = (1,) -> "Mv1" """ + assert isinstance(template_args, (tuple, list)) + + if not wrap_scalar and grades == [0]: + return 'R' + if template_args: targs = '<{}>'.format(join(template_args, ', ')) else: @@ -253,8 +275,31 @@ def csize(grades): p += l return p + - +""" +k,i -- grade, index inside grade +d -- index inside our multi-vector + +n = 3 + +k:[i] + 0:[0] + 1:[0 1 2] + 2:[0 1 2] + 3:[0] + +Mv02 d: (k,i) + 0: (0,0) + 1: (2,0) + 2: (2,1) + 3: (2,2) + +0 <= d < csize(gs) + +d_ki(gs,k,i) -- index inside Mv containing all grades from gs +ki_d(gs,d) -- k,i from d +""" def d_ki(gs, k, i): """ d -> k,i """ @@ -292,22 +337,36 @@ def p_cls(grades): gs = grades + # constructor args,body cargs = [] cbody = [] + for k in gs: l = _comb(n,k) for i in range(l): k,i + + # k -- grade + # i -- index inside grade + # d_ki(gs,k,i) -- index inside Mv containing all grades from gs cargs.append('R const& a{}{}'.format(k,i)) cbody.append('arr[{}] = a{}{};'.format(d_ki(gs, k,i), k, i)) + + # casting constructor body + ccbody_lines = [] + for d in range(csize(gs)): + ccbody_lines.append('arr[{d}] = R(other[{d}]);'.format(d=d)) + ccbody = '\n'.join(ccbody_lines) if gs == [0]: + # implicit cast to R from scalar mod = '' cast = [ mod+'operator R() const { return arr[0]; }', '', ] elif gs == [n]: + # explicit cast to R from pseudoscalar mod = 'explicit ' cast = [ mod+'operator R() const { return arr[0]; }', @@ -318,7 +377,24 @@ def p_cls(grades): mod = '' cast = [] + class_name = name_cls(gs) + + + + assigment = [] + assigment.append('// operator=') + + assigment.extend(p_func_wrap( + name = 'operator=', + ret_type = 'void', + arg_types = [name_cls(gs,['A'])], + arg_mods = ['const&'], + arg_names = ['x'], + body = '\n'.join(['(*this)[{i}] = x[{i}];'.format(i=i) for i in range(len(gs))]), + template = "template ::type* = nullptr>", + )) + return [ 'template ', @@ -337,45 +413,50 @@ def p_cls(grades): 'using {0} = typename Array::{0};'.format('difference_type'), 'using {0} = typename Array::{0};'.format('size_type'), '', - 'Array arr;'.format(csize(gs)), + 'using scalar_type = R;', '', - mod+'{}({}) '.format(name_cls(gs, 'R'), ', '.join(cargs)) + '{', + 'Array arr;', + '', + '// cast constructor from scalar type', + '{} {}({}) {{'.format(mod, name_cls(gs, ['R']), ', '.join(cargs)), cbody, '}', '', - # null constructor - '{}() '.format(name_cls(gs, 'R')) + '{', + '// null constructor', + '{}() '.format(name_cls(gs, ['R'])) + '{', '}', '', + #'// implicit cast constructor', + #'template::type* = nullptr', + #'>', + #'{ClassName}({ClassName} const& other) {{'.format(ClassName = class_name), + #' {ccbody}'.format(ccbody = ccbody), + #'}', + #'', + '// explicit cast constructor', + 'template', + 'explicit', + '{ClassName}({ClassName} const& other) {{'.format(ClassName = class_name), + ' {ccbody}'.format(ccbody = ccbody), + '}', + '', ] + cast + [ 'R& operator[](uint const& d) {', - [ - 'assert(d < size());', - 'return arr[d];', - ], - '}', - '', - 'template', - '{} cast() const {{'.format(name_cls(gs, 'F')), - [ - 'return {}({});'.format( - name_cls(gs, 'F'), - join(['F(arr[{}])'.format(i) for i in range(csize(gs))], ', '), - ), - ], + ' assert(d < size());', + ' return arr[d];', '}', '', 'const R& operator[](uint const& d) const {', - [ - 'assert(d < size());', - 'return arr[d];', - ], + ' assert(d < size());', + ' return arr[d];', '}', '', 'uint size() const {', - ['return {};'.format(csize(gs))], + ' return {};'.format(csize(gs)), '}', '', + ] + assigment + [ p_op('norm2', lambda x: x.norm2(), [gs], gen = p_meth_wrap_inline)[1], '', p_op('rev', lambda x: x.rev(), [gs], gen = p_meth_wrap_inline)[1], @@ -419,13 +500,13 @@ def p_cls(grades): ], '};', '', - 'template class {};'.format(prec, name_cls(gs)), + # 'template class {};'.format(prec, name_cls(gs)), ] from sympy.core.power import Pow -from sympy.core.numbers import Integer,NegativeOne +from sympy.core.numbers import Integer,NegativeOne, Zero from sympy.core.symbol import Symbol from sympy.core.add import Add from sympy.core.mul import Mul @@ -467,6 +548,8 @@ def conv_expr(root): # + + ... return ('('+pat+')').format(*ls) + elif root.func == Zero: + return '0' else: import ipdb; ipdb.set_trace() assert 0 @@ -481,7 +564,9 @@ def conv_expr(root): -def p_meth_wrap_inline(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = ''): +def p_meth_wrap_inline(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = '', + template = '' + ): """ () { = *this; @@ -494,6 +579,7 @@ def p_meth_wrap_inline(name, ret_type, arg_types, arg_mods, arg_names, body, ass decl_args.append(format('{} {} {}', arg_type, arg_mod, arg_name)) return [( + '{template}\n' '{ret_type} {func_name}({arg_lst}) {f_arg_mod} {{\n' '{assert_}\n' 'auto& {f_arg_name} = *this;\n' @@ -507,10 +593,13 @@ def p_meth_wrap_inline(name, ret_type, arg_types, arg_mods, arg_names, body, ass ret_type = ret_type, func_name = name, arg_lst = join(decl_args, ', '), - body = body, + body = body, + template = template, )] -def p_meth_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = ''): +def p_meth_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = '', + template = 'template ' + ): """ template ::() { @@ -525,7 +614,7 @@ def p_meth_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = decl_args.append(format('{} {} {}', arg_type, arg_mod, arg_name)) return [( - 'template \n' + '{template}\n' '{ret_type} {f_arg_type}::{func_name}({arg_lst}) {f_arg_mod} {{\n' '{assert_}\n' 'auto& {f_arg_name} = *this;\n' @@ -539,11 +628,14 @@ def p_meth_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = ret_type = ret_type, func_name = name, arg_lst = join(decl_args, ', '), - body = body, + body = body, + template = template, )] -def p_func_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = ''): +def p_func_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = '', + template = 'template ' + ): """ template () { @@ -557,7 +649,7 @@ def p_func_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = decl_args.append(format('{} {} {}', arg_type, arg_mod, arg_name)) return [( - 'template \n' + '{template}\n' '{ret_type} {func_name}({arg_lst}) {{\n' '{assert_}\n' '{body}\n' @@ -567,14 +659,11 @@ def p_func_wrap(name, ret_type, arg_types, arg_mods, arg_names, body, assert_ = ret_type = ret_type, func_name = name, arg_lst = join(decl_args, ', '), - body = body, + body = body, + template = template, )] - - - - -def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): +def p_op(opname, opfunc, kss, nargs = 'xyz', nbtypes='ABCD', gen = p_func_wrap, wrap_scalar=True): """ template @@ -585,14 +674,42 @@ def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): """ args = [] arg_types = [] - for ks, narg in zip(kss, nargs): - args.append(produce_obj(narg, ks)) - arg_types.append(name_cls(ks,'R')) + for ks, narg, btype in zip(kss, nargs, nbtypes): + args.append(produce_obj(narg, ks, wrap_scalar=wrap_scalar)) + + if len(kss) == 1: + btype = 'R' + + if not wrap_scalar and ks == [0]: + arg_types.append(btype) + else: + arg_types.append(name_cls(ks,[btype])) + + + + if len(kss) == 1: + arg_btypes = ['R'] + ret_btype = 'R' + + if gen == p_func_wrap: + template = 'template ' + else: + template = '' + + else: + arg_btypes = nbtypes[:len(kss)] + ret_btype = nbtypes[len(kss)] + + arg_btypes_lst1 = ', '.join('class {}'.format(X) for X in arg_btypes) + arg_btypes_lst2 = ', '.join('{}'.format(X) for X in arg_btypes) + + ret_type_decl = 'class {} = typename std::common_type<{}>::type'.format(ret_btype, arg_btypes_lst2) + template = 'template<{}, \n{}>\n'.format(arg_btypes_lst1, ret_type_decl) + arg_names = nargs[:len(kss)] - + r = opfunc(*args) - if (isinstance(r, MV)): @@ -606,8 +723,9 @@ def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): if any([b != ZERO for b in bs]): nz_grades.append(g) - ret_type = name_cls(nz_grades,'R') + ret_type = name_cls(nz_grades,[ret_btype], wrap_scalar=wrap_scalar) + ces = [] for g in nz_grades: for coef in bss[g]: @@ -616,6 +734,7 @@ def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): coe = ', '.join(ces) body = format('return {}({});', ret_type, coe) + #import ipdb; ipdb.set_trace() else: # result is scalar @@ -628,10 +747,12 @@ def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): if len(kss) == 2 and kss[0] == kss[1]: - assert_ = 'assert(&{} != &{});\n'.format(nargs[0], nargs[1]) + # assert_ = 'assert(&{} != &{});\n'.format(nargs[0], nargs[1]) + assert_ = '' else: assert_ = '' + return nz_grades, gen( name = opname, ret_type = ret_type, @@ -639,7 +760,8 @@ def p_op(opname, opfunc, kss, nargs = 'xyz', gen = p_func_wrap): arg_mods = ['const&'] * len(arg_types), arg_names = arg_names, body = body, - assert_=assert_ + assert_=assert_, + template = template, ) @@ -662,7 +784,7 @@ def p_print(ks): ' t << "{ncls}(" << {out_args} << ")";' ' return t;' '}}').format( - ncls = name_cls(ks,'R'), + ncls = name_cls(ks,['R']), out_args = join(['x[{}]'.format(i) for i in range(csize(ks))], ' << "," << '), )] @@ -697,7 +819,7 @@ def p_xeq_func(grades, name, opers): return p_func_wrap( name = name, ret_type = 'bool', - arg_types = [name_cls(grades,'R'), name_cls(grades,'R')], + arg_types = [name_cls(grades,['R']), name_cls(grades,['R'])], arg_mods = ['const&'] * 2, arg_names = ['x', 'y'], body = format('return {};', oper_join(pairs, *opers)) @@ -741,7 +863,22 @@ def main(): rk, func = p_op('operator*', operator.mul, (c1, c2)) if rk in cs: xs.extend(func) - + + xs.append('// mul when one arg is Scalar') + for c1 in [[0]]: + for c2 in cs: + if c1 != c2: # disable mul(R,R) + rk, func = p_op('operator*', operator.mul, (c1, c2), wrap_scalar=False) + if rk in cs: + xs.extend(func) + + for c1 in cs: + for c2 in [[0]]: + if c1 != c2: # disable mul(R,R) + rk, func = p_op('operator*', operator.mul, (c1, c2), wrap_scalar=False) + if rk in cs: + xs.extend(func) + xs.append('// inner product') for c1 in cs: @@ -775,6 +912,7 @@ def main(): xs.extend(func) ''' + xs.append('// add') for c1 in cs: for c2 in cs: @@ -786,10 +924,11 @@ def main(): xs.extend(p_func_wrap( name = 'operator+=', ret_type = 'void', - arg_types = [name_cls(c1,'R'), name_cls(c2,'R')], + arg_types = [name_cls(c1,['A']), name_cls(c2,['B'])], arg_mods = ['&', 'const&'], arg_names = ['x', 'y'], body = 'x = x + y;', + template = "template ::type* = nullptr>", )) xs.append('// sub') @@ -803,10 +942,11 @@ def main(): xs.extend(p_func_wrap( name = 'operator-=', ret_type = 'void', - arg_types = [name_cls(c1,'R'), name_cls(c2,'R')], + arg_types = [name_cls(c1,['A']), name_cls(c2,['B'])], arg_mods = ['&', 'const&'], arg_names = ['x', 'y'], body = 'x = x - y;', + template = "template ::type* = nullptr>", )) xs.append('// rotated') @@ -823,7 +963,7 @@ def main(): # GEN:: auto const _1 = Mv0<>(1); xs.append('auto const _1 = {}(1);'.format( - name_cls([0], '') + name_cls([0], ['float']) )) # GEN:: auto const e1 = Mv1<>(1,0,0); @@ -834,13 +974,13 @@ def main(): args[i] = 1 xs.append('auto const e{} = {}({});'.format( str(i), - name_cls([1], ''), + name_cls([1], ['float']), join(map(str,args), ',') )) # GEN:: auto const I = Mv3<>(1); xs.append('auto const I = {}(1);'.format( - name_cls([n], '') + name_cls([n], ['float']) )) xs.append('') @@ -858,8 +998,8 @@ def main(): func = p_func_wrap( name='rotor', - ret_type = name_cls([0,2], 'R'), - arg_types = [name_cls([2], 'R'), 'R'], + ret_type = name_cls([0,2], ['R']), + arg_types = [name_cls([2], ['R']), 'R'], arg_mods = ['const&', 'const&'], arg_names = ['nplane', 'angle'], body = ( diff --git a/tests/test_aga2.cpp b/tests/test_aga2.cpp index ee84076..c068d81 100644 --- a/tests/test_aga2.cpp +++ b/tests/test_aga2.cpp @@ -2,26 +2,114 @@ #include "catch.hpp" #include "../aga2.hpp" +#include "../dual.hpp" using aga2::Mv0; // scalar, _1 using aga2::Mv1; // vector using aga2::Mv2; // plane, I using aga2::Mv02; // rotor +using dual::Dual; + +// template::Mv1) +// check + + + + + +TEST_CASE( "conversions2", "" ) { + + + // implicit conversion int -> float + Mv1 x; + x = Mv1(1,2); + + //Mv1(Mv1(1,2)); + + REQUIRE( float(Mv0(1)) == 1.0f ); + + REQUIRE( Mv0(1) == 1.0f ); + + REQUIRE( (Mv0(1) * 2.0f) == 2.0f ); + + REQUIRE( (Mv1(1,2) * 2.0f) == Mv1(2,4) ); + + // explicit safe conversion + REQUIRE_NOTHROW( Mv1(Mv1(1,2)) ); + + // explicit unsafe conv + REQUIRE_NOTHROW( Mv1(Mv1(1,2)) ); + + + REQUIRE_NOTHROW( Mv1(1,2) ); + + // implicit safe conversion + //REQUIRE_NOTHROW( (Mv1(1,2) * 2.0f) ); + +} + + +TEST_CASE( "dual", "" ) { + + + Dual x; + + x = Dual(1.0f, 1.0f); + + // f(x) = x*x + auto f = x*x; + + // f(x) and df(x)/dx + REQUIRE( f[0] == 1.0f ); + REQUIRE( f[1] == 2.0f ); + +} + +TEST_CASE( "dual and vect", "" ) { + /* + using T = Dual; + + Mv1 v; + + // gradient + float g[2] = {1,1}; + + v[0] = T(2.0f, 1.0f); + v[1] = T(3.0f); + + // f(x) = x|x + auto f = T(v|v); + + // f(x) and df(x)/dx1 + REQUIRE( f[0] == 13.0f ); + REQUIRE( f[1] == 4.0f ); + */ + +} + + + +TEST_CASE( "vector mul num", "" ) { + auto x = 3 * Mv1(1,2); + REQUIRE( x[0] == 3 ); + REQUIRE( x[1] == 6 ); +} + TEST_CASE( "vector add", "" ) { - auto x = Mv1<>(1,2) + Mv1<>(2,3); + auto x = Mv1(1,2) + Mv1(2,3); REQUIRE( x[0] == 3 ); REQUIRE( x[1] == 5 ); } TEST_CASE( "vector sub", "" ) { - auto x = Mv1<>(1,-8) - Mv1<>(2,3); + auto x = Mv1(1,-8) - Mv1(2,3); REQUIRE( x[0] == -1 ); REQUIRE( x[1] == -11 ); } TEST_CASE( "vector inner product", "" ) { - auto x = Mv1<>(1,-8) | Mv1<>(2,3); + auto x = Mv1(1,-8) | Mv1(2,3); REQUIRE( x == (1*2-8*3) ); } @@ -31,15 +119,15 @@ TEST_CASE( "vector inner product", "" ) { }*/ TEST_CASE( "vector neq", "" ) { - REQUIRE( Mv1<>(1,2) != Mv1<>(1,3) ); - REQUIRE( Mv1<>(2,1) != Mv1<>(3,1) ); - REQUIRE( Mv1<>(1,2) != Mv1<>(3,4) ); - REQUIRE( !(Mv1<>(1,2) != Mv1<>(1,2)) ); + REQUIRE( Mv1(1,2) != Mv1(1,3) ); + REQUIRE( Mv1(2,1) != Mv1(3,1) ); + REQUIRE( Mv1(1,2) != Mv1(3,4) ); + REQUIRE( !(Mv1(1,2) != Mv1(1,2)) ); } TEST_CASE( "vector eq", "" ) { - REQUIRE( Mv1<>(1,2) == Mv1<>(1,2) ); - REQUIRE( !(Mv1<>(1,3) == Mv1<>(1,2)) ); - REQUIRE( !(Mv1<>(3,1) == Mv1<>(2,1)) ); - REQUIRE( !(Mv1<>(1,2) == Mv1<>(3,4)) ); -} \ No newline at end of file + REQUIRE( Mv1(1,2) == Mv1(1,2) ); + REQUIRE( !(Mv1(1,3) == Mv1(1,2)) ); + REQUIRE( !(Mv1(3,1) == Mv1(2,1)) ); + REQUIRE( !(Mv1(1,2) == Mv1(3,4)) ); +}