diff --git a/source/rk/tautodiff/aux/tape.d b/source/rk/tautodiff/aux/tape.d index 374cd12..3ee5ca7 100644 --- a/source/rk/tautodiff/aux/tape.d +++ b/source/rk/tautodiff/aux/tape.d @@ -30,7 +30,7 @@ class Tape /// Update tape elements values starting from the begining of the tape void update() { - foreach (v; values) v.update(); + foreach (ref v; values) v.update(); } /// Locks the tape. Tape can only be unlocked with `reset()` afterwards. @@ -42,5 +42,61 @@ class Tape bool isLocked() { return this.locked; } + + // Push back a single value + void pushBack(Value v) + { + this.values ~= v; + } + + /// Push back values + void pushBack(Value[] vs) + { + this.values ~= vs; + } + + /// Append a single value + void opOpAssign(string op: "~")(Value v) + { + this.pushBack(v); + } + + /// Append values + void opOpAssign(string op: "~")(Value[] vs) + { + this.pushBack(vs); + } } +unittest +{ + // init + auto tape = new Tape(); + assert(tape.values == []); + assert(tape.values.length == 0); + assert(tape.locked == false); + assert(!tape.isLocked); + + // d = a * b - c + auto a = 5.value; + auto b = 10.value; + auto c = 25.value; + auto d = a * b; + auto e = d - c; + assert(e.data == 25); + + // push + tape.pushBack(a); + tape ~= b; + tape ~= [c, d, e]; + assert(tape.values == [a, b, c, d, e]); + assert(tape.values.length == 5); + assert(tape.lastValue.data == 25); + + // modify value + a.data = 6; + + // update tape + tape.update(); + assert(tape.lastValue.data == 35); +} diff --git a/source/rk/tautodiff/core/value.d b/source/rk/tautodiff/core/value.d index 2f463bd..6e76066 100644 --- a/source/rk/tautodiff/core/value.d +++ b/source/rk/tautodiff/core/value.d @@ -88,7 +88,7 @@ class Value : INeuron /// Update variable value from cached `op` and `parents` information void update() { - if (this.parents[0] && this.parents[1]) + if (this.parents.length == 2 && this.parents[0] && this.parents[1]) { auto lhs = this.parents[0]; auto rhs = this.parents[1]; @@ -171,11 +171,11 @@ class Value : INeuron { static if (op == "+" || op == "-") { - this.reinit(mixin("rhs.data" ~ op ~ "lhs.data"), op[0], [lhs, rhs], &opBackwardAddSub); + this.reinit(mixin("lhs.data" ~ op ~ "rhs.data"), op[0], [lhs, rhs], &opBackwardAddSub); } else static if (op == "*" || op == "/") { - this.reinit(mixin("rhs.data" ~ op ~ "lhs.data"), op[0], [lhs, rhs], &opBackwardMulDiv); + this.reinit(mixin("lhs.data" ~ op ~ "rhs.data"), op[0], [lhs, rhs], &opBackwardMulDiv); } else static assert(0, "Operator <"~op~"> not supported!"); }