From dd5544060284ccbcc0d9a29ee72dfffaa45c4c08 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sat, 30 Jul 2016 15:12:45 +0200 Subject: [PATCH 1/9] Added opBinary and opOpAssign with +/- to Matrix Also a unittest to validate the results is provided. --- source/scid/matrix.d | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index c62fff8..68cb530 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -370,6 +370,53 @@ public: } else static assert (false); } + + /** + Sum or substract operation for two matrices. + */ + MatrixView opBinary(string op)(MatrixView rhs) + if (op == "+" || op == "-") + in + { + assert(rows == rhs.rows && cols == rhs.cols); + } + body + { + auto new_array = new T[rows * cols]; + mixin("new_array[] = array[] " ~ op ~ " rhs.array[];"); + return MatrixView!(T, stor, tri)(new_array, rows, cols); + } + + ref MatrixView opOpAssign(string op)(MatrixView rhs) + if (op == "+" || op == "-") + in + { + assert(rows == rhs.rows && cols == rhs.cols); + } + body + { + mixin("array[] " ~ op ~ "= rhs.array[];"); + return this; + } + + unittest + { + import std.range; + void testOpBinary(NumericType)() { + auto m1 = MatrixView!NumericType(iota!NumericType(4).array, 2, 2); + auto m2 = MatrixView!NumericType(iota!NumericType(3, 7).array, 2, 2); + assert((m1 + m2).array == [0 + 3, 1 + 4, 2 + 5, 3 + 6]); + assert((m1 - m2).array == [0 - 3, 1 - 4, 2 - 5, 3 - 6]); + m1 += m2; + assert(m1.array == [0 + 3, 1 + 4, 2 + 5, 3 + 6]); + m1 -= m2; + m1 -= m2; + assert(m1.array == [0 - 3, 1 - 4, 2 - 5, 3 - 6]); + } + testOpBinary!float(); + testOpBinary!double(); + testOpBinary!int(); + } } unittest From ec681c5674264065b965dd8f460c273f50b7efe4 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sun, 31 Jul 2016 12:59:59 +0200 Subject: [PATCH 2/9] Added multiplication by scalar and move unittests The unittests are all inside the class definition --- source/scid/matrix.d | 238 +++++++++++++++++++++++++++---------------- 1 file changed, 150 insertions(+), 88 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index 68cb530..6d776e7 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -8,6 +8,7 @@ License: Boost License 1.0 */ module scid.matrix; +import std.array; import std.string: format; import std.traits; @@ -371,24 +372,80 @@ public: else static assert (false); } - /** - Sum or substract operation for two matrices. - */ - MatrixView opBinary(string op)(MatrixView rhs) - if (op == "+" || op == "-") - in - { - assert(rows == rhs.rows && cols == rhs.cols); - } - body + unittest { - auto new_array = new T[rows * cols]; - mixin("new_array[] = array[] " ~ op ~ " rhs.array[];"); - return MatrixView!(T, stor, tri)(new_array, rows, cols); + alias MatrixView!real GeneralMatrix; + real[] g = [1.0L, 2, 3, 4, 5, 6]; + + auto gm1 = GeneralMatrix(g, 2); + auto gm2 = GeneralMatrix(g, 3); + + assert (gm1.cols == 3); + assert (gm2.cols == 2); + + assert (gm1[1,0] == 2); + assert (gm2[1,0] == 2); + + assert (gm1[1,1] == 4); + assert (gm2[1,1] == 5); + + gm2[1,1] += 1; assert (gm2[1,1] == 6); + gm2[1,1] = 10; assert (gm2[1,1] == 10); + + + alias MatrixView!(real, Storage.Triangular) UTMatrix; + real[] u = [1.0, 2, 3, 4, 5, 6]; + + auto um1 = UTMatrix(u, 3); + assert (um1.cols == 3); + assert (um1[1,0] == 0.0); + assert (um1[1,1] == 3.0); + um1[0,2] += 3; assert (u[3] == 7); + um1[2,2] = 10; assert (u[5] == 10); + + + alias MatrixView!(real, Storage.Triangular, Triangle.Lower) LTMatrix; + real[] l = [1.0, 2, 3, 4, 5, 6]; + + auto lm1 = LTMatrix(l, 3); + assert (lm1.cols == 3); + assert (lm1[0,1] == 0.0); + assert (lm1[1,1] == 4.0); + lm1[2,0] += 4; assert (l[2] == 7); + lm1[2,2] = 10; assert (l[5] == 10); + + + alias MatrixView!(real, Storage.Symmetric) USMatrix; + real[] us = [1.0, 2, 3, 4, 5, 6]; + + auto usm1 = USMatrix(us, 3); + assert (usm1.cols == 3); + assert (usm1[1,2] == 5.0); + foreach (i; 0 .. usm1.rows) + foreach (j; 0 .. i) + assert (usm1[i,j] == usm1[j,i]); + usm1[0,2] += 3; assert (usm1[2,0] == 7); + usm1[1,2] = 10; assert (usm1[2,1] == 10); + + + alias MatrixView!(real, Storage.Symmetric, Triangle.Lower) LSMatrix; + real[] ls = [1.0, 2, 3, 4, 5, 6]; + + auto lsm1 = LSMatrix(ls, 3); + assert (lsm1.cols == 3); + assert (lsm1[1,2] == 5.0); + foreach (i; 0 .. lsm1.rows) + foreach (j; 0 .. i) + assert (lsm1[i,j] == lsm1[j,i]); + lsm1[0,2] += 3; assert (lsm1[2,0] == 6); + lsm1[1,2] = 10; assert (lsm1[2,1] == 10); } + /** + Elementwise sum, substract, product and division operations for matrices. + */ ref MatrixView opOpAssign(string op)(MatrixView rhs) - if (op == "+" || op == "-") + if (op == "+" || op == "-" || op == "*" || op == "/") in { assert(rows == rhs.rows && cols == rhs.cols); @@ -401,91 +458,96 @@ public: unittest { - import std.range; - void testOpBinary(NumericType)() { - auto m1 = MatrixView!NumericType(iota!NumericType(4).array, 2, 2); - auto m2 = MatrixView!NumericType(iota!NumericType(3, 7).array, 2, 2); - assert((m1 + m2).array == [0 + 3, 1 + 4, 2 + 5, 3 + 6]); - assert((m1 - m2).array == [0 - 3, 1 - 4, 2 - 5, 3 - 6]); + void test(NumericType)() { + auto m1 = MatrixView!NumericType([0, 1, 2, 3], 2, 2); + auto m2 = MatrixView!NumericType([3, 4, 5, 6], 2, 2); m1 += m2; - assert(m1.array == [0 + 3, 1 + 4, 2 + 5, 3 + 6]); - m1 -= m2; - m1 -= m2; - assert(m1.array == [0 - 3, 1 - 4, 2 - 5, 3 - 6]); + assert(m1.array == [3, 5, 7, 9]); + m1 -= m2; m1 -= m2; + assert(m1.array == [-3, -3, -3, -3]); } - testOpBinary!float(); - testOpBinary!double(); - testOpBinary!int(); + test!float(); + test!double(); + test!int(); } -} - -unittest -{ - alias MatrixView!real GeneralMatrix; - real[] g = [1.0L, 2, 3, 4, 5, 6]; - - auto gm1 = GeneralMatrix(g, 2); - auto gm2 = GeneralMatrix(g, 3); - - assert (gm1.cols == 3); - assert (gm2.cols == 2); - - assert (gm1[1,0] == 2); - assert (gm2[1,0] == 2); - - assert (gm1[1,1] == 4); - assert (gm2[1,1] == 5); - - gm2[1,1] += 1; assert (gm2[1,1] == 6); - gm2[1,1] = 10; assert (gm2[1,1] == 10); + /** + Multiply a matrix by an scalar factor + */ + ref MatrixView opOpAssign(string op)(T scalar) + if (op == "*") + body + { + array[] *= scalar; + return this; + } - alias MatrixView!(real, Storage.Triangular) UTMatrix; - real[] u = [1.0, 2, 3, 4, 5, 6]; - - auto um1 = UTMatrix(u, 3); - assert (um1.cols == 3); - assert (um1[1,0] == 0.0); - assert (um1[1,1] == 3.0); - um1[0,2] += 3; assert (u[3] == 7); - um1[2,2] = 10; assert (u[5] == 10); - - - alias MatrixView!(real, Storage.Triangular, Triangle.Lower) LTMatrix; - real[] l = [1.0, 2, 3, 4, 5, 6]; - - auto lm1 = LTMatrix(l, 3); - assert (lm1.cols == 3); - assert (lm1[0,1] == 0.0); - assert (lm1[1,1] == 4.0); - lm1[2,0] += 4; assert (l[2] == 7); - lm1[2,2] = 10; assert (l[5] == 10); + unittest + { + void test(NumericType)() { + auto m = MatrixView!NumericType([0, 1, 2, 3], 2, 2); + m *= 2; + assert(m.array == [0, 2, 4, 6]); + } + test!float(); + test!double(); + test!int(); + } + /** + Use opOpAssign methods to generate equivalent opBinary operators + */ + MatrixView opBinary(string op)(MatrixView rhs) + in + { + assert(rows == rhs.rows && cols == rhs.cols); + } + body + { + auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); + matrix.opOpAssign!op(rhs); + return matrix; + } - alias MatrixView!(real, Storage.Symmetric) USMatrix; - real[] us = [1.0, 2, 3, 4, 5, 6]; + unittest + { + void test(NumericType)() { + auto m1 = MatrixView!NumericType([1, 1, 2, 3], 2, 2); + auto m2 = MatrixView!NumericType([3, 4, 6, 6], 2, 2); + assert((m1 + m2).array == [ 4, 5, 8, 9]); + assert((m1 - m2).array == [-2, -3, -4, -3]); + assert((m1 * m2).array == [ 3, 4, 12, 18]); + assert((m2 / m1).array == [ 3, 4, 3, 2]); + } + test!float(); + test!double(); + test!int(); + } - auto usm1 = USMatrix(us, 3); - assert (usm1.cols == 3); - assert (usm1[1,2] == 5.0); - foreach (i; 0 .. usm1.rows) - foreach (j; 0 .. i) - assert (usm1[i,j] == usm1[j,i]); - usm1[0,2] += 3; assert (usm1[2,0] == 7); - usm1[1,2] = 10; assert (usm1[2,1] == 10); + /** + Multiplication of a matrix by an scalar. + */ + MatrixView opBinary(string op)(T scalar) + if (op == "*") + body + { + auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); + matrix.opOpAssign!op(scalar); + return matrix; + } - alias MatrixView!(real, Storage.Symmetric, Triangle.Lower) LSMatrix; - real[] ls = [1.0, 2, 3, 4, 5, 6]; + unittest + { + void test(NumericType)() { + auto m = MatrixView!NumericType([0, 1, 2, 3], 2, 2); + assert((m * 2).array == [0, 2, 4, 6]); + } + test!float(); + test!double(); + test!int(); + } - auto lsm1 = LSMatrix(ls, 3); - assert (lsm1.cols == 3); - assert (lsm1[1,2] == 5.0); - foreach (i; 0 .. lsm1.rows) - foreach (j; 0 .. i) - assert (lsm1[i,j] == lsm1[j,i]); - lsm1[0,2] += 3; assert (lsm1[2,0] == 6); - lsm1[1,2] = 10; assert (lsm1[2,1] == 10); } From 45501e2654178ea70c27e38185edd9ef04061156 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sun, 31 Jul 2016 13:26:56 +0200 Subject: [PATCH 3/9] Add +/-/div by scalar and use a single opBinary --- source/scid/matrix.d | 48 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index 6d776e7..89a2e98 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -474,11 +474,15 @@ public: /** Multiply a matrix by an scalar factor */ - ref MatrixView opOpAssign(string op)(T scalar) - if (op == "*") + ref MatrixView opOpAssign(string op, RightType)(RightType scalar) + if (op == "+" || op == "-" || op == "*" || op == "/") + in + { + static assert(isNumeric!RightType); + } body { - array[] *= scalar; + mixin("array[] " ~ op ~ "= scalar;"); return this; } @@ -497,11 +501,7 @@ public: /** Use opOpAssign methods to generate equivalent opBinary operators */ - MatrixView opBinary(string op)(MatrixView rhs) - in - { - assert(rows == rhs.rows && cols == rhs.cols); - } + MatrixView opBinary(string op, RightType)(RightType rhs) body { auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); @@ -518,30 +518,14 @@ public: assert((m1 - m2).array == [-2, -3, -4, -3]); assert((m1 * m2).array == [ 3, 4, 12, 18]); assert((m2 / m1).array == [ 3, 4, 3, 2]); - } - test!float(); - test!double(); - test!int(); - } - - - /** - Multiplication of a matrix by an scalar. - */ - MatrixView opBinary(string op)(T scalar) - if (op == "*") - body - { - auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); - matrix.opOpAssign!op(scalar); - return matrix; - } - - unittest - { - void test(NumericType)() { - auto m = MatrixView!NumericType([0, 1, 2, 3], 2, 2); - assert((m * 2).array == [0, 2, 4, 6]); + assert((m1 + 1).array == [ 2, 2, 3, 4]); + assert((m1 - 1).array == [ 0, 0, 1, 2]); + assert((m1 * 2).array == [ 2, 2, 4, 6]); + static if (isIntegral!NumericType) { + assert((m2 / 2).array == [1, 2, 3, 3]); + } else { + assert((m2 / 2).array == [1.5, 2, 3, 3]); + } } test!float(); test!double(); From eb26f042e638f2dc232b330c66b17d1c50e39205 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sun, 31 Jul 2016 15:49:05 +0200 Subject: [PATCH 4/9] Added dotProduct for two matrices It can still be optimized, it is only a proof of concept. --- source/scid/matrix.d | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index 89a2e98..c6a79d4 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -535,6 +535,49 @@ public: } +/** +Matrix-matrix inner product. + +Currently only supports general storage. + +TODO: Optimize to iterate the arrays in sequential order. +TODO: Make sure the calls to the opIndex are inlined +*/ + +MatrixView!(T, Storage.General) dotProduct(T)(MatrixView!(T, Storage.General) a, + MatrixView!(T, Storage.General) b) +in +{ + assert(a.cols == b.rows); +} +body +{ + auto c = MatrixView!T(new T[a.rows * b.cols], a.rows, b.cols); + for (int i = 0; i < c.rows; ++i) { + for (int j = 0; j < c.cols; ++j) { + c[i,j] = 0; + for (int k = 0; k < a.cols; ++k) { + c[i,j] += a[i,k] * b[k,j]; + } + } + } + return c; +} + +unittest +{ + // | 3 6 | + // | 1 2 4 | | | | 35 16 | + // | | * | 4 1 | = | | + // | 1 3 5 | | | | 45 19 | + // | 6 2 | + auto m1 = MatrixView!double([1, 1, 2, 3, 4, 5], 2, 3); + auto m2 = MatrixView!double([3, 4, 6, 6, 1, 2], 3, 2); + auto m3 = dotProduct(m1, m2); + assert(m3.array == [35, 45, 16, 19]); +} + + /** Evaluates to true if the given type is an instantiation of MatrixView. Optionally test the element type and/or storage From 2b1fc8062930bfd51f1900263efeb11e3eeabead Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sun, 31 Jul 2016 15:53:27 +0200 Subject: [PATCH 5/9] Added TODO list for dotProduct --- source/scid/matrix.d | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index c6a79d4..6a065a8 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -538,10 +538,10 @@ public: /** Matrix-matrix inner product. -Currently only supports general storage. - +TODO: Extend to other kinds of storage. TODO: Optimize to iterate the arrays in sequential order. TODO: Make sure the calls to the opIndex are inlined +TODO: Use BLAS. */ MatrixView!(T, Storage.General) dotProduct(T)(MatrixView!(T, Storage.General) a, @@ -564,6 +564,7 @@ body return c; } + unittest { // | 3 6 | From 73e64a13cd2e83454e0262a972e44db55ec3c5e3 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Sun, 31 Jul 2016 16:26:09 +0200 Subject: [PATCH 6/9] Make sure the opBinaryRight works as expected Special care must be taken with - and / operations. --- source/scid/matrix.d | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index 6a065a8..b80ded0 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -509,23 +509,45 @@ public: return matrix; } + /** + Use opOpAssign methods to generate equivalent opBinaryRight operators + */ + MatrixView opBinaryRight(string op, LeftType)(LeftType lhs) + body + { + static if (op == "/" || op == "-") { + auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); + for (int i = 0; i < matrix.array.length; ++i) { + mixin("matrix.array[i] = lhs " ~ op ~ " matrix.array[i];"); + } + return matrix; + } + else { + return opBinary!op(lhs); + } + } + unittest { void test(NumericType)() { auto m1 = MatrixView!NumericType([1, 1, 2, 3], 2, 2); auto m2 = MatrixView!NumericType([3, 4, 6, 6], 2, 2); assert((m1 + m2).array == [ 4, 5, 8, 9]); - assert((m1 - m2).array == [-2, -3, -4, -3]); assert((m1 * m2).array == [ 3, 4, 12, 18]); + assert((m1 - m2).array == [-2, -3, -4, -3]); assert((m2 / m1).array == [ 3, 4, 3, 2]); assert((m1 + 1).array == [ 2, 2, 3, 4]); - assert((m1 - 1).array == [ 0, 0, 1, 2]); assert((m1 * 2).array == [ 2, 2, 4, 6]); + assert((m1 - 1).array == [ 0, 0, 1, 2]); static if (isIntegral!NumericType) { - assert((m2 / 2).array == [1, 2, 3, 3]); + assert((m2 / 2).array == [ 1, 2, 3, 3]); } else { - assert((m2 / 2).array == [1.5, 2, 3, 3]); + assert((m2 / 2).array == [1.5, 2, 3, 3]); } + assert((1 + m1).array == [ 2, 2, 3, 4]); + assert((2 * m1).array == [ 2, 2, 4, 6]); + assert((1 - m1).array == [ 0, 0, -1, -2]); + assert((6 / m1).array == [ 6, 6, 3, 2]); } test!float(); test!double(); From 533368616fe698e589f3131e5d67470b89caa939 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Mon, 1 Aug 2016 00:49:24 +0200 Subject: [PATCH 7/9] Added support for ^^ operator --- source/scid/matrix.d | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index b80ded0..4d087cd 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -442,10 +442,10 @@ public: } /** - Elementwise sum, substract, product and division operations for matrices. + Sum, substract, product, division and exponentiation operations. */ ref MatrixView opOpAssign(string op)(MatrixView rhs) - if (op == "+" || op == "-" || op == "*" || op == "/") + if (op == "+" || op == "-" || op == "*" || op == "/" || op == "^^") in { assert(rows == rhs.rows && cols == rhs.cols); @@ -463,8 +463,14 @@ public: auto m2 = MatrixView!NumericType([3, 4, 5, 6], 2, 2); m1 += m2; assert(m1.array == [3, 5, 7, 9]); - m1 -= m2; m1 -= m2; - assert(m1.array == [-3, -3, -3, -3]); + m1 -= m2; + assert(m1.array == [0, 1, 2, 3]); + m1 *= m2; + assert(m1.array == [0, 4, 10, 18]); + m1 /= m2; + assert(m1.array == [0, 1, 2, 3]); + m1 ^^= m2; + assert(m1.array == [0, 1, 32, 729]); } test!float(); test!double(); @@ -472,10 +478,10 @@ public: } /** - Multiply a matrix by an scalar factor + Apply an scalar a matrix by an scalar factor */ ref MatrixView opOpAssign(string op, RightType)(RightType scalar) - if (op == "+" || op == "-" || op == "*" || op == "/") + if (op == "+" || op == "-" || op == "*" || op == "/" || op == "^^") in { static assert(isNumeric!RightType); @@ -490,8 +496,16 @@ public: { void test(NumericType)() { auto m = MatrixView!NumericType([0, 1, 2, 3], 2, 2); + m += 1; + assert(m.array == [1, 2, 3, 4]); + m -= 1; + assert(m.array == [0, 1, 2, 3]); m *= 2; assert(m.array == [0, 2, 4, 6]); + m /= 2; + assert(m.array == [0, 1, 2, 3]); + m ^^= 3; + assert(m.array == [0, 1, 8, 27]); } test!float(); test!double(); @@ -515,7 +529,7 @@ public: MatrixView opBinaryRight(string op, LeftType)(LeftType lhs) body { - static if (op == "/" || op == "-") { + static if (op == "/" || op == "-" || op == "^^") { auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); for (int i = 0; i < matrix.array.length; ++i) { mixin("matrix.array[i] = lhs " ~ op ~ " matrix.array[i];"); @@ -539,15 +553,17 @@ public: assert((m1 + 1).array == [ 2, 2, 3, 4]); assert((m1 * 2).array == [ 2, 2, 4, 6]); assert((m1 - 1).array == [ 0, 0, 1, 2]); + assert((m1 ^^ 3).array == [ 1, 1, 8, 27]); static if (isIntegral!NumericType) { assert((m2 / 2).array == [ 1, 2, 3, 3]); } else { assert((m2 / 2).array == [1.5, 2, 3, 3]); } - assert((1 + m1).array == [ 2, 2, 3, 4]); - assert((2 * m1).array == [ 2, 2, 4, 6]); - assert((1 - m1).array == [ 0, 0, -1, -2]); - assert((6 / m1).array == [ 6, 6, 3, 2]); + assert((1 + m1).array == [ 2, 2, 3, 4]); + assert((2 * m1).array == [ 2, 2, 4, 6]); + assert((1 - m1).array == [ 0, 0, -1, -2]); + assert((6 / m1).array == [ 6, 6, 3, 2]); + assert((3 ^^ m1).array == [ 3, 3, 9, 27]); } test!float(); test!double(); From c519548ecfe1a21c86dfb2065202dc7b52297238 Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Mon, 1 Aug 2016 00:52:27 +0200 Subject: [PATCH 8/9] Use copy function instead of custom line of code --- source/scid/matrix.d | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index 4d087cd..e27e444 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -518,19 +518,21 @@ public: MatrixView opBinary(string op, RightType)(RightType rhs) body { - auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); + auto matrix = copy(this); matrix.opOpAssign!op(rhs); return matrix; } /** Use opOpAssign methods to generate equivalent opBinaryRight operators + + TODO: simplify this code (it looks like it can be easier). */ MatrixView opBinaryRight(string op, LeftType)(LeftType lhs) body { static if (op == "/" || op == "-" || op == "^^") { - auto matrix = MatrixView!(T, stor, tri)(array.array, rows, cols); + auto matrix = copy(this); for (int i = 0; i < matrix.array.length; ++i) { mixin("matrix.array[i] = lhs " ~ op ~ " matrix.array[i];"); } From 39f7303c5f5bbd4b78d6b584b4a01865409ff38d Mon Sep 17 00:00:00 2001 From: Aleix Gimenez Date: Mon, 1 Aug 2016 13:24:33 +0200 Subject: [PATCH 9/9] Improve opBinaryRight code --- source/scid/matrix.d | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/source/scid/matrix.d b/source/scid/matrix.d index e27e444..d6b9e1d 100644 --- a/source/scid/matrix.d +++ b/source/scid/matrix.d @@ -524,23 +524,20 @@ public: } /** - Use opOpAssign methods to generate equivalent opBinaryRight operators + Generate opBinaryRight operators TODO: simplify this code (it looks like it can be easier). */ MatrixView opBinaryRight(string op, LeftType)(LeftType lhs) + if (isNumeric!LeftType + && (op == "+" || op == "-" || op == "*" || op == "/" || op == "^^")) body { - static if (op == "/" || op == "-" || op == "^^") { - auto matrix = copy(this); - for (int i = 0; i < matrix.array.length; ++i) { - mixin("matrix.array[i] = lhs " ~ op ~ " matrix.array[i];"); - } - return matrix; - } - else { - return opBinary!op(lhs); + auto matrix = copy(this); + for (int i = 0; i < matrix.array.length; ++i) { + mixin("matrix.array[i] = lhs " ~ op ~ " matrix.array[i];"); } + return matrix; } unittest