/// <summary> /// Creates a Tensor from an Abstraction. /// The difference with Elementwise.Create is that we reuse the existing arrays. /// </summary> private Tensor <Type> Lift(Scalar <Type> expr) { if (expr == this.Abstraction) { return(this); } var result = Vars.FirstOrDefault(e => e == expr); if (result != null) { return(Inputs[Array.IndexOf(Vars, expr)]); } // HACK: here the `Clone` only works on some specific cases. switch (expr) { case Scalar <Type> .Binary binary: return(Op.Apply(Lift(binary.x), Lift(binary.y), (_x, _y) => binary.Clone(_x, _y))); case Scalar <Type> .Unary unary: return(Op.Apply(Lift(unary.x), _x => unary.Clone(_x))); case Scalar <Type> .Const cst: return(Op.ConstLike(expr, this)); default: throw new NotImplementedException(); } }
internal static Tensor <Type> Create(Tensor <Type> x, Func <Scalar <Type>, Scalar <Type> > f) { if (x is Fill <Type> ) { var fill = (Fill <Type>)x; return(Op.ConstLike(f(fill.x), fill)); } else { var _x = new Scalar <Type> .Var($"_x{x0++}"); return(Create(new[] { x }, new[] { _x }, f(_x))); } }