template ExpressionOperatorsInferable(size_t spec)
enum stringMixin =
format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
alias at = opIndex;
} ~ format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
bool opEquals(Rhs)(auto ref in Rhs mat) const
if(isMatrix!Rhs && !is(Unqual!Rhs == typeof(this)) && !isAbstractMatrix!(Rhs))
{
static assert(isValidOperator!(Unqual!(typeof(this)), "+", Rhs));
if(!this.inferSize(mat.rows, mat.cols).isValid)
return false;
foreach(i; 0 .. mat.rows)
foreach(j; 0 .. mat.cols)
if(this[i, j] != mat.at(i, j))
return false;
return true;
}
} ~ (spec & ETOSpec.matrixAddMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "+", Rhs)(auto ref const Rhs mat) const
if(isMatrix!Rhs || isAbstractMatrix!Rhs)
in{
static if(!isAbstractMatrix!Rhs)
assert(this.inferSize(mat.rows, mat.cols).isValid);
}
body{
static assert(isValidOperator!(typeof(this), op, Rhs));
return matrixExpression!"+"(this, mat);
}
} : "") ~ (spec & ETOSpec.matrixSubMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "-", Rhs)(auto ref const Rhs mat) const
if(isMatrix!Rhs || isAbstractMatrix!Rhs)
in{
static if(!isAbstractMatrix!Rhs)
assert(this.inferSize(mat.rows, mat.cols).isValid);
}
body{
static assert(isValidOperator!(typeof(this), op, Rhs));
return matrixExpression!"-"(this, mat);
}
} : "") ~ (spec & ETOSpec.matrixMulMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "*", Rhs)(auto ref const Rhs mat) const
if(isMatrix!Rhs || isAbstractMatrix!Rhs)
in{
static if(!isAbstractMatrix!Rhs)
assert(this.inferSize(wild, mat.rows).isValid);
}
body{
static assert(isValidOperator!(typeof(this), op, Rhs));
return matrixExpression!"*"(this, mat);
}
} : "") ~ (spec & ETOSpec.matrixAddScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "+", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(typeof(this), op, S));
return matrixExpression!"+"(this, s);
}
} : "") ~ (spec & ETOSpec.scalarAddMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinaryRight(string op : "+", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(S, op, typeof(this)));
return matrixExpression!"+"(s, this);
}
} : "") ~ (spec & ETOSpec.matrixSubScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "-", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(typeof(this), op, S));
return matrixExpression!"-"(this, s);
}
} : "") ~ (spec & ETOSpec.scalarSubMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinaryRight(string op : "-", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(S, op, typeof(this)));
return matrixExpression!"-"(s, this);
}
} : "") ~ (spec & ETOSpec.matrixMulScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "*", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(typeof(this), op, S));
return matrixExpression!"*"(this, s);
}
} : "") ~ (spec & ETOSpec.scalarMulMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinaryRight(string op : "*", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(S, op, typeof(this)));
return matrixExpression!"*"(s, this);
}
} : "") ~ (spec & ETOSpec.matrixDivScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinary(string op : "/", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(typeof(this), op, S));
return matrixExpression!"/"(this, s);
}
} : "") ~ (spec & ETOSpec.scalarDivMatrix ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
auto opBinaryRight(string op : "/", S)(const S s) const
if(isNotVectorOrMatrix!S)
{
static assert(isValidOperator!(S, op, typeof(this)));
return matrixExpression!"/"(s, this);
}
} : "") ~ (spec & ETOSpec.addScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
void opOpAssign(string op : "+", S)(const S scalar)
if(isNotVectorOrMatrix!S && is(typeof(this[0, 0] += scalar)))
{
foreach(r; 0 .. rows)
foreach(c; 0 .. cols)
this[r, c] += scalar;
}
} : "") ~ (spec & ETOSpec.subScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
void opOpAssign(string op : "-", S)(const S scalar)
if(isNotVectorOrMatrix!S && is(typeof(this[0, 0] -= scalar)))
{
foreach(r; 0 .. rows)
foreach(c; 0 .. cols)
this[r, c] -= scalar;
}
} : "") ~ (spec & ETOSpec.mulScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
void opOpAssign(string op : "*", S)(const S scalar)
if(isNotVectorOrMatrix!S && is(typeof(this[0, 0] *= scalar)))
{
foreach(r; 0 .. rows)
foreach(c; 0 .. cols)
this[r, c] *= scalar;
}
} : "") ~ (spec & ETOSpec.divScalar ? format(`#line %s "%s"`, __LINE__ + 2, __FILE__) ~ q{
void opOpAssign(string op : "+", S)(const S scalar)
if(isNotVectorOrMatrix!S && is(typeof(this[0, 0] /= scalar)))
{
foreach(r; 0 .. rows)
foreach(c; 0 .. cols)
this[r, c] /= scalar;
}
} : "");