std::string DebugString(Multivector<Scalar, Frame, rank> const& multivector) { // This |using| is required for the |Trivector|, since we need an ambiguity // between |geometry::DebugString(R3Element<Scalar> const&)| and // |quantities::DebugString(Scalar const&)| in order for the template magic // to work out. using quantities::DebugString; return DebugString(multivector.coordinates()); }
std::string ToMathematica(Quantity<D> const& quantity) { std::string s = DebugString(quantity); if (IsFinite(quantity)) { s.replace(s.find("e"), 1, "*^"); } std::string const number = ToMathematica(quantity / SIUnit<Quantity<D>>()); std::size_t const split = s.find(" "); std::string const units = Escape(s.substr(split, s.size())); return Apply( "SetPrecision", {Apply("Quantity", {number, units}), "MachinePrecision"}); }
inline std::string ToMathematica(double const& real) { if (std::isinf(real)) { if (real > 0.0) { return "Infinity"; } else { return Apply("Minus", {"Infinity"}); } } else if (std::isnan(real)) { return "Indeterminate"; } else { std::string s = DebugString(real); s.replace(s.find("e"), 1, "*^"); return Apply("SetPrecision", {s, "MachinePrecision"}); } }
std::ostream& operator<<(std::ostream& out, Multivector<Scalar, Frame, rank> const& multivector) { out << DebugString(multivector); return out; }