// L============================================================================= // L This software is distributed under the MIT license. // L Copyright 2021 Péter Kardos // L============================================================================= #pragma once #include "Vector.hpp" #include namespace mathter { enum class eEnclosingBracket { NONE, PARANTHESE, BRACKET, BRACE, }; /// Prints the vector like [1,2,3]. template std::ostream& operator<<(std::ostream& os, const mathter::Vector& v) { os << "["; for (int x = 0; x < Dim; ++x) { os << v(x) << (x == Dim - 1 ? "" : ", "); } os << "]"; return os; } namespace impl { template struct dependent_false { static constexpr bool value = false; }; template constexpr bool dependent_false_v = dependent_false::value; template ::value && std::is_signed::value, int>::type = 0> AritT strtonum(const char* str, const char** end) { AritT value; value = (AritT)strtoll(str, (char**)end, 10); return value; } template ::value && !std::is_signed::value, int>::type = 0> AritT strtonum(const char* str, const char** end) { AritT value; value = (AritT)strtoull(str, (char**)end, 10); return value; } template ::value, int>::type = 0> AritT strtonum(const char* str, const char** end) { AritT value; value = (AritT)strtold(str, (char**)end); return value; } inline const char* StripSpaces(const char* str) { while (*str != '\0' && isspace(*str)) ++str; return str; }; } // namespace impl /// Parses a vector from a string. template Vector strtovec(const char* str, const char** end) { Vector ret; const char* strproc = str; // parse initial bracket if any strproc = impl::StripSpaces(strproc); if (*strproc == '\0') { *end = str; return ret; } char startBracket = *strproc; char endBracket; bool hasBrackets = false; switch (startBracket) { case '(': endBracket = ')'; hasBrackets = true; ++strproc; break; case '[': endBracket = ']'; hasBrackets = true; ++strproc; break; case '{': endBracket = '}'; hasBrackets = true; ++strproc; break; } // parse elements for (int i = 0; i < Dim; ++i) { const char* elemend; T elem = impl::strtonum(strproc, &elemend); if (elemend == strproc) { *end = str; return ret; } else { ret[i] = elem; strproc = elemend; } strproc = impl::StripSpaces(strproc); if (*strproc == ',') { ++strproc; } } // parse ending bracket corresponding to initial bracket if (hasBrackets) { strproc = impl::StripSpaces(strproc); if (*strproc != endBracket) { *end = str; return ret; } ++strproc; } *end = strproc; return ret; } template VectorT strtovec(const char* str, const char** end) { static_assert(traits::IsVector::value, "This type is not a Vector, dumbass."); return strtovec< typename traits::VectorTraits::Type, traits::VectorTraits::Dim, traits::VectorTraits::Packed>(str, end); } template std::ostream& operator<<(std::ostream& os, const Matrix& mat) { os << "["; for (int i = 0; i < mat.Height(); ++i) { for (int j = 0; j < mat.Width(); ++j) { os << mat(i, j) << (j == mat.Width() - 1 ? "" : ", "); } if (i < Rows - 1) { os << "; "; } } os << "]"; return os; } template Matrix strtomat(const char* str, const char** end) { using MatrixT = Matrix; using VectorT = Vector; MatrixT ret; const char* strproc = str; // parse initial bracket if any strproc = impl::StripSpaces(strproc); if (*strproc == '\0') { *end = str; return ret; } char startBracket = *strproc; char endBracket; bool hasBrackets = false; switch (startBracket) { case '(': endBracket = ')'; hasBrackets = true; ++strproc; break; case '[': endBracket = ']'; hasBrackets = true; ++strproc; break; case '{': endBracket = '}'; hasBrackets = true; ++strproc; break; } // parse rows for (int i = 0; i < Rows; ++i) { const char* rowend; VectorT row = strtovec(strproc, &rowend); if (rowend == strproc) { *end = str; return ret; } else { ret.Row(i) = row; strproc = rowend; } strproc = impl::StripSpaces(strproc); if (i < Rows - 1) { if (*strproc == ';') { ++strproc; } else { *end = str; return ret; } } } // parse ending bracket corresponding to initial bracket if (hasBrackets) { strproc = impl::StripSpaces(strproc); if (*strproc != endBracket) { *end = str; return ret; } ++strproc; } *end = strproc; return ret; } template MatrixT strtomat(const char* str, const char** end) { static_assert(traits::IsMatrix::value, "This type if not a matrix, dumbass."); return strtomat< typename traits::MatrixTraits::Type, traits::MatrixTraits::Rows, traits::MatrixTraits::Columns, traits::MatrixTraits::Order, traits::MatrixTraits::Layout, traits::MatrixTraits::Packed>(str, end); } template std::ostream& operator<<(std::ostream& os, const Quaternion& q) { os << "[" << q.Angle() * T(180.0) / T(3.1415926535897932384626) << " deg @ " << q.Axis() << "]"; return os; } } // namespace mathter