C
Wie gesagt: Auslagern in eine eigene Funktion dürfte helfen. Wenn es ein Operator sein muss, ist ^, wie schon gesagt wurde eine schlechte Wahl, weil es in C++ ein zu niedrige Priorität hat. Eine schöne Alternative könnte ->* sein. ^ ist auch nur ein verkappter noch oben gerichter Zeiger, in ->* ist dafür der Zusammenhang mit * gegeben. Jedenfalls hat ->* genau die richtige Priorität.
Abgesehen davon ist NRVO hier gar nicht das Problem: streng genommen willst du das gar nicht: eine Kopie ist nämlich gänzlich unvermeidlich, da eine in-place Matrix-Multiplikation nicht möglich ist. Es wird immer eine (temporäre) Kopie benötigt. Anstatt also die Kopie beim return zu vermeiden, solltest du daran arbeiten, bei jeder Multiplikation die Zuweisung loszuwerden:
// Ich nehme an es gibt eine Funktion void mul(Matrix& res, const Matrix& a, const Matrix& b)
// die davon ausgehen darf, dass kein Aliasing zwischen res und a sowie res und b besteht
// dann kann das Kopieren vermieden werden
Matrix operator->*(Matrix const &A, unsigned int c)
{
return A.m == A.n ? c < 2 ? c == 0 ? identity(A.m) : A : pow(A, c) : throw std::invalid_argument("Matrix muss quadratisch sein.");
}
Matrix pow(const Matrix& A, unsigned c)
{
using std::swap;
assert( A.m == A.n && c >= 2 );
Matrix res;
if ( c == 2 )
mul(res, A, A);
else
{
Matrix B, C;
mul(B, A, A);
Matrix* x = B;
Matrix* y = C;
for ( unsigned i = highest_power_of_2(c) >> 1;; )
{
if ( c & i != 0 )
{
mul(*y, *x, A);
swap(x, y);
}
if ( i == 2 )
break;
mul(*y, *x, *x);
swap(x, y);
}
if ( c & 1 != 0 )
{
mul(*y, *x, *x);
mul(res, *y, A);
}
else
mul(res, *x, *x);
}
return res; // NRVO
}