RosettaCodeData/Task/Matrix-exponentiation-operator/D/matrix-exponentiation-operator.d

76 lines
2.2 KiB
D
Raw Permalink Normal View History

2015-02-20 00:35:01 -05:00
import std.stdio, std.string, std.math, std.array, std.algorithm;
2013-04-10 21:29:02 -07:00
struct SquareMat(T = creal) {
2013-10-27 22:24:23 +00:00
public static string fmt = "%8.3f";
private alias TM = T[][];
2013-04-10 21:29:02 -07:00
private TM a;
2015-02-20 00:35:01 -05:00
public this(in size_t side) pure nothrow @safe
2013-04-10 21:29:02 -07:00
in {
assert(side > 0);
} body {
a = new TM(side, side);
}
2015-02-20 00:35:01 -05:00
public this(in TM m) pure nothrow @safe
2013-04-10 21:29:02 -07:00
in {
assert(!m.empty);
2015-02-20 00:35:01 -05:00
assert(m.all!(row => row.length == m.length)); // Is square.
2013-04-10 21:29:02 -07:00
} body {
2015-02-20 00:35:01 -05:00
// 2D dup.
2013-04-10 21:29:02 -07:00
a.length = m.length;
2013-10-27 22:24:23 +00:00
foreach (immutable i, const row; m)
2015-02-20 00:35:01 -05:00
a[i] = row.dup;
2013-04-10 21:29:02 -07:00
}
2015-02-20 00:35:01 -05:00
string toString() const @safe {
2013-10-27 22:24:23 +00:00
return format("<%(%(" ~ fmt ~ ", %)\n %)>", a);
2013-04-10 21:29:02 -07:00
}
2015-02-20 00:35:01 -05:00
public static SquareMat identity(in size_t side) pure nothrow @safe {
auto m = SquareMat(side);
foreach (immutable r, ref row; m.a)
2013-10-27 22:24:23 +00:00
foreach (immutable c; 0 .. side)
2015-02-20 00:35:01 -05:00
row[c] = (r == c) ? 1+0i : 0+0i;
2013-04-10 21:29:02 -07:00
return m;
}
public SquareMat opBinary(string op:"*")(in SquareMat other)
2015-02-20 00:35:01 -05:00
const pure nothrow @safe in {
2013-04-10 21:29:02 -07:00
assert (a.length == other.a.length);
} body {
2015-02-20 00:35:01 -05:00
immutable side = other.a.length;
auto d = SquareMat(side);
2013-10-27 22:24:23 +00:00
foreach (immutable r; 0 .. side)
foreach (immutable c; 0 .. side) {
2015-02-20 00:35:01 -05:00
d.a[r][c] = 0+0i;
2013-10-27 22:24:23 +00:00
foreach (immutable k, immutable ark; a[r])
2013-04-10 21:29:02 -07:00
d.a[r][c] += ark * other.a[k][c];
}
return d;
}
2015-02-20 00:35:01 -05:00
public SquareMat opBinary(string op:"^^")(int n) // The task part.
const pure nothrow @safe in {
2013-04-10 21:29:02 -07:00
assert(n >= 0, "Negative exponent not implemented.");
} body {
auto sq = SquareMat(this.a);
auto d = SquareMat.identity(a.length);
for (; n > 0; sq = sq * sq, n >>= 1)
if (n & 1)
d = d * sq;
return d;
}
}
void main() {
2013-10-27 22:24:23 +00:00
alias M = SquareMat!();
2015-02-20 00:35:01 -05:00
enum real q = 0.5.sqrt;
2013-10-27 22:24:23 +00:00
immutable m = M([[ q + 0*1.0Li, q + 0*1.0Li, 0.0L + 0.0Li],
[0.0L - q*1.0Li, 0.0L + q*1.0Li, 0.0L + 0.0Li],
[0.0L + 0.0Li, 0.0L + 0.0Li, 0.0L + 1.0Li]]);
2013-04-10 21:29:02 -07:00
M.fmt = "%5.2f";
2013-10-27 22:24:23 +00:00
foreach (immutable p; [0, 1, 23, 24])
2013-04-10 21:29:02 -07:00
writefln("m ^^ %d =\n%s", p, m ^^ p);
}