1 #ifndef CPPLATEX_LATEX_HPP
2 #define CPPLATEX_LATEX_HPP
12 constexpr
const static char* oparen =
"\\left(";
13 constexpr
const static char* cparen =
"\\right)";
14 constexpr
const static char* obracket =
"\\left[";
15 constexpr
const static char* cbracket =
"\\right]";
16 constexpr
const static char* obrace =
"\\left{";
17 constexpr
const static char* cbrace =
"\\right}";
27 constexpr
const static char* open =
"";
28 constexpr
const static char* close =
"";
33 constexpr
const static char* open =
"\\normal{";
34 constexpr
const static char* close =
"}";
39 constexpr
const static char* open =
"\\textit{";
40 constexpr
const static char* close =
"}";
45 constexpr
const static char* open =
"\\textbf{";
46 constexpr
const static char* close =
"}";
51 constexpr
const static char* open =
"\\underline{";
52 constexpr
const static char* close =
"}";
61 constexpr
const static char* open =
"\\tiny{";
62 constexpr
const static char* close =
"}";
67 constexpr
const static char* open =
"\\small{";
68 constexpr
const static char* close =
"}";
73 constexpr
const static char* open =
"\\large{";
74 constexpr
const static char* close =
"}";
79 constexpr
const static char* open =
"\\Large{";
80 constexpr
const static char* close =
"}";
85 constexpr
const static char* open =
"\\LARGE{";
86 constexpr
const static char* close =
"}";
91 constexpr
const static char* open =
"\\huge{";
92 constexpr
const static char* close =
"}";
97 constexpr
const static char* open =
"\\Huge{";
98 constexpr
const static char* close =
"}";
109 template <
typename Style=
style::None,
typename... Rest>
114 Text(
const char* t) : raw(std::string(t)) {}
115 Text(
const std::string& t) : raw(t) {}
117 std::string to_string()
const {
118 std::stringstream ss;
122 friend std::ostream& operator<<(std::ostream& os,
const Text& t) {
127 void build(std::ostream& ss)
const {
128 print_open(ss, Style::open, Rest::open...);
132 print_close(ss, Style::close, Rest::close...);
136 template <
typename First,
typename... T>
137 void print_open(std::ostream& ss, First f)
const { ss << f; }
139 template <
typename First,
typename... T>
140 void print_open(std::ostream& ss, First f, T... rest)
const {
142 print_open(ss, rest...);
145 template <
typename First,
typename... T>
146 void print_close(std::ostream& ss, First f)
const { ss << f; }
148 template <
typename First,
typename... T>
149 void print_close(std::ostream& ss, First f, T... rest)
const {
150 print_close(ss, rest...);
178 template <
typename T>
auto to_string_impl(
int) -> decltype(std::declval<T>().to_string(), std::true_type{});
179 template <
typename T>
auto to_string_impl(...) -> std::false_type;
180 template <
typename T>
using can_stringify = decltype(to_string_impl<T>(0));
185 template <
typename T>
auto latex_impl(
int) -> decltype(std::declval<T>().latex(), std::true_type{});
186 template <
typename T>
auto latex_impl(...) -> std::false_type;
187 template <
typename T>
using can_latex = decltype(latex_impl<T>(0));
191 namespace listtypes {
195 constexpr
const static char* open =
"\\begin{enumerate}";
196 constexpr
const static char* close =
"\\end{enumerate}";
202 constexpr
const static char* open =
"\\begin{itemize}";
203 constexpr
const static char* close =
"\\end{itemize}";
211 template <
typename Style=listtypes::Unordered>
214 enum class EntryType : std::uint8_t {
218 std::vector<EntryType> ordering;
221 std::vector<std::string> items;
222 std::vector<List<Style>> sublists;
228 List<Style>& operator<<(
const char* val) { add(std::string(val));
return *
this; }
229 List<Style>& operator<<(
const std::string& val) { add(val);
return *
this; }
231 List<Style>& operator<<(List<Style>& val) { add_sublist(val);
return *
this; }
232 List<Style>& operator<<(const List<Style>& val) { add_sublist(val);
return *
this; }
236 typename =
typename std::enable_if<
237 can_stringify<T>::value
242 List<Style>& operator<<(
const T& val) { add(val.to_string());
return *
this; }
244 template <
typename T>
245 typename std::enable_if<
249 operator<<(
const T& val) { add(val.latex());
return *
this; }
251 void add(
const std::string& str) {
252 items.push_back(str);
253 ordering.push_back(EntryType::String);
257 sublists.push_back(list);
258 ordering.push_back(EntryType::Sublist);
265 std::string to_string()
const {
266 std::stringstream ss;
271 friend std::ostream& operator<<(std::ostream& os,
List& list) { list.build(os);
return os; }
273 void build(std::ostream& os, std::size_t depth = 1)
const {
274 auto itemit = items.begin();
275 auto subit = sublists.begin();
277 std::stringstream prefix;
278 for (
auto i = 1u; i < depth; ++i) { prefix <<
"\t"; }
280 os << prefix.str() << Style::open << std::endl;
281 for (
auto& type : ordering) {
283 case EntryType::String:
284 if (itemit != items.end()) {
285 os << prefix.str() <<
"\t" <<
"\\item " << *itemit << std::endl;
288 throw std::runtime_error(
"attempted to output a list item, but no items remaining.");
292 case EntryType::Sublist:
293 if (subit != sublists.end()) {
294 (*subit).build(os, depth+1);
297 throw std::runtime_error(
"attempted to output a sublist item, but no sublists remaining.");
302 os << prefix.str() << Style::close << std::endl;
320 std::vector<std::string> content;
323 Subsection(
const std::string& title) : title(title) {}
325 Subsection& operator<<(
const char* val) {content.push_back(std::string(val));
return *
this;}
326 Subsection& operator<<(
const std::string& val) {content.push_back(val);
return *
this;}
328 template <typename T, typename std::enable_if<can_stringify<T>::value,
bool>::type = 0>
329 Subsection& operator<<(
const T& val) { content.push_back(val.to_string());
return *
this; }
331 template <typename T, typename std::enable_if<can_latex<T>::value,
char>::type = 0>
332 Subsection& operator<<(
const T& val) { content.push_back(val.latex());
return *
this; }
334 friend std::ostream& operator<<(std::ostream& os,
const Subsection& sub) {
335 os <<
"\\subsection{" << sub.title <<
"}\n\n";
337 for (
auto& c : sub.content) {
359 std::vector<Subsection> subs;
360 std::vector<std::string> leading_content;
363 Section(
const std::string& title,
bool new_page =
false) : new_page(new_page), title(title) {}
365 Section& operator<<(
const char* val) {leading_content.push_back(std::string(val));
return *
this;}
366 Section& operator<<(
const std::string& val) {leading_content.push_back(val);
return *
this;}
369 template <typename T, typename = typename std::enable_if<can_stringify<T>::value>::type>
370 Section& operator<<(
const T& val) { leading_content.push_back(val.to_string());
return *
this; }
372 void build(std::ostream& os)
const {
374 os <<
"\n\n\\newpage\n\n";
377 os <<
"\\section{" << title <<
"}\n\n";
379 for (
auto& c : leading_content) {
383 for (
auto& s : subs) {
389 std::string latex()
const {
390 std::stringstream ss;
395 friend std::ostream& operator<<(std::ostream& os,
const Section& sect) {
400 void add_subsection(
const Subsection& sub) { *
this << sub; }
409 constexpr
const static char* header =
"article";
410 constexpr
const static bool can_toc =
false;
411 constexpr
const static bool can_subtitle =
false;
418 constexpr
const static char* header =
"report";
419 constexpr
const static bool can_toc =
true;
420 constexpr
const static bool can_subtitle =
true;
427 constexpr
const static char* header =
"book";
428 constexpr
const static bool can_toc =
true;
429 constexpr
const static bool can_subtitle =
true;
446 template<
typename DocType=doctypes::Article, std::u
int8_t font_size = 12>
450 std::string subtitle;
453 std::vector<std::string> imports;
454 std::vector<std::string> leading_contents;
455 std::vector<Section> sections;
462 Document(
const std::string& title,
const std::string& subtitle)
463 : title(title), subtitle(subtitle), use_toc(DocType::can_toc)
467 Document&
use(
const std::string&
import) { imports.push_back(
import);
return *
this; }
477 void write_leading(
const std::string& content) { leading_contents.push_back(content); }
478 void insert(
const Section& sect) { sections.push_back(sect); }
480 Document& operator<<(
const char* val) {
write_leading(std::string(val));
return *
this;}
481 Document& operator<<(
const std::string& val) {
write_leading(val);
return *
this;}
483 Document& operator<<(
const Section& val) {
484 sections.push_back(val);
489 friend std::ostream& operator<<(std::ostream& os,
const Document& doc) { doc.build(os);
return os; }
493 std::stringstream ss;
499 void build(std::ostream& ss)
const {
500 ss <<
"\\documentclass[" << (std::size_t)font_size <<
"pt]{" << DocType::header <<
"}\n"
503 if (DocType::can_subtitle and subtitle.size()) {
504 ss <<
"\\title{" << title <<
" \\\\ " << subtitle <<
"}\n";
506 ss <<
"\\title{" << title <<
"}\n";
510 for (
auto& i : imports) {
511 ss <<
"\\usepackage{" << i <<
"}\n";
515 ss <<
"\\begin{document}\n"
519 << (use_toc ?
"\\tableofcontents\n\n\\newpage\n\n" :
"")
523 for (
auto& c : leading_contents) {
527 for (
auto& s : sections) {
531 ss <<
"\\end{document}\n";
535 using Article = Document<doctypes::Article>;
536 using Report = Document<doctypes::Report>;
537 using Book = Document<doctypes::Book>;
552 constexpr
const static char* open =
"";
553 constexpr
const static char* close =
"";
558 constexpr
const static char* open =
"\\mathnormal{";
559 constexpr
const static char* close =
"}";
564 constexpr
const static char* open =
"\\mathit{";
565 constexpr
const static char* close =
"}";
570 constexpr
const static char* open =
"\\boldsymbol{";
571 constexpr
const static char* close =
"}";
578 template <
typename T>
auto solve_impl(
int) -> decltype(std::declval<T>().solve(), std::true_type{});
579 template <
typename T>
auto solve_impl(...) -> std::false_type;
580 template <
typename T>
using can_solve = decltype(solve_impl<T>(0));
582 template <typename T, typename = typename std::enable_if<can_solve<T>::value>::type>
583 auto reduce(T& val) {
return val.solve(); }
585 template <
typename T>
586 typename std::enable_if<
587 not can_solve<T>::value || std::is_arithmetic<T>::value
590 reduce(T& val) {
return val; }
594 template <
typename LHS,
typename RHS>
class Addition;
596 template <
typename LHS,
typename RHS>
class Fraction;
598 template <
typename LHS,
typename RHS>
class Power;
599 template <
typename Val,
typename Power>
class Root;
600 template <
typename Val,
typename Base>
class Log;
609 template <
typename T>
617 Number(T val) : val(val) {}
619 auto solve() {
return reduce(val); }
621 std::string latex()
const {
622 std::stringstream ss;
627 friend std::ostream& operator<<(std::ostream& os,
const Number& num) { os << num.latex();
return os; }
640 template <
typename T>
641 auto make_num(
const T& val) {
return Number<T>(val); }
646 template <
typename T>
651 Paren(T enc) : enclosed(enc) {}
653 auto solve() {
return reduce(enclosed); }
655 std::string latex()
const {
656 std::stringstream ss;
657 ss << ::latex::oparen << enclosed << ::latex::cparen;
661 friend std::ostream& operator<<(std::ostream& os,
const Paren& par) { os << par.latex();
return os; }
664 template <
typename T>
665 auto make_paren(
const T& val) {
return Paren<T>(val); }
673 template <
typename Numerator=
double,
typename Denominator=Numerator>
680 using NumeratorType = Numerator;
681 using DenominatorType = Denominator;
682 using Self = Fraction<Numerator, Denominator>;
684 Fraction(Numerator num, Denominator den) : num(num), den(den) {}
687 return reduce(num) / reduce(den);
690 std::string latex()
const {
691 std::stringstream ss;
692 ss <<
"\\frac{" << num <<
"}{" << den <<
"}";
696 friend std::ostream& operator<<(std::ostream& os,
const Fraction& frac) { os << frac.latex();
return os; }
698 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
700 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
702 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
704 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
707 template <
typename LHS,
typename RHS>
708 auto make_fraction(
const LHS& lhs,
const RHS& rhs) {
return Fraction<LHS, RHS>(lhs, rhs); }
711 template <
typename LHS,
typename RHS=LHS>
712 class Multiplication {
720 using Self = Multiplication<LHS, RHS>;
722 Multiplication(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) {}
724 auto solve() {
return reduce(lhs) * reduce(rhs); }
725 std::string latex()
const {
726 std::stringstream ss;
727 ss << lhs <<
" * " << rhs;
731 friend std::ostream& operator<<(std::ostream& os,
const Multiplication& mult) { os << mult.latex();
return os; }
733 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
735 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
737 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
739 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
742 template <
typename LHS,
typename RHS>
743 auto make_mult(
const LHS& lhs,
const RHS& rhs) {
return Multiplication<LHS, RHS>(lhs, rhs); }
745 template <
typename LHS,
typename RHS=LHS>
754 using Self = Addition<LHS, RHS>;
756 Addition(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) {}
758 auto solve() {
return reduce(lhs) + reduce(rhs); }
759 std::string latex()
const {
760 std::stringstream ss;
761 ss << lhs <<
" + " << rhs;
765 friend std::ostream& operator<<(std::ostream& os,
const Addition& add) { os << add.latex();
return os; }
767 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
769 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
771 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
773 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
776 template <
typename LHS,
typename RHS>
777 auto make_add(
const LHS& lhs,
const RHS& rhs) {
return Addition<LHS, RHS>(lhs, rhs); }
779 template <
typename LHS,
typename RHS=LHS>
788 using Self = Subtraction<LHS, RHS>;
790 Subtraction(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) {}
792 auto solve() {
return reduce(lhs) - reduce(rhs); }
793 std::string latex()
const {
794 std::stringstream ss;
795 ss << lhs <<
" - " << rhs;
799 friend std::ostream& operator<<(std::ostream& os,
const Subtraction& sub) { os << sub.latex();
return os; }
801 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
803 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
805 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
807 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
810 template <
typename LHS,
typename RHS>
811 auto make_sub(
const LHS& lhs,
const RHS& rhs) {
return Subtraction<LHS, RHS>(lhs, rhs); }
815 template <
typename LHS,
typename RHS=LHS>
824 using Self = Power<LHS, RHS>;
826 Power(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) {}
828 auto solve() { return ::pow(reduce(lhs), reduce(rhs)); }
830 std::string latex()
const {
831 std::stringstream ss;
832 ss <<
"{" << ::latex::oparen << lhs << ::latex::cparen <<
"}^{" << rhs <<
"}";
836 friend std::ostream& operator<<(std::ostream& os,
const Power& expo) { os << expo.latex();
return os; }
838 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
840 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
842 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
844 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
847 template <
typename LHS,
typename RHS>
848 auto make_pow(
const LHS& lhs,
const RHS& rhs) {
return Power<LHS, RHS>(lhs, rhs); }
852 template <
typename RHS>
863 auto solve() { return ::exp(reduce(rhs)); }
865 std::string latex()
const {
866 std::stringstream ss;
868 ss <<
"\\mathit{e}^{" << ::latex::oparen << rhs << ::latex::cparen <<
"}";
872 friend std::ostream& operator<<(std::ostream& os,
const Exponent& expo) { os << expo.latex();
return os; }
883 template <
typename RHS>
888 template <
typename Val,
typename Pow=Val>
898 using Self = Root<Val, Pow>;
900 Root(Val val, Pow base) : val(val), base(base) {}
902 auto solve() { return ::pow(reduce(val), ((
double)1.0)/reduce(base)); }
904 std::string latex()
const {
905 std::stringstream ss;
906 ss <<
'\\' <<
"sqrt";
907 if (reduce(base) != 2) { ss <<
"[" << base <<
"]"; }
908 ss <<
"{" << val <<
"}";
912 friend std::ostream& operator<<(std::ostream& os,
const Root& r) { os << r.latex();
return os; }
914 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
916 template <
typename InnerPower> Log<Self, InnerPower> log() {
return Log<Self, InnerPower>(*this); }
918 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
920 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
923 template <
typename Val,
typename Base=Val>
924 auto make_root(
const Val& val,
const Base& base) {
return Root<Val, Base>(val, base); }
928 template <
typename Val,
typename Base=Val>
936 using BaseType = Base;
937 using Self = Root<Val, Base>;
939 Log(Val val, Base base) : val(val), base(base) {}
941 auto solve() { return ::log(reduce(val)) / ::log(base); }
942 std::string latex()
const {
943 std::stringstream ss;
944 ss <<
'\\' <<
"log_{" << base <<
"}{" << oparen << val << cparen <<
"}";
948 friend std::ostream& operator<<(std::ostream& os,
const Log& loga) { os << loga.latex();
return os;}
950 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
952 template <
typename InnerBase> Log<Self, Base> log() {
return Log<Self, InnerBase>(*this); }
954 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
956 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
959 template <
typename Val,
typename Base>
960 auto make_log(
const Val& val,
const Base& base) {
return Log<Val, Base>(val, base); }
964 template <
typename Val>
971 using Self = NaturalLog<Val>;
973 NaturalLog(Val val) : val(val) {}
975 auto solve() { return ::log(reduce(val)); }
976 std::string latex()
const {
977 std::stringstream ss;
978 ss <<
"\\ln{" << oparen << val << cparen <<
"}";
982 friend std::ostream& operator<<(std::ostream& os,
const NaturalLog& loga) { os << loga.latex();
return os;}
984 template <
typename T> Power<Self, T> pow(
const T& power) {
return Power<Self, T>(*
this, power); }
986 template <
typename Base> Log<Self, Base> log(Base base) {
return Log<Self, Base>(*
this, base); }
988 NaturalLog<Self> ln() {
return NaturalLog<Self>(*this); }
990 Root<Self, int> sqrt() {
return Root<Self, int>(*
this, 2); }
993 template <
typename Val>
994 auto make_ln(
const Val& val) {
return NaturalLog<Val>(val); }
1002 template<
typename LHS,
typename RHS>
1009 constexpr
const static char* open_context =
"\\begin{equation}";
1010 constexpr
const static char* close_context =
"\\end{equation}";
1013 using LHSType = LHS;
1014 using RHSType = RHS;
1016 Equation(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) {}
1018 Equation(
const std::string& label, LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs), label(label) {}
1020 void insert_label(std::ostream& os)
const {
1022 os <<
"\\label{eq:" << label <<
"}\n";
1038 std::stringstream ss;
1042 ss << lhs <<
" = " << rhs <<
"\n";
1044 ss << close_context <<
"\n";
1048 friend std::ostream& operator<<(std::ostream& os,
const Equation& eq) { os << eq.
latex();
return os; }
1051 template <
typename LHS,
typename RHS>
1052 auto make_eqn(
const LHS& lhs,
const RHS& rhs) {
return Equation<LHS, RHS>(lhs, rhs); }
1055 template <
typename LHS,
typename... Steps>
1061 constexpr
const static char* open_context =
"\\begin{equation}";
1062 constexpr
const static char* close_context =
"\\end{equation}";
1063 constexpr
const static char* split_eq =
" & = ";
1065 template <
typename First,
typename... T>
1066 void print_steps(std::ostream& os, First& f, T... rest) {
1067 os << split_eq << f <<
"\\\\\n";
1068 print_steps(os, rest...);
1071 template <
typename First,
typename... T>
1072 void print_steps(std::ostream& os, First& f) {
1073 os << split_eq << f <<
"\n";
1078 std::stringstream ss;
1079 ss << open_context <<
"\n";
1081 ss <<
"\\begin{split}\n";
1084 print_steps(ss, steps...);
1086 ss <<
"\\end{split}\n";
1087 ss << close_context <<
"\n";
1092 std::string latex()
const {
return eqn; }
1094 friend std::ostream& operator<<(std::ostream& os,
const AlignedEquation& eq) { os << eq.latex();
return os;}
1097 template <
typename LHS,
typename... Steps>
1098 auto make_aligned_eqn(
const LHS& lhs,
const Steps... steps) {
return AlignedEquation<LHS, Steps...>(lhs, steps...); }
1108 template <
typename T=std::
string>
1113 Variable(
const T& name) : name(name) {}
1116 std::stringstream ss;
1117 ss <<
"attempted to solve an equation containing variable '" << name <<
"'\n";
1118 throw std::runtime_error(ss.str());
1121 std::string latex()
const {
1122 std::stringstream ss;
1127 friend std::ostream& operator<<(std::ostream& os,
const Variable& var) {
1133 template <
typename T,
typename StrType=std::
string>
1144 ValuedVariable(
const T& val,
const StrType& name,
bool use_name=
true)
1145 : use_name(use_name), val(val), name(name)
1148 auto solve() {
return reduce(val); }
1150 std::string latex()
const {
1151 std::stringstream ss;
1160 friend std::ostream& operator<<(std::ostream& os,
const ValuedVariable& var) {
1174 template <
typename Upper,
typename Lower=Upper>
1183 std::stringstream ss;
1184 ss <<
"attempted to solve an equation containing variable '" << upper <<
"_" << lower <<
"'\n";
1185 throw std::runtime_error(ss.str());
1188 std::string latex()
const {
1189 std::stringstream ss;
1190 ss << upper <<
"_{" << lower <<
"}";
1202 template <
typename Val>
1208 using ValType = Val;
1211 Sin(Val val) : val(val) {}
1213 auto solve() { return ::sin(reduce(val)); }
1214 std::string latex()
const {
1215 std::stringstream ss;
1216 ss <<
"\\sin{" << latex::oparen << val << latex::cparen <<
"}";
1220 friend std::ostream& operator<<(std::ostream& os,
const Sin& s) { os << s.latex();
return os;}
1231 template <
typename Val>
1232 auto make_sin(
const Val& val) {
return Sin<Val>(val); }
1236 template <
typename Val>
1242 using ValType = Val;
1245 Cos(Val val) : val(val) {}
1247 auto solve() { return ::sin(reduce(val)); }
1248 std::string latex()
const {
1249 std::stringstream ss;
1250 ss <<
"\\cos{" << latex::oparen << val << latex::cparen <<
"}";
1254 friend std::ostream& operator<<(std::ostream& os,
const Cos& s) { os << s.latex();
return os;}
1265 template <
typename Val>
1266 auto make_cos(
const Val& val) {
return Cos<Val>(val); }
1270 template <
typename Val>
1276 using ValType = Val;
1279 Tan(Val val) : val(val) {}
1281 auto solve() { return ::sin(reduce(val)); }
1282 std::string latex()
const {
1283 std::stringstream ss;
1284 ss <<
"\\tan{" << latex::oparen << val << latex::cparen <<
"}";
1288 friend std::ostream& operator<<(std::ostream& os,
const Tan& s) { os << s.latex();
return os;}
1299 template <
typename Val>
1300 auto make_tan(
const Val& val) {
return Tan<Val>(val); }
1318 typename =
typename std::enable_if<
1319 latex::math::can_solve<T>::value ||
1320 latex::math::can_solve<L>::value
1330 typename =
typename std::enable_if<
1331 latex::math::can_solve<T>::value ||
1332 latex::math::can_solve<L>::value
1342 typename =
typename std::enable_if<
1343 latex::math::can_solve<T>::value ||
1344 latex::math::can_solve<L>::value
1353 typename =
typename std::enable_if<
1354 latex::math::can_solve<T>::value ||
1355 latex::math::can_solve<L>::value