diff --git a/doc/fp_utilities/formatting.qbk b/doc/fp_utilities/formatting.qbk new file mode 100644 index 0000000000..05e3a1facf --- /dev/null +++ b/doc/fp_utilities/formatting.qbk @@ -0,0 +1,510 @@ +[section:formatting Numeric Formatters (Pretty Printers)] + +[heading Synopsis] + + #include + + enum output_format_t + { + text_format, + docbook_format, + latex_format, + html_format + }; + + template > + class basic_numeric_printer; + + typedef basic_numeric_printer<> text_printer; + typedef basic_numeric_printer docbook_printer; + typedef basic_numeric_printer latex_printer; + typedef basic_numeric_printer html_printer; + + typedef basic_numeric_printer wtext_printer; + typedef basic_numeric_printer wdocbook_printer; + typedef basic_numeric_printer wlatex_printer; + typedef basic_numeric_printer whtml_printer; + +[heading Description] + +The class `basic_numeric_printer` provides "pretty printing" capabilities for numeric data. +Its use mirrors that of the `iostream` library, but fulfills a very different role: +There is no "input streaming" and the output is human readable--and not intended for machine consumption. + +Supported types are integers, floating point numbers, complex numbers, rationals, polynomials, intervals +and containers thereof(TODO). +Other types, plus all the standard library manipulators can also be streamed to `basic_numeric_printer` +but are simply forwarded to the underlying stream. + +Output formats include plain text (including formatted output to console), Docbook XML markup, HTML markup, and Latex. MathML may come later(TODO). + +Integer values have the same representation as the underlying stream would give them, +but can have styling applied to their XML wrapper in HTML and Docbook output modes. + +Floats in scientific mode are styled somewhat differently from the underlying `iostream`: '''-1.23457×10-24''' +and can be customised to change the default multiplication operator: '''-1.235⋅10-24'''. + +Complex numbers inherit all the properties of floats, and in addition allow the unit "i" to be customised, for example +'''1.23 - 1.23×10-24i''' or +'''1.23 - 1.2345678765⋅10-24'''. + +Polynomials can be polynomials of integers, floats, or complex numbers and inherit all the properties of each of those: +'''(2.4 + 3.25i) - 34.25x + 4.2×10-06ix2 - (5.34×10-67 - 4.65×10-20i)x3'''. + +[import ../../example/formatter_snips.cpp] + +[formatting_eg1] + +[formatting_eg2] + +[formatting_eg3] + +Here's the revised result: + +[$../images/polynomial_latex_2.svg] + + +[h4 Examples:] + +[heading Class `basic_numeric_printer`] + + enum output_format_t + { + text_format, + docbook_format, + latex_format, + html_format + }; + + template > + class basic_numeric_printer + { + basic_numeric_printer(std::basic_ostream& os); + std::basic_ostream& stream(); + }; + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, const Unspecified& data); + + typedef basic_numeric_printer<> text_printer; + typedef basic_numeric_printer docbook_printer; + typedef basic_numeric_printer latex_printer; + typedef basic_numeric_printer html_printer; + + typedef basic_numeric_printer wtext_printer; + typedef basic_numeric_printer wdocbook_printer; + typedef basic_numeric_printer wlatex_printer; + typedef basic_numeric_printer whtml_printer; + +Class `basic_numeric_printer` is a `std::basic_ostream` lookalike which is constructible from an underlying +stream, and has a single public member function which returns a reference to the underlying stream. + +Its usage via `<<` manipulators is identical to that of `std::basic_ostream`: anything that `basic_numeric_printer` doesn't +understand is passed unchanged to the underlying stream, while numeric data alone is intercepted and pretty-formatted. + +[heading Manipulators] + +There are some stream manipulators which are specific to `basic_numeric_printer` and control how the "pretty printing" is conduced: + + enum styling_level_t + { + no_styling = 0, + minimal_styling = 1, + full_styling = 6 + }; + +Controls the level of styling applied to XML based output formats. + +[variablelist + [[no_styling] [As it's name suggests, results in no styling applied to the output.]] + [[minimal_styling] [Adds minimal styling to the output: for Docbook this wraps the number in `...` + and for HTML it adds `...` around each number.]] + [[full_styling] [This is the default. It adds styling around each complete number, plus styling to indicate the type of number, and styling + around some individual components. In HTML, an integer would be formatted as `-23`, + the inner class name changes to "float" or "complex" depending on the number type, and the XML container to `` in Docbook. In addition + complex numbers get the "i" wrapped in `...`.]] +] + + enum multiplyer_t + { + multiply_times = 0, + multiply_dot = 1, + multiply_x = 2 + }; + +Controls the character used for the multiplication symbol: + +[variablelist + [[multiply_times] [The default. Uses the character U+x00D7 (or [^$\times\$] in Latex): \u00D7.]] + [[multiply_dot] [Uses the character U+x22C5 (or [^$\cdot\$] in Latex): \u22C5.]] + [[multiply_x] [Uses a literal `x` character, this is generally not such a good choice, but is the only one available for plain text output.]] +] + + enum imaginary_i_t + { + upright_i = 0, + slanted_i = 1, + doublestruck_i = 2 + }; + +Controls how the imaginary unit is formatted (plain text output ignores this option): + +[variablelist + [[upright_i] [The default. Formats "i" as a regular upright character, this matches "ISO 80000-2:2009, Quantities and units---part2: Mathematical signs and symbols to be used in the natural sciences and technology".]] + [[slanted_i] [Uses an italic character ['"i"], this style has strong historical precedent.]] + [[doublestruck_i] [Uses the double struct letter i: \u2148. This is the form used by Mathematica. This is not available in Latex output.]] +] + + constexpr const unspecified latex_as_equation; + constexpr const unspecified latex_as_text; + +Controls how Latex output is handled: the default is to format all numbers in equation mode, but streaming `latex_as_text` to the stream +will result in numbers being formatted in text mode instead. +Note that even in text mode some entities need to drop into math mode temporarily for example to access symbols such as `\times`. + +[heading Format Gallery] + +The following section (using Docbook output format) illustrates how each of the number categories are formatted with various options: + +[import ../../example/formatter_docbook_output.qbk] + +[integer_formatting_examples] + +[float_formatting_examples] + +[complex_formatting_examples] + +[complex_formatting_examples_2] + +[rational_formatting_examples] + +[polynomial_formatting_examples] + +[table:intervals Interval Values +[[Value][Result]] +[[`boost::math::constants::pi>>()`]['''3.1415926535897932385 ± 6.7762635780344027125×10-21''']] +[[Polynomial of `number>`]['''2 - (1.6666666666666666667 ± 3.3881317890172013563×10-21)x + (0.66666666666666666666 ± 1.6940658945086006781×10-21)x2 + 15x3 + 11x4 - (14.666666666666666667 ± 2.710505431213761085×10-20)x5 - (5.6666666666666666667 ± 1.3552527156068805425×10-20)x6 + (9.3333333333333333334 ± 2.710505431213761085×10-20)x7 + 20x8''']] +] + +[table:misc Misc Types +[[Type][Comments][Result]] +[[cardinal_quadratic_b_spline][Formatted output of this type is primarily for debugging purposes since + despite appearances, only a few terms of the sum are nonzero, since the basis function B_n has compact support.] + ['''-B2(10(x - 5) + 1) + 5×B2(10(x - 5)) + 11×B2(10(x - 5) - 1) + 17×B2(10(x - 5) - 2) + 23×B2(10(x - 5) - 3) + 29×B2(10(x - 5) - 4) + 35×B2(10(x - 5) - 5) + 41×B2(10(x - 5) - 6) + 47×B2(10(x - 5) - 7) + 53×B2(10(x - 5) - 8) + 59×B2(10(x - 5) - 9) + 65×B2(10(x - 5) - 10)''']] +[[cardinal_cubic_b_spline][Formatted output of this type is primarily for debugging purposes since + despite appearances, only a few terms of the sum are nonzero, since the basis function B_n has compact support.] + ['''32 - 33×B3(10(x - 5) + 1) - 27×B3(10(x - 5)) - 21×B3(10(x - 5) - 1) - 15×B3(10(x - 5) - 2) - 9×B3(10(x - 5) - 3) - 3×B3(10(x - 5) - 4) + 3×B3(10(x - 5) - 5) + 9×B3(10(x - 5) - 6) + 15×B3(10(x - 5) - 7) + 21×B3(10(x - 5) - 8) + 27×B3(10(x - 5) - 9) + 33×B3(10(x - 5) - 10)''']] +[[cardinal_quintic_b_spline][Formatted output of this type is primarily for debugging purposes since + despite appearances, only a few terms of the sum are nonzero, since the basis function B_n has compact support.] + ['''-7×B5(10(x - 5) + 2) - B5(10(x - 5) + 3) + 5×B5(10(x - 5) + 4) + 11×B5(10(x - 5) + 5) + 17×B5(10(x - 5) + 6) + 23×B5(10(x - 5) + 7) + 29×B5(10(x - 5) + 8) + 35×B5(10(x - 5) + 9) + 41×B5(10(x - 5) + 10) + 47×B5(10(x - 5) + 11) + 53×B5(10(x - 5) + 12) + 59×B5(10(x - 5) + 13) + 65×B5(10(x - 5) + 14) + 71×B5(10(x - 5) + 15)''']] +[[barycentric_rational][While usefule for debugging purposes, the formatted output can be rather verbose, + users may find it convenient to output to LaTex and cut and paste into an online processor for improved display.] + [Docbook: + + '''P(x)Q(x) ; P(x) = 5.727×-20833.3(x - 0.02) + 5.544×83333.3(x - 0.04) + 5.45×-145833(x - 0.06) + 5.351×166667(x - 0.08) + 5.253×-166667(x - 0.1) + 5.157×166667(x - 0.12) + 5.058×-166667(x - 0.14) + 4.96×161458(x - 0.16) + 4.862×-133333(x - 0.18) + 4.762×70312.5(x - 0.2) + 4.563×-26041.7(x - 0.24) + 4.36×21354.2(x - 0.28) + 4.1584×-20833.3(x - 0.32) + 3.9463×20833.3(x - 0.36) + 3.736×-20833.3(x - 0.4) + 3.5429×20833.3(x - 0.44) + 3.3797×-20833.3(x - 0.48) + 3.2417×20182.3(x - 0.52) + 3.1209×-16666.7(x - 0.56) + 3.0138×8789.06(x - 0.6) + 2.8342×-3255.21(x - 0.68) + 2.6881×2669.27(x - 0.76) + 2.5662×-2604.17(x - 0.84) + 2.4242×2604.17(x - 0.92) + 2.3766×-2604.17(x - 1) + 2.3058×2604.17(x - 1.08) + 2.2458×-2604.17(x - 1.16) + 2.2035×2604.17(x - 1.24) + 2.1661×-2522.79(x - 1.32) + 2.135×2083.33(x - 1.4) + 2.109×-1098.63(x - 1.48) + 2.0697×406.901(x - 1.64) + 2.0466×-333.659(x - 1.8) + 2.0325×325.521(x - 1.96) + 2.0288×-325.521(x - 2.12) + 2.0292×325.521(x - 2.28) + 2.0228×-325.521(x - 2.44) + 2.0124×325.521(x - 2.6) + 2.0065×-325.521(x - 2.76) + 2.0031×325.521(x - 2.92) + 2.0015×-325.521(x - 3.08) + 2.0008×325.521(x - 3.24) + 2.0004×-284.831(x - 3.4) + 2.0002×162.76(x - 3.56) + 2.0001×-40.6901(x - 3.72) ∧ Q(x) = 5.727(x - 0.02) + 5.544(x - 0.04) + 5.45(x - 0.06) + 5.351(x - 0.08) + 5.253(x - 0.1) + 5.157(x - 0.12) + 5.058(x - 0.14) + 4.96(x - 0.16) + 4.862(x - 0.18) + 4.762(x - 0.2) + 4.563(x - 0.24) + 4.36(x - 0.28) + 4.1584(x - 0.32) + 3.9463(x - 0.36) + 3.736(x - 0.4) + 3.5429(x - 0.44) + 3.3797(x - 0.48) + 3.2417(x - 0.52) + 3.1209(x - 0.56) + 3.0138(x - 0.6) + 2.8342(x - 0.68) + 2.6881(x - 0.76) + 2.5662(x - 0.84) + 2.4242(x - 0.92) + 2.3766(x - 1) + 2.3058(x - 1.08) + 2.2458(x - 1.16) + 2.2035(x - 1.24) + 2.1661(x - 1.32) + 2.135(x - 1.4) + 2.109(x - 1.48) + 2.0697(x - 1.64) + 2.0466(x - 1.8) + 2.0325(x - 1.96) + 2.0288(x - 2.12) + 2.0292(x - 2.28) + 2.0228(x - 2.44) + 2.0124(x - 2.6) + 2.0065(x - 2.76) + 2.0031(x - 2.92) + 2.0015(x - 3.08) + 2.0008(x - 3.24) + 2.0004(x - 3.4) + 2.0002(x - 3.56) + 2.0001(x - 3.72)''' + + Latex: + + [$../images/barycentric_latex.svg]]] +] + +[heading Output Format Gallery] + +The above tables of sample output are available in various other formats + +[@../../example/formatter_html_output.html HTML sample page], generated with [@../../example/formatter_html_output.cpp formatter_html_output.cpp]. + +[@../../example/formatter_text_output.txt Plain text sample page], generated with [@../../example/formatter_text_output.cpp formatter_text_output.cpp]. + +[@../../example/formatter_latex_output.tex Latex source output], generated with [@../../example/formatter_latex_output.cpp formatter_latex_output.cpp]. + +[@../../example/formatter_latex_output.pdf Latex PDF output], generated with [@../../example/formatter_latex_output.cpp formatter_latex_output.cpp] and then converted to PDF. + +[heading Extender Manual] + +This component is (somewhat) extendable to other output formats and other numeric types. + +The class `basic_numeric_printer` inherits from `basic_numeric_printer_base` like so: + + template + class basic_numeric_printer : public basic_numeric_printer_base {/*details*/ }; + +The task of enabling a new output format is to define a partial specialisation of `basic_numeric_printer` which inherits from +`basic_numeric_printer_base` and overrides it's virtual member functions to tailor the output. Conversely, the task +of enabling support for a new number type, is to provide a free function `print`: + + template + void print(basic_numeric_printer_base& os, MyNumber const& value); + +Which can be found via ADL, and which calls `basic_numeric_printer_base`'s member functions to +perform the formatted output, it may also make unqualified calls to `print` where the sub-type +is already supported (integers, floats, complex numbers, polynomials). This is prefered to overloading `operator<<` directly, since the +default `operator<<` will handle stream padding (as a result of `std::setw()`) for you. + +Note that it is not required to include the header ``, a simple forward declaration +of `basic_numeric_printer_base` will suffice: + + namespace boost { namespace math{ namespace tools{ template class basic_numeric_printer_base; }}} + +Details of the public interface of `basic_numeric_printer_base` are as follows: + + template + class basic_numeric_printer_base + { + public: + // Manipulator support: + void styling(styling_level_t i); + styling_level_t styling()const; + + void imaginary_style(imaginary_i_t i); + imaginary_i_t imaginary_style()const; + + void multiply(multiplyer_t t); + multiplyer_t multiply()const; + + void parenthesis(std::size_t b); + std::size_t parenthesis()const; + + void show_zero_components(bool b); + bool show_zero_components()const; + + void use_unicode(bool b); + bool use_unicode()const; + + bool latex_as_equation()const; + void latex_as_equation(bool); + + // stream access: + std::basic_ostream& stream(); + + // scoped helper objects + struct scoped_parenthesis + { + scoped_parenthesis(basic_numeric_printer_base* formatter); + ~scoped_parenthesis(); + }; + struct scoped_styling + { + scoped_styling(basic_numeric_printer_base* formatter); + ~scoped_styling(); + }; + struct scoped_prolog + { + scoped_prolog(basic_numeric_printer_base* formatter, const char* number_type); + ~scoped_prolog(); + }; + + // virtual functions overridden in derived classes: + virtual void print_prolog(const char*); + virtual void print_epilog(const char*); + virtual void print_special_character(boost::uint32_t unicode_value); + virtual void print_times(); + virtual void print_superscript(const std::basic_string& s); + virtual void print_imaginary_unit(); + virtual void print_complex_infinity(); + virtual void print_variable(charT c); + virtual void print_name(const std::basic_string& s); + virtual void print_fraction(const std::basic_string& s1, const std::basic_string& s2); + virtual void print_subscript(const std::basic_string& s); + virtual std::unique_ptr clone(std::basic_ostream& os) = 0; + + template + std::basic_string part_as_string(const Value& value); + template + std::basic_string part_as_plain_text(const Value& value); + }; + +Details are as follows: + + void styling(styling_level_t i); + styling_level_t styling()const; + +Gets and sets the XML styling level. + + void imaginary_style(imaginary_i_t i); + imaginary_i_t imaginary_style()const; + +Gets and sets the character used for the imaginary unit /i/. + + void multiply(multiplyer_t t); + multiplyer_t multiply()const; + +Gets and sets the character used as the multiplication symbol. + + void parenthesis(std::size_t b); + std::size_t parenthesis()const; + +Gets and sets the current parenthesis level, should typically only be set via `scoped_parenthesis`. + +Compound types should always check the current parenthesis level and if it is greater than zero, wrap themselves in +parenthesis. They should do this before constructing a `scoped_parenthesis` of course. + + void show_zero_components(bool b); + bool show_zero_components()const; + +Gets and sets whether zero sub-components are displayed or not. + + void use_unicode(bool b); + bool use_unicode()const; + +Gets and sets whether plain text shoud use Unicode output or not: when `true` then the output is UTF-N where +N is either 8, 16 or 32 and is determined by the size of `charT`. + + bool latex_as_equation()const; + void latex_as_equation(bool); + +Gets and sets whether latex output formats numbers using math mode. + + std::basic_ostream& stream(); + +Returns the underlying output stream. + + struct scoped_parenthesis + { + scoped_parenthesis(basic_numeric_printer_base* formatter); + ~scoped_parenthesis(); + }; + +A scoped parenthesis object should be constructed, whenever sub-objects need to wrap themselves in parenthesis if +they themselves contain sub-objects. For example the `print` function for polynomials declares a `scoped_parenthesis` +right at it's start, if the coefficients are "atomic" types such as integers then they ignore the parenthesis level +and are printed normally. Compound coefficients such as complex numbers will make use of the parenthesis level though +and wrap themselves in parenthesis. + + struct scoped_styling + { + scoped_styling(basic_numeric_printer_base* formatter); + ~scoped_styling(); + }; + +XML output will wrap numbers in styling tags - for example `...` in html output. +If the current type being formatted should be treated as a single number then a `scoped_styling` object should be +constructed at the start of the types `print` function. This will then suppress styling tags being added to +any printed sub-objects. + + struct scoped_prolog + { + scoped_prolog(basic_numeric_printer_base* formatter, const char* number_type); + ~scoped_prolog(); + }; + +Any type that provides a `print` function should construct a `scoped_prolog` object at it's start - it calls +`print_prolog` during construction and `print_epilog` during destruction. Set `number_type` to the empty +string if you're printing an expression that contains multiple sub-components, and you're not constructing +a `scoped_styling` object. ie if sub-objects are styled, but this object is not. + + virtual void print_prolog(const char*); + +Prints any prolog to the formatted output - for example styling tags in HTML/XML output. + +`basic_numeric_printer_base<>::print_prolog` does nothing, specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_epilog(const char*); + +Prints any epilog to the formatted output - for example closing styling tags in HTML/XML output. + +`basic_numeric_printer_base<>::print_epilog` does nothing, specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_special_character(boost::uint32_t unicode_value); + +Prints a special math character denoted by it's unicode code point. + +`basic_numeric_printer_base<>::print_special_character` outputs the character as UTF-N where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints the closest plain text approximation, +specializations of `basic_numeric_printer` +override that behaviour according to need. + + + virtual void print_times(); + +Prints the multiplication character. + +`basic_numeric_printer_base<>::print_times` outputs the character as UTF-N where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints an "x", specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_superscript(const std::basic_string& s); + +Prints `s` as superscript. + +`basic_numeric_printer_base<>::print_superscript` outputs the characters as UTF-N superscript where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints a "^" followed by `s`, specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_imaginary_unit(); + +Prints the imaginary unit i. + +`basic_numeric_printer_base<>::print_imaginary_unit` outputs the character as UTF-N where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints a literal "i", specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_complex_infinity(); + +Prints complex infinity. + +`basic_numeric_printer_base<>::print_complex_infinity` outputs the infinity symbol as UTF-N where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints a literal "INFINITY", specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_variable(charT c); + +Prints a character `c` that represents a named variable, typically rendered in italic text. + +`basic_numeric_printer_base<>::print_variable` outputs the character "as is", specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_name(const std::basic_string& s); + +Prints a string name `s` that represents a named quantity, typically rendered in upright (non-italic) text. + +`basic_numeric_printer_base<>::print_variable` outputs the string "as is", specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_fraction(const std::basic_string& s1, const std::basic_string& s2); + +Prints the fraction `s1/s2`. + +`basic_numeric_printer_base<>::print_fraction` outputs the fraction as plain text s1/s2, specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual void print_subscript(const std::basic_string& s); + +Prints `s` as subscript. + +`basic_numeric_printer_base<>::print_subscript` outputs the characters as UTF-N subscript where N is determined by +the size of `charT` if `use_unicode()` is true, otherwise prints a "_" followed by `s`, specializations of `basic_numeric_printer` +override that behaviour according to need. + + virtual std::unique_ptr clone(std::basic_ostream& os); + +Returns a (smart-) pointer to a copy of this object but which uses `os` as the underlying output stream. + +All derived classes must override this method. + + template + std::basic_string part_as_string(const Value& value); + +Helper function. Returns `value` as a string. Uses a copy of `this` which contains the same formatting flags (on both itself and +the std::ostream it points to) but which outputs to a `std::basic_ostringstream` and then returns the result. + +Typically used to format numerator and denominator of a fraction. + + template + std::basic_string part_as_plain_text(const Value& value); + +Helper function. Returns `value` as a string. Differs from `part_as_string` in that it uses a plain text printer +internally with `use_unicode()` set to `false`. + +Typically used to check if a value will be "trivial" such as "1" or "0" once printed to current precision. + +[endsect] [/section:formatting] + + +[/ Copyright 2019 John Maddock. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +] diff --git a/doc/images/barycentric_latex.svg b/doc/images/barycentric_latex.svg new file mode 100644 index 0000000000..a189eada26 --- /dev/null +++ b/doc/images/barycentric_latex.svg @@ -0,0 +1,5236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/console1.png b/doc/images/console1.png new file mode 100644 index 0000000000..10f1dc53a7 Binary files /dev/null and b/doc/images/console1.png differ diff --git a/doc/images/console2.png b/doc/images/console2.png new file mode 100644 index 0000000000..77b22cb959 Binary files /dev/null and b/doc/images/console2.png differ diff --git a/doc/images/polynomial_latex_1.svg b/doc/images/polynomial_latex_1.svg new file mode 100644 index 0000000000..558521530f --- /dev/null +++ b/doc/images/polynomial_latex_1.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/polynomial_latex_2.svg b/doc/images/polynomial_latex_2.svg new file mode 100644 index 0000000000..fa55dff20c --- /dev/null +++ b/doc/images/polynomial_latex_2.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/math.qbk b/doc/math.qbk index bd60c40f44..0baee4eb3e 100644 --- a/doc/math.qbk +++ b/doc/math.qbk @@ -569,6 +569,7 @@ and as a CD ISBN 0-9504833-2-X 978-0-9504833-2-0, Classification 519.2-dc22. [include fp_utilities/float_next.qbk] [include fp_utilities/float_comparison.qbk] [include fp_utilities/condition_numbers.qbk] +[include fp_utilities/formatting.qbk] [endmathpart] [mathpart cstdfloat..Specified-width floating-point typedefs] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index fd40f3982d..3f38040f23 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -8,6 +8,9 @@ # bring in the rules for testing import testing ; import ../../config/checks/config : requires ; +using quickbook ; + +path-constant here : . ; project : requirements @@ -147,7 +150,13 @@ test-suite examples : [ run ooura_fourier_integrals_example.cpp : : : [ requires cxx11_hdr_mutex cxx11_lambdas cxx11_inline_namespaces cxx11_auto_declarations ] ] [ run ooura_fourier_integrals_cosine_example.cpp : : : [ requires cxx11_hdr_mutex cxx11_inline_namespaces cxx11_auto_declarations cxx17_std_apply ] ] [ run ooura_fourier_integrals_multiprecision_example.cpp : : : [ check-target-builds ../config//has_float128 "GCC libquadmath and __float128 support" : -lquadmath ] [ requires cxx11_hdr_mutex cxx11_inline_namespaces cxx11_auto_declarations cxx17_std_apply ] ] - + + [ run formatter_latex_output.cpp : $(here)/formatter_latex_output.tex : : [ requires cxx11_constexpr cxx14_variable_templates ] ] + [ run formatter_html_output.cpp : $(here)/formatter_html_output.html : : [ requires cxx11_constexpr cxx14_variable_templates ] ] + [ run formatter_docbook_output.cpp : $(here)/formatter_docbook_output.qbk : : [ requires cxx11_constexpr cxx14_variable_templates ] ] + [ run formatter_text_output.cpp : $(here)/formatter_text_output.txt : : [ requires cxx11_constexpr cxx14_variable_templates ] ] + [ run formatter_barycentric_interpolation_example.cpp : : : [ requires cxx11_constexpr cxx14_variable_templates ] ] + [ run formatter_b_spline_output.cpp : : : [ requires cxx11_constexpr cxx14_variable_templates ] ] ; run root_elliptic_finding.cpp /boost/timer : : : release static [ requires cxx11_unified_initialization_syntax cxx11_defaulted_functions ] freebsd:"-lrt" linux:"-lrt -lpthread" ; @@ -157,3 +166,15 @@ run root_n_finding_algorithms.cpp /boost/timer : : : release static [ req explicit root_elliptic_finding ; explicit root_finding_algorithms ; explicit root_n_finding_algorithms ; + +xml formatting_test : formatter_docbook_output_test.qbk : formatter_docbook_output +; +boostbook standalone + : + formatting_test + : +; + +explicit standalone ; +install pdfinstall : standalone/pdf : . PDF formatting.pdf ; +explicit pdfinstall ; # b2 pdf pdfinstall to do this pdf file copy. diff --git a/example/formatter_b_spline_output.cpp b/example/formatter_b_spline_output.cpp new file mode 100644 index 0000000000..234ad85177 --- /dev/null +++ b/example/formatter_b_spline_output.cpp @@ -0,0 +1,71 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +int main() { + std::vector v(10); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = static_cast(5 + 6 * i); + } + + double step = 0.1; + double a = 5; + { + std::cout << "Quadratic B Spline:\n\n"; + boost::math::interpolators::cardinal_quadratic_b_spline spline(v.data(), v.size(), a, step); + + boost::math::tools::text_printer printer(std::cout); + printer << spline << std::endl << std::endl; + + boost::math::tools::latex_printer lprinter(std::cout); + lprinter << spline << std::endl << std::endl; + + boost::math::tools::html_printer hprinter(std::cout); + hprinter << spline << std::endl << std::endl; + + boost::math::tools::docbook_printer dprinter(std::cout); + dprinter << spline << std::endl << std::endl; + } + { + std::cout << "Cubic B Spline:\n\n"; + boost::math::interpolators::cardinal_cubic_b_spline spline(v.data(), v.size(), a, step); + + boost::math::tools::text_printer printer(std::cout); + printer << spline << std::endl << std::endl; + + boost::math::tools::latex_printer lprinter(std::cout); + lprinter << spline << std::endl << std::endl; + + boost::math::tools::html_printer hprinter(std::cout); + hprinter << spline << std::endl << std::endl; + + boost::math::tools::docbook_printer dprinter(std::cout); + dprinter << spline << std::endl << std::endl; + } + { + std::cout << "Quintic B Spline:\n\n"; + boost::math::interpolators::cardinal_quintic_b_spline spline(v.data(), v.size(), a, step); + + boost::math::tools::text_printer printer(std::cout); + printer << spline << std::endl << std::endl; + + boost::math::tools::latex_printer lprinter(std::cout); + lprinter << spline << std::endl << std::endl; + + boost::math::tools::html_printer hprinter(std::cout); + hprinter << spline << std::endl << std::endl; + + boost::math::tools::docbook_printer dprinter(std::cout); + dprinter << spline << std::endl << std::endl; + } + return 0; +} diff --git a/example/formatter_barycentric_interpolation_example.cpp b/example/formatter_barycentric_interpolation_example.cpp new file mode 100644 index 0000000000..3597942f72 --- /dev/null +++ b/example/formatter_barycentric_interpolation_example.cpp @@ -0,0 +1,95 @@ + +// Copyright Nick Thompson, 2017 + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt). + +#include +#include +#include +#include + +//[barycentric_rational_example + +/*` +This example shows how to use barycentric rational interpolation, using Walter Kohn's classic paper +"Solution of the Schrodinger Equation in Periodic Lattices with an Application to Metallic Lithium" +In this paper, Kohn needs to repeatedly solve an ODE (the radial Schrodinger equation) given a potential +which is only known at non-equally samples data. + +If he'd only had the barycentric rational interpolant of Boost.Math! + +References: Kohn, W., and N. Rostoker. "Solution of the Schrodinger equation in periodic lattices with an application to metallic lithium." Physical Review 94.5 (1954): 1111. +*/ + +#include + +int main() +{ + // The lithium potential is given in Kohn's paper, Table I: + std::vector r(45); + std::vector mrV(45); + + r[0] = 0.02; mrV[0] = 5.727; + r[1] = 0.04, mrV[1] = 5.544; + r[2] = 0.06, mrV[2] = 5.450; + r[3] = 0.08, mrV[3] = 5.351; + r[4] = 0.10, mrV[4] = 5.253; + r[5] = 0.12, mrV[5] = 5.157; + r[6] = 0.14, mrV[6] = 5.058; + r[7] = 0.16, mrV[7] = 4.960; + r[8] = 0.18, mrV[8] = 4.862; + r[9] = 0.20, mrV[9] = 4.762; + r[10] = 0.24, mrV[10] = 4.563; + r[11] = 0.28, mrV[11] = 4.360; + r[12] = 0.32, mrV[12] = 4.1584; + r[13] = 0.36, mrV[13] = 3.9463; + r[14] = 0.40, mrV[14] = 3.7360; + r[15] = 0.44, mrV[15] = 3.5429; + r[16] = 0.48, mrV[16] = 3.3797; + r[17] = 0.52, mrV[17] = 3.2417; + r[18] = 0.56, mrV[18] = 3.1209; + r[19] = 0.60, mrV[19] = 3.0138; + r[20] = 0.68, mrV[20] = 2.8342; + r[21] = 0.76, mrV[21] = 2.6881; + r[22] = 0.84, mrV[22] = 2.5662; + r[23] = 0.92, mrV[23] = 2.4242; + r[24] = 1.00, mrV[24] = 2.3766; + r[25] = 1.08, mrV[25] = 2.3058; + r[26] = 1.16, mrV[26] = 2.2458; + r[27] = 1.24, mrV[27] = 2.2035; + r[28] = 1.32, mrV[28] = 2.1661; + r[29] = 1.40, mrV[29] = 2.1350; + r[30] = 1.48, mrV[30] = 2.1090; + r[31] = 1.64, mrV[31] = 2.0697; + r[32] = 1.80, mrV[32] = 2.0466; + r[33] = 1.96, mrV[33] = 2.0325; + r[34] = 2.12, mrV[34] = 2.0288; + r[35] = 2.28, mrV[35] = 2.0292; + r[36] = 2.44, mrV[36] = 2.0228; + r[37] = 2.60, mrV[37] = 2.0124; + r[38] = 2.76, mrV[38] = 2.0065; + r[39] = 2.92, mrV[39] = 2.0031; + r[40] = 3.08, mrV[40] = 2.0015; + r[41] = 3.24, mrV[41] = 2.0008; + r[42] = 3.40, mrV[42] = 2.0004; + r[43] = 3.56, mrV[43] = 2.0002; + r[44] = 3.72, mrV[44] = 2.0001; + + // Now we want to interpolate this potential at any r: + boost::math::barycentric_rational b(r.data(), mrV.data(), r.size()); + + boost::math::tools::text_printer printer(std::cout); + printer << b << std::endl << std::endl; + + boost::math::tools::latex_printer lprinter(std::cout); + lprinter << b << std::endl << std::endl; + + boost::math::tools::html_printer hprinter(std::cout); + hprinter << b << std::endl << std::endl; + + boost::math::tools::docbook_printer dprinter(std::cout); + dprinter << b << std::endl << std::endl; + +} diff --git a/example/formatter_docbook_output.cpp b/example/formatter_docbook_output.cpp new file mode 100644 index 0000000000..7a07db009d --- /dev/null +++ b/example/formatter_docbook_output.cpp @@ -0,0 +1,203 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +void print(std::ostream& os) +{ + boost::math::tools::docbook_printer printer(os); + + printer << "[template integer_formatting_examples[]\n"; + + int ival = 0; + printer << "[table:integer_fmt_examples Basic Integer Values\n[[Value][Base][Result]]\n"; + printer.stream() << "[[" << ival << "][default]['''"; + printer << ival << "''']]\n"; + ival = -23; + printer.stream() << "[[" << ival << "][default]['''"; + printer << ival << "''']]\n"; + ival = 23; + printer.stream() << std::dec << "[[" << ival << "][hex]['''"; + printer << std::hex << ival << "''']]\n"; + printer.stream() << std::dec << "[[" << ival << "][oct]['''"; + printer << std::oct << ival << "''']]\n]\n]\n" << std::dec; + + printer << "[template float_formatting_examples[]\n"; + double fval = 3; + printer << "[table:float_fmt_examples Basic Float Values\n[[Value][Precision][Format][Result]]"; + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = 3.14; + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = -1.2345678765e-24; + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + printer.stream() << "[[" << fval << "][3][scientific]['''"; + printer << std::setprecision(3) << std::scientific << fval << "''']]\n"; + printer.stream() << "[[" << fval << "][3][scientific + multiply_x]['''"; + printer << std::setprecision(3) << std::scientific << boost::math::tools::multiply_x << fval << "''']]\n"; + printer.stream() << "[[" << fval << "][3][scientific + multiply_dot]['''"; + printer << std::setprecision(3) << std::scientific << boost::math::tools::multiply_dot << fval << "''']]\n" << boost::math::tools::multiply_times << std::defaultfloat; + fval = 0; + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = -fval; + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = std::numeric_limits::infinity(); + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = -std::numeric_limits::infinity(); + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = std::numeric_limits::quiet_NaN(); + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + fval = -std::numeric_limits::quiet_NaN(); + printer.stream() << "[[" << fval << "][default][default]['''"; + printer << fval << "''']]\n"; + + printer << "]\n]\n" << std::defaultfloat; + + printer << "[template complex_formatting_examples[]\n"; + std::complex cval(3.25, 4.67); + printer << "[table:complex_fmt_examples Basic Complex Values\n[[Value][Precision][Format][Result]]"; + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = 3.14; + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(1.23, -1.2345678765e-24); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][3][scientific]['''"; + printer << std::scientific << std::setprecision(3) << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][12][default + slanted_i]['''"; + printer << boost::math::tools::slanted_i << std::defaultfloat << std::setprecision(12) << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][12][default + doublestruck_i]['''"; + printer << boost::math::tools::doublestruck_i << std::defaultfloat << std::setprecision(12) << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][12][default + doublestruck_i + multiply_x]['''"; + printer << boost::math::tools::doublestruck_i << std::defaultfloat << std::setprecision(12) << boost::math::tools::multiply_x << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][12][default + doublestruck_i + multiply_dot]['''"; + printer << boost::math::tools::doublestruck_i << std::defaultfloat << std::setprecision(12) << boost::math::tools::multiply_dot << cval << "''']]\n" << boost::math::tools::multiply_times << boost::math::tools::upright_i; + printer << "\n]\n]\n"; + + printer << "[template complex_formatting_examples_2[]\n"; + printer << "[table:complex_fmt_examples Complex Special Values\n[[Value][Precision][Format][Result]]"; + cval = std::complex(0, 0); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][default][show_zero_components]['''"; + printer << boost::math::tools::show_zero_components << cval << "''']]\n" << boost::math::tools::hide_zero_components; + cval = std::complex(2.5, 0); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][default][show_zero_components]['''"; + printer << boost::math::tools::show_zero_components << cval << "''']]\n" << boost::math::tools::hide_zero_components; + cval = std::complex(-2.5, 0); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][default][show_zero_components]['''"; + printer << boost::math::tools::show_zero_components << cval << "''']]\n" << boost::math::tools::hide_zero_components; + cval = std::complex(0, 3.25); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][default][show_zero_components]['''"; + printer << boost::math::tools::show_zero_components << cval << "''']]\n" << boost::math::tools::hide_zero_components; + cval = std::complex(0, -3.25); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + printer.stream() << "[[" << cval << "][default][show_zero_components]['''"; + printer << boost::math::tools::show_zero_components << cval << "''']]\n" << boost::math::tools::hide_zero_components; + // Infinites and NaN's: + cval = std::complex(std::numeric_limits::infinity(), 2.5); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(-std::numeric_limits::infinity(), 2.5); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(2.5, std::numeric_limits::infinity()); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(2.5, -std::numeric_limits::infinity()); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(2.5, std::numeric_limits::quiet_NaN()); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(std::numeric_limits::quiet_NaN(), 2.5); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + cval = std::complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity()); + printer.stream() << "[[" << cval << "][default][default]['''"; + printer << cval << "''']]\n"; + + printer << "\n]\n]\n"; + + printer << "[template rational_formatting_examples[]\n"; + printer << "[table:rat_fmt_examples Rational Values\n[[Value][Result]]\n"; + + boost::rational rat(1, 3); + printer.stream() << "[[" << rat << "]['''"; + printer << rat << "''']]\n"; + rat = -rat; + printer.stream() << "[[" << rat; + printer << "]['''" << rat << "''']]\n"; + rat *= 345634; + rat /= 565; + printer.stream() << "[[" << rat; + printer << "]['''" << rat << "''']]\n"; + rat = 0; + printer.stream() << "[[" << rat; + printer << "]['''" << rat << "''']]\n"; + rat = -23; + printer.stream() << "[[" << rat; + printer << "]['''" << rat << "''']]\n"; + boost::multiprecision::cpp_rational rat2(1); + for (unsigned i = 1; i < 20; i += 2) + { + rat2 *= i; + rat2 /= i + 1; + } + printer.stream() << "[[" << rat2; + printer << "]['''" << rat2 << "''']]\n"; + printer << "\n]\n]\n"; + + + printer << "[template polynomial_formatting_examples[]\n"; + printer << "[table:poly_fmt_examples Polynomial Values\n[[Kind][Result]]"; + boost::math::tools::polynomial poly1 = { 2, -3, 4, 5 }; + printer << "[[Integer]['''" << poly1 << "''']]" << std::endl; + boost::math::tools::polynomial poly2 = { 2.4, -34.25, 4.2e-6, -5.34e-67 }; + printer << "[[Float]['''" << poly2 << "''']]" << std::endl; + boost::math::tools::polynomial > poly3 = { { 2.4, 3.25 }, {-34.25 }, { 0, 4.2e-6 }, { -5.34e-67, 4.65e-20 } }; + printer << "[[Complex]['''" << poly3 << "''']]" << std::endl; + boost::math::tools::polynomial> poly4 = { {2, 3}, {-3, 23}, {4, 56}, {5, 32} }; + printer << "[[Rational]['''" << poly4 << "''']]" << std::endl; + + printer << "\n]\n]\n"; +} + + +int main(int argc, const char* argv[]) +{ + if (argc > 1) + { + std::ofstream ofs(argv[1]); + print(ofs); + } + else + print(std::cout); + return 0; +} diff --git a/example/formatter_docbook_output.qbk b/example/formatter_docbook_output.qbk new file mode 100644 index 0000000000..77f735c0de --- /dev/null +++ b/example/formatter_docbook_output.qbk @@ -0,0 +1,82 @@ +[template integer_formatting_examples[] +[table:integer_fmt_examples Basic Integer Values +[[Value][Base][Result]] +[[0][default]['''0''']] +[[-23][default]['''-23''']] +[[23][hex]['''17''']] +[[23][oct]['''27''']] +] +] +[template float_formatting_examples[] +[table:float_fmt_examples Basic Float Values +[[Value][Precision][Format][Result]][[3][default][default]['''3''']] +[[3.14][default][default]['''3.14''']] +[[-1.23457e-24][default][default]['''-1.23457×10-24''']] +[[-1.23457e-24][3][scientific]['''-1.235×10-24''']] +[[-1.235e-24][3][scientific + multiply_x]['''-1.235x10-24''']] +[[-1.235e-24][3][scientific + multiply_dot]['''-1.235⋅10-24''']] +[[0][default][default]['''0''']] +[[-0][default][default]['''-0''']] +[[inf][default][default]['''''']] +[[-inf][default][default]['''-∞''']] +[[nan][default][default]['''NaN''']] +[[-nan(ind)][default][default]['''NaN''']] +] +] +[template complex_formatting_examples[] +[table:complex_fmt_examples Basic Complex Values +[[Value][Precision][Format][Result]][[(3.25,4.67)][default][default]['''3.25 + 4.67i''']] +[[(3.14,0)][default][default]['''3.14''']] +[[(1.23,-1.23e-24)][default][default]['''1.23 - 1.23×10-24i''']] +[[(1.23,-1.23e-24)][3][scientific]['''1.230×10+00 - 1.235×10-24i''']] +[[(1.230e+00,-1.235e-24)][12][default + slanted_i]['''1.23 - 1.2345678765×10-24i''']] +[[(1.23,-1.2345678765e-24)][12][default + doublestruck_i]['''1.23 - 1.2345678765×10-24''']] +[[(1.23,-1.2345678765e-24)][12][default + doublestruck_i + multiply_x]['''1.23 - 1.2345678765x10-24''']] +[[(1.23,-1.2345678765e-24)][12][default + doublestruck_i + multiply_dot]['''1.23 - 1.2345678765⋅10-24''']] + +] +] +[template complex_formatting_examples_2[] +[table:complex_fmt_examples Complex Special Values +[[Value][Precision][Format][Result]][[(0,0)][default][default]['''0''']] +[[(0,0)][default][show_zero_components]['''0 + 0i''']] +[[(2.5,0)][default][default]['''2.5''']] +[[(2.5,0)][default][show_zero_components]['''2.5 + 0i''']] +[[(-2.5,0)][default][default]['''-2.5''']] +[[(-2.5,0)][default][show_zero_components]['''-2.5 + 0i''']] +[[(0,3.25)][default][default]['''3.25i''']] +[[(0,3.25)][default][show_zero_components]['''0 + 3.25i''']] +[[(0,-3.25)][default][default]['''-3.25i''']] +[[(0,-3.25)][default][show_zero_components]['''0 - 3.25i''']] +[[(inf,2.5)][default][default]['''∞̃''']] +[[(-inf,2.5)][default][default]['''∞̃''']] +[[(2.5,inf)][default][default]['''∞̃''']] +[[(2.5,-inf)][default][default]['''∞̃''']] +[[(2.5,nan)][default][default]['''NaN''']] +[[(nan,2.5)][default][default]['''NaN''']] +[[(inf,nan)][default][default]['''NaN''']] +[[(nan,inf)][default][default]['''NaN''']] + +] +] +[template rational_formatting_examples[] +[table:rat_fmt_examples Rational Values +[[Value][Result]] +[[1/3]['''13''']] +[[-1/3]['''-13''']] +[[-345634/1695]['''-3456341695''']] +[[0/1]['''0''']] +[[-23/1]['''-23''']] +[[46189/262144]['''46189262144''']] + +] +] +[template polynomial_formatting_examples[] +[table:poly_fmt_examples Polynomial Values +[[Kind][Result]][[Integer]['''2 - 3x + 4x2 + 5x3''']] +[[Float]['''2.4 - 34.25x + 4.2×10-06x2 - 5.34×10-67x3''']] +[[Complex]['''(2.4 + 3.25i) - 34.25x + 4.2×10-06ix2 - (5.34×10-67 - 4.65×10-20i)x3''']] +[[Rational]['''(23) - (323)x + (114)x2 + (532)x3''']] + +] +] diff --git a/example/formatter_docbook_output_test.qbk b/example/formatter_docbook_output_test.qbk new file mode 100644 index 0000000000..8a9553804f --- /dev/null +++ b/example/formatter_docbook_output_test.qbk @@ -0,0 +1,26 @@ + +[article Docbook Formatting Test + [quickbook 1.7] + [copyright 2019 John Maddock] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Maddock, John]] + [/last-revision $Date$] +] + +[import formatter_docbook_output.qbk] + +[integer_formatting_examples] + +[float_formatting_examples] + +[complex_formatting_examples] + +[complex_formatting_examples_2] + +[polynomial_formatting_examples] + +[rational_formatting_examples] diff --git a/example/formatter_html_output.cpp b/example/formatter_html_output.cpp new file mode 100644 index 0000000000..e9dc7443eb --- /dev/null +++ b/example/formatter_html_output.cpp @@ -0,0 +1,227 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +void print(std::ostream& os) +{ + boost::math::tools::html_printer printer(os); + + printer << "\n\n" << std::endl; + printer << "" << std::endl; + + printer << "

Synopsis

\nSample HTML output for various number types, these are then styled in bold, and various (somewhat untasteful!) colors just because we can, and to check that our markup generation is working correctly.\n"; + + printer << "

Basic Integers Values:

\n" << boost::math::tools::full_styling; + + int ival = 0; + printer << ""; + printer.stream() << "\n"; + ival = -23; + printer.stream() << "\n"; + ival = 23; + printer.stream() << std::dec << "\n"; + printer.stream() << std::dec << "\n
ValueBaseResult
" << ival << "default"; + printer << ival << "
" << ival << "default"; + printer << ival << "
" << ival << "hex"; + printer << std::hex << ival << "
" << ival << "oct"; + printer << std::oct << ival << "
\n\n" << std::dec; + + printer << "

Basic Floating Point Values:

\n\n"; + double fval = 3; + printer << ""; + printer.stream() << "\n"; + fval = 3.14; + printer.stream() << "\n"; + fval = -1.2345678765e-24; + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n" << boost::math::tools::multiply_times << std::defaultfloat; + + // Infinities: + fval = std::numeric_limits::infinity(); + printer.stream() << "\n"; + fval = -std::numeric_limits::infinity(); + printer.stream() << "\n"; + // NaN's: + fval = std::numeric_limits::quiet_NaN(); + printer.stream() << "\n"; + // Zeros: + fval = 0; + printer.stream() << "\n"; + fval = -fval; + printer.stream() << "\n"; + + printer << "
ValuePrecisionFormatResult
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "3scientific"; + printer << std::setprecision(3) << std::scientific << fval << "
" << fval << "defaultmultiply_x"; + printer << boost::math::tools::multiply_x << fval << "
" << fval << "3scientific + multiply_x"; + printer << std::setprecision(3) << std::scientific << fval << "
" << fval << "defaultmultiply_dot"; + printer << boost::math::tools::multiply_dot << fval << "
" << fval << "3scientific + multiply_dot"; + printer << std::setprecision(3) << std::scientific << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
" << fval << "defaultdefault"; + printer << fval << "
\n\n" << std::defaultfloat; + + printer << "

Complex Values:

\n\n"; + std::complex cval(3.25, 4.67); + printer << ""; + printer.stream() << "\n"; + cval = 3.14; + printer.stream() << "\n"; + cval = std::complex(1.23, -1.2345678765e-24); + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n"; + printer.stream() << "\n"; + + printer.stream() << "\n"; + printer.stream() << "\n" << boost::math::tools::multiply_times << boost::math::tools::upright_i; + printer << "\n
ValuePrecisionFormatResult
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "3scientific"; + printer << std::scientific << std::setprecision(3) << cval << "
" << cval << "12default + slanted_i"; + printer << boost::math::tools::slanted_i << std::defaultfloat << std::setprecision(12) << cval << "
" << cval << "12default + doublestruck_i"; + printer << boost::math::tools::doublestruck_i << std::defaultfloat << std::setprecision(12) << cval << "
" << cval << "12default + doublestruck_i + multiply_x"; + printer << boost::math::tools::doublestruck_i << boost::math::tools::multiply_x << std::defaultfloat << std::setprecision(12) << cval << "
" << cval << "12default + doublestruck_i + multiply_dot"; + printer << boost::math::tools::doublestruck_i << std::defaultfloat << std::setprecision(12) << boost::math::tools::multiply_dot << cval << "
\n\n"; + + printer << "

Complex Special Values:

\n\n"; + printer << ""; + cval = std::complex(0, 0); + printer.stream() << "\n"; + printer.stream() << "\n"; + cval = std::complex(3.14, 0); + printer.stream() << "\n"; + printer.stream() << "\n"; + cval = std::complex(-3.14, 0); + printer.stream() << "\n"; + printer.stream() << "\n"; + cval = std::complex(0, 25.5); + printer.stream() << "\n"; + printer.stream() << "\n"; + cval = std::complex(0, -25.5); + printer.stream() << "\n"; + printer.stream() << "\n"; + cval = std::complex(std::numeric_limits::infinity(), 0); + printer.stream() << "\n"; + cval = std::complex(-std::numeric_limits::infinity(), 0); + printer.stream() << "\n"; + cval = std::complex(25.5, std::numeric_limits::infinity()); + printer.stream() << "\n"; + cval = std::complex(25.5, -std::numeric_limits::infinity()); + printer.stream() << "\n"; + + cval = std::complex(std::numeric_limits::quiet_NaN(), 0); + printer.stream() << "\n"; + cval = std::complex(-std::numeric_limits::quiet_NaN(), 0); + printer.stream() << "\n"; + cval = std::complex(25.5, std::numeric_limits::quiet_NaN()); + printer.stream() << "\n"; + cval = std::complex(25.5, -std::numeric_limits::quiet_NaN()); + printer.stream() << "\n"; + + cval = std::complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity()); + printer.stream() << "\n"; + cval = std::complex(-std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity()); + printer.stream() << "\n"; + cval = std::complex(std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()); + printer.stream() << "\n"; + cval = std::complex(std::numeric_limits::infinity(), -std::numeric_limits::quiet_NaN()); + printer.stream() << "\n"; + + printer << "\n
ValuePrecisionFormatResult
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultshow_zero_components"; + printer << boost::math::tools::show_zero_components << cval << boost::math::tools::hide_zero_components << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultshow_zero_components"; + printer << boost::math::tools::show_zero_components << cval << boost::math::tools::hide_zero_components << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultshow_zero_components"; + printer << boost::math::tools::show_zero_components << cval << boost::math::tools::hide_zero_components << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultshow_zero_components"; + printer << boost::math::tools::show_zero_components << cval << boost::math::tools::hide_zero_components << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultshow_zero_components"; + printer << boost::math::tools::show_zero_components << cval << boost::math::tools::hide_zero_components << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
" << cval << "defaultdefault"; + printer << cval << "
\n\n"; + + printer << "

Rationals:

\n\n"; + + printer << ""; + boost::rational rat(1, 3); + printer.stream() << "\n"; + rat = -rat; + printer.stream() << "\n"; + rat *= 345634; + rat /= 565; + printer.stream() << "\n"; + rat = 0; + printer.stream() << "\n"; + rat = -23; + printer.stream() << "\n"; + boost::multiprecision::cpp_rational rat2(1); + for (unsigned i = 1; i < 20; i += 2) + { + rat2 *= i; + rat2 /= i + 1; + } + printer.stream() << "\n"; + printer << "\n
ValueResult
" << rat << ""; + printer << rat << "
" << rat; + printer << "" << rat << "
" << rat; + printer << "" << rat << "
" << rat; + printer << "" << rat << "
" << rat; + printer << "" << rat << "
" << rat2; + printer << "" << rat2 << "
\n\n"; + + printer << "

Polynomials:

\n\n"; + + printer << ""; + boost::math::tools::polynomial poly1 = { 2, -3, 4, 5 }; + printer << "\n"; + boost::math::tools::polynomial poly2 = { 2.4, -34.25, 4.2e-6, -5.34e-67 }; + printer << "\n"; + boost::math::tools::polynomial > poly3 = { { 2.4, 3.25 }, {-34.25 }, { 0, 4.2e-6 }, { -5.34e-67, 4.65e-20 } }; + printer << "\n"; + boost::math::tools::polynomial> poly4 = { {2, 3}, {-3, 23}, {4, 56}, {5, 32} }; + printer << "\n"; + printer << "\n
TypeResult
Integer" << poly1 << "
Float" << poly2 << "
Complex" << poly3 << "
Polynomial" << poly4 << "
\n\n"; + + printer << "\n\n"; +} + +int main(int argc, const char* argv[]) +{ + if (argc > 1) + { + std::ofstream ofs(argv[1]); + print(ofs); + } + else + print(std::cout); + return 0; +} diff --git a/example/formatter_html_output.html b/example/formatter_html_output.html new file mode 100644 index 0000000000..dd8b06e6b5 --- /dev/null +++ b/example/formatter_html_output.html @@ -0,0 +1,92 @@ + + + + +

Synopsis

+Sample HTML output for various number types, these are then styled in bold, and various (somewhat untasteful!) colors just because we can, and to check that our markup generation is working correctly. +

Basic Integers Values:

+ + + + +
ValueBaseResult
0default0
-23default-23
23hex17
23oct27
+ +

Basic Floating Point Values:

+ + + + + + + + + + + + + + +
ValuePrecisionFormatResult
3defaultdefault3
3.14defaultdefault3.14
-1.23457e-24defaultdefault-1.23457×10-24
-1.23457e-243scientific-1.235×10-24
-1.235e-24defaultmultiply_x-1.235x10-24
-1.235e-243scientific + multiply_x-1.235x10-24
-1.235e-24defaultmultiply_dot-1.235⋅10-24
-1.235e-243scientific + multiply_dot-1.235⋅10-24
infdefaultdefault
-infdefaultdefault-∞
nandefaultdefaultNaN
0defaultdefault0
-0defaultdefault-0
+ +

Complex Values:

+ + + + + + + + + + +
ValuePrecisionFormatResult
(3.25,4.67)defaultdefault3.25 + 4.67i
(3.14,0)defaultdefault3.14
(1.23,-1.23e-24)defaultdefault1.23 - 1.23×10-24i
(1.23,-1.23e-24)3scientific1.230×10+00 - 1.235×10-24i
(1.230e+00,-1.235e-24)12default + slanted_i1.23 - 1.2345678765×10-24i
(1.23,-1.2345678765e-24)12default + doublestruck_i1.23 - 1.2345678765×10-24
(1.23,-1.2345678765e-24)12default + doublestruck_i + multiply_x1.23 - 1.2345678765x10-24
(1.23,-1.2345678765e-24)12default + doublestruck_i + multiply_dot1.23 - 1.2345678765⋅10-24
+ +

Complex Special Values:

+ + + + + + + + + + + + + + + + + + + + + + + + +
ValuePrecisionFormatResult
(0,0)defaultdefault0
(0,0)defaultshow_zero_components0 + 0i
(3.14,0)defaultdefault3.14
(3.14,0)defaultshow_zero_components3.14 + 0i
(-3.14,0)defaultdefault-3.14
(-3.14,0)defaultshow_zero_components-3.14 + 0i
(0,25.5)defaultdefault25.5i
(0,25.5)defaultshow_zero_components0 + 25.5i
(0,-25.5)defaultdefault-25.5i
(0,-25.5)defaultshow_zero_components0 - 25.5i
(inf,0)defaultdefault∞̃
(-inf,0)defaultdefault∞̃
(25.5,inf)defaultdefault∞̃
(25.5,-inf)defaultdefault∞̃
(nan,0)defaultdefaultNaN
(-nan(ind),0)defaultdefaultNaN
(25.5,nan)defaultdefaultNaN
(25.5,-nan(ind))defaultdefaultNaN
(nan,inf)defaultdefaultNaN
(-nan(ind),inf)defaultdefaultNaN
(inf,nan)defaultdefaultNaN
(inf,-nan(ind))defaultdefaultNaN
+ +

Rationals:

+ + + + + + + + +
ValueResult
1/313
-1/3-13
-345634/1695-3456341695
0/10
-23/1-23
46189/26214446189262144
+ +

Polynomials:

+ + + + + + +
TypeResult
Integer2 - 3x + 4x2 + 5x3
Float2.4 - 34.25x + 4.2×10-06x2 - 5.34×10-67x3
Complex(2.4 + 3.25i) - 34.25x + 4.2×10-06ix2 - (5.34×10-67 - 4.65×10-20i)x3
Polynomial(23) - (323)x + (114)x2 + (532)x3
+ + + diff --git a/example/formatter_interval_output.cpp b/example/formatter_interval_output.cpp new file mode 100644 index 0000000000..a7f78f060a --- /dev/null +++ b/example/formatter_interval_output.cpp @@ -0,0 +1,40 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include + +int main() +{ + typedef boost::multiprecision::number > mp_type; + mp_type f = boost::math::constants::pi(); + + std::cout << std::setprecision(std::numeric_limits::digits10); + + boost::math::tools::text_printer t_print(std::cout); + t_print << f << std::endl; + + boost::math::tools::latex_printer l_print(std::cout); + l_print << f << std::endl; + + boost::math::tools::docbook_printer d_print(std::cout); + d_print << f << std::endl; + + boost::math::tools::polynomial poly1 = { 2, 3, 4, -5, -4, 12 }; + boost::math::tools::polynomial poly2 = { -3, 2, 4, 5 }; + poly1 *= poly2; + poly1 /= 3; + + t_print << poly1 << std::endl; + + l_print << poly1 << std::endl; + + d_print << poly1 << std::endl; + + return 0; +} diff --git a/example/formatter_latex_output.cpp b/example/formatter_latex_output.cpp new file mode 100644 index 0000000000..1f26dde66b --- /dev/null +++ b/example/formatter_latex_output.cpp @@ -0,0 +1,213 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include + +void print(std::ostream& os) +{ + boost::math::tools::latex_printer printer(os); + + printer << "\\documentclass[10pt]{article}" << std::endl; + printer << "\\usepackage{lingmacros}" << std::endl; + printer << "\\usepackage{tree-dvips}" << std::endl; + printer << "\\usepackage[a4paper, left = { 0.5in }]{ geometry }" << std::endl; + printer << "\\begin{document}" << std::endl << std::endl; + + int ival = 0; + printer << "\\textbf{Basic Integer Values}\n\n\\begin{tabular}{r r r}\nValue & Base & Result \\\\ \\hline \n"; + printer.stream() << ival << " & default & "; + printer << ival << "\\\\\n"; + ival = -23; + printer.stream() << ival << " & default & "; + printer << ival << " \\\\\n"; + ival = 23; + printer.stream() << std::dec << ival << " & hex & "; + printer << std::hex << ival << "\\\\\n"; + printer.stream() << std::dec << ival << " & oct & "; + printer << std::oct << ival << "\\\\\n\\end{tabular}\n\n" << std::dec; + + double fval = 3; + printer << "\\textbf{Basic Float Values}\n\n\\begin{tabular}{r r r r}\nValue & Precision & Format & Result \\\\\n"; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = 3.14; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = -1.2345678765e-24; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + printer.stream() << fval << " & 3 & scientific & "; + printer << std::setprecision(3) << std::scientific << fval << " \\\\\n"; + printer.stream() << fval << " & 10 & scientific + latex\\_as\\_text & "; + printer << std::setprecision(10) << boost::math::tools::latex_as_text << std::scientific << fval << " \\\\\n" << boost::math::tools::latex_as_equation; + + printer.stream() << fval << " & 3 & scientific + multiply\\_x & "; + printer << std::setprecision(3) << std::scientific << boost::math::tools::multiply_x << fval << " \\\\\n"; + printer.stream() << fval << " & 10 & scientific + latex\\_as\\_text + multiply\\_x & "; + printer << std::setprecision(10) << boost::math::tools::latex_as_text << boost::math::tools::multiply_x << std::scientific << fval << " \\\\\n" << boost::math::tools::latex_as_equation; + printer.stream() << fval << " & 3 & scientific + multiply\\_dot & "; + printer << std::setprecision(3) << std::scientific << boost::math::tools::multiply_dot << fval << " \\\\\n"; + printer.stream() << fval << " & 10 & scientific + latex\\_as\\_text + multiply\\_dot & "; + printer << std::setprecision(10) << boost::math::tools::latex_as_text << boost::math::tools::multiply_dot << std::scientific << fval << " \\\\\n" + << boost::math::tools::latex_as_equation << boost::math::tools::multiply_times << std::defaultfloat << boost::math::tools::latex_as_equation; + + // Special Values: + fval = 0; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = -fval; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = std::numeric_limits::infinity(); + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = -fval; + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + fval = std::numeric_limits::quiet_NaN(); + printer.stream() << fval << " & default & default & "; + printer << fval << " \\\\\n"; + printer << boost::math::tools::latex_as_text; + fval = 0; + printer.stream() << fval << " & default & latex\\_as\\_text & "; + printer << fval << " \\\\\n"; + fval = -fval; + printer.stream() << fval << " & default & latex\\_as\\_text & "; + printer << fval << " \\\\\n"; + fval = std::numeric_limits::infinity(); + printer.stream() << fval << " & default & latex\\_as\\_text & "; + printer << fval << " \\\\\n"; + fval = -fval; + printer.stream() << fval << " & default & latex\\_as\\_text & "; + printer << fval << " \\\\\n"; + fval = std::numeric_limits::quiet_NaN(); + printer.stream() << fval << " & default & latex\\_as\\_text & "; + printer << fval << " \\\\\n"; + printer << boost::math::tools::latex_as_equation; + + printer << "\\end{tabular}\n\n" << std::defaultfloat; + + std::complex cval(3.25, 4.67); + printer << "\\textbf{Basic Complex Values}\n\n\\begin{tabular}{r r r r}\nValue & Precision & Format & Result \\\\\n"; + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = 3.14; + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = std::complex(1.23, -1.2345678765e-24); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & 3 & scientific & "; + printer << std::scientific << std::setprecision(3) << cval << " \\\\\n"; + printer.stream() << cval << " & 12 & default + slanted\\_i & "; + printer << boost::math::tools::slanted_i << std::defaultfloat << std::setprecision(12) << cval << " \\\\\n"; + printer.stream() << cval << " & 12 & default + upright\\_i & "; + printer << boost::math::tools::upright_i << std::defaultfloat << std::setprecision(12) << cval << " \\\\\n"; + printer.stream() << cval << " & 12 & default + slanted\\_i + latex\\_as\\_text & "; + printer << boost::math::tools::slanted_i << boost::math::tools::latex_as_text << std::defaultfloat << std::setprecision(12) << cval << " \\\\\n"; + printer.stream() << cval << " & 12 & default + upright\\_i + latex\\_as\\_text& "; + printer << boost::math::tools::upright_i << std::defaultfloat << std::setprecision(12) << cval << " \\\\\n"; + printer << "\\end{tabular}\n\n" << std::defaultfloat << boost::math::tools::multiply_times << boost::math::tools::latex_as_equation; + + printer << "\\textbf{Complex Special Values}\n\n\\begin{tabular}{r r r r}\nValue & Precision & Format & Result \\\\\n"; + cval = std::complex(0, 0); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & default & show\\_zero\\_components & "; + printer << boost::math::tools::show_zero_components << cval << " \\\\\n" << boost::math::tools::hide_zero_components; + cval = std::complex(2.5, 0); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & default & show\\_zero\\_components & "; + printer << boost::math::tools::show_zero_components << cval << " \\\\\n" << boost::math::tools::hide_zero_components; + cval = std::complex(-2.5, 0); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & default & show\\_zero\\_components & "; + printer << boost::math::tools::show_zero_components << cval << " \\\\\n" << boost::math::tools::hide_zero_components; + cval = std::complex(0, 2.5); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & default & show\\_zero\\_components & "; + printer << boost::math::tools::show_zero_components << cval << " \\\\\n" << boost::math::tools::hide_zero_components; + cval = std::complex(0, -2.5); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer.stream() << cval << " & default & show\\_zero\\_components & "; + printer << boost::math::tools::show_zero_components << cval << " \\\\\n" << boost::math::tools::hide_zero_components; + // Infinity: + cval = std::complex(std::numeric_limits::infinity(), 2.5); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = std::complex(2.5, std::numeric_limits::infinity()); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + // NaN: + cval = std::complex(std::numeric_limits::quiet_NaN(), 2.5); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = std::complex(2.5, std::numeric_limits::quiet_NaN()); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = std::complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity()); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + cval = std::complex(std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()); + printer.stream() << cval << " & default & default & "; + printer << cval << " \\\\\n"; + printer << "\\end{tabular}\n\n" << std::defaultfloat << boost::math::tools::multiply_times; + + printer << "\\textbf{Rational Values}\n\n\\begin{tabular}{r r r}\nValue & Format & Result \\\\\n"; + boost::rational r(2, 3); + printer.stream() << r << " & default &"; + printer << r << " \\\\\n"; + r = -r; + printer.stream() << r << " & default &"; + printer << r << " \\\\\n"; + r = 0; + printer.stream() << r << " & default &"; + printer << r << " \\\\\n"; + r = -23; + printer.stream() << r << " & default &"; + printer << r << " \\\\\n"; + r *= 345634; + r /= 565; + printer.stream() << r << " & default &"; + printer << r << " \\\\\n"; + printer.stream() << r << " & latex\\_as\\_text &"; + printer << boost::math::tools::latex_as_text << r << " \\\\\n"; + printer << "\\end{tabular}\n\n" << boost::math::tools::latex_as_equation; + + printer << "\\textbf{Polynomial Values}\n\n\\begin{tabular}{r r}\nType & Result \\\\\n"; + boost::math::tools::polynomial poly1 = { 2, -3, 4, 5 }; + printer << "Integer & " << poly1 << " \\\\\n"; + boost::math::tools::polynomial poly2 = { 2.4, -34.25, 4.2e-6, -5.34e-67 }; + printer << "Float & " << poly2 << " \\\\\n"; + boost::math::tools::polynomial > poly3 = { { 2.4, 3.25 }, {-34.25 }, { 0, 4.2e-6 }, { -5.34e-67, 4.65e-20 } }; + printer << "Complex & " << poly3 << " \\\\\n"; + printer << "Complex (latex\\_as\\_text) & " << boost::math::tools::latex_as_text << poly3 << " \\\\\n" << boost::math::tools::latex_as_equation; + printer << "Complex (multiply\\_dot) & " << boost::math::tools::multiply_dot << poly3 << " \\\\\n" << boost::math::tools::multiply_times; + boost::math::tools::polynomial> poly4 = { {2, 3}, {-3, 23}, {4, 56}, {5, 32} }; + printer << "Rational & " << poly4 << " \\\\\n"; + printer << "\\end{tabular}\n\n" << std::defaultfloat << boost::math::tools::multiply_times; + + printer << "\\end{document}\n\n"; +} + +int main(int argc, const char* argv[]) +{ + if (argc > 1) + { + std::ofstream ofs(argv[1]); + print(ofs); + } + else + print(std::cout); + return 0; +} diff --git a/example/formatter_latex_output.pdf b/example/formatter_latex_output.pdf new file mode 100644 index 0000000000..8b22a131c7 Binary files /dev/null and b/example/formatter_latex_output.pdf differ diff --git a/example/formatter_latex_output.tex b/example/formatter_latex_output.tex new file mode 100644 index 0000000000..6e481238e4 --- /dev/null +++ b/example/formatter_latex_output.tex @@ -0,0 +1,103 @@ +\documentclass[10pt]{article} +\usepackage{lingmacros} +\usepackage{tree-dvips} +\usepackage[a4paper, left = { 0.5in }]{ geometry } +\begin{document} + +\textbf{Basic Integer Values} + +\begin{tabular}{r r r} +Value & Base & Result \\ \hline +0 & default & $0$\\ +-23 & default & $-23$ \\ +23 & hex & $17$\\ +23 & oct & $27$\\ +\end{tabular} + +\textbf{Basic Float Values} + +\begin{tabular}{r r r r} +Value & Precision & Format & Result \\ +3 & default & default & $3$ \\ +3.14 & default & default & $3.14$ \\ +-1.23457e-24 & default & default & $-1.23457\times10^{-24}$ \\ +-1.23457e-24 & 3 & scientific & $-1.235\times10^{-24}$ \\ +-1.235e-24 & 10 & scientific + latex\_as\_text & -1.2345678765$\times$10\textsuperscript{-24} \\ +-1.2345678765e-24 & 3 & scientific + multiply\_x & $-1.235\mathrm{x}10^{-24}$ \\ +-1.235e-24 & 10 & scientific + latex\_as\_text + multiply\_x & -1.2345678765x10\textsuperscript{-24} \\ +-1.2345678765e-24 & 3 & scientific + multiply\_dot & $-1.235\cdot10^{-24}$ \\ +-1.235e-24 & 10 & scientific + latex\_as\_text + multiply\_dot & -1.2345678765$\cdot$10\textsuperscript{-24} \\ +0 & default & default & $0$ \\ +-0 & default & default & $-0$ \\ +inf & default & default & $\infty$ \\ +-inf & default & default & $-\infty$ \\ +nan & default & default & $\mathrm{NaN}$ \\ +0 & default & latex\_as\_text & 0 \\ +-0 & default & latex\_as\_text & -0 \\ +inf & default & latex\_as\_text & $\infty$ \\ +-inf & default & latex\_as\_text & -$\infty$ \\ +nan & default & latex\_as\_text & NaN \\ +\end{tabular} + +\textbf{Basic Complex Values} + +\begin{tabular}{r r r r} +Value & Precision & Format & Result \\ +(3.25,4.67) & default & default & $3.25 + 4.67\mathrm{i}$ \\ +(3.14,0) & default & default & $3.14$ \\ +(1.23,-1.234567876e-24) & default & default & $1.23 - 1.234567876\times10^{-24}\mathrm{i}$ \\ +(1.23,-1.234567876e-24) & 3 & scientific & $1.230\times10^{+00} - 1.235\times10^{-24}\mathrm{i}$ \\ +(1.230e+00,-1.235e-24) & 12 & default + slanted\_i & $1.23 - 1.2345678765\times10^{-24}i$ \\ +(1.23,-1.2345678765e-24) & 12 & default + upright\_i & $1.23 - 1.2345678765\times10^{-24}\mathrm{i}$ \\ +(1.23,-1.2345678765e-24) & 12 & default + slanted\_i + latex\_as\_text & 1.23 - 1.2345678765$\times$10\textsuperscript{-24}\textit{i} \\ +(1.23,-1.2345678765e-24) & 12 & default + upright\_i + latex\_as\_text& 1.23 - 1.2345678765$\times$10\textsuperscript{-24}i \\ +\end{tabular} + +\textbf{Complex Special Values} + +\begin{tabular}{r r r r} +Value & Precision & Format & Result \\ +(0,0) & default & default & $0$ \\ +(0,0) & default & show\_zero\_components & $0 + 0\mathrm{i}$ \\ +(2.5,0) & default & default & $2.5$ \\ +(2.5,0) & default & show\_zero\_components & $2.5 + 0\mathrm{i}$ \\ +(-2.5,0) & default & default & $-2.5$ \\ +(-2.5,0) & default & show\_zero\_components & $-2.5 + 0\mathrm{i}$ \\ +(0,2.5) & default & default & $2.5\mathrm{i}$ \\ +(0,2.5) & default & show\_zero\_components & $0 + 2.5\mathrm{i}$ \\ +(0,-2.5) & default & default & $-2.5\mathrm{i}$ \\ +(0,-2.5) & default & show\_zero\_components & $0 - 2.5\mathrm{i}$ \\ +(inf,2.5) & default & default & $\tilde{\infty}$ \\ +(2.5,inf) & default & default & $\tilde{\infty}$ \\ +(nan,2.5) & default & default & $\mathrm{NaN}$ \\ +(2.5,nan) & default & default & $\mathrm{NaN}$ \\ +(nan,inf) & default & default & $\mathrm{NaN}$ \\ +(inf,nan) & default & default & $\mathrm{NaN}$ \\ +\end{tabular} + +\textbf{Rational Values} + +\begin{tabular}{r r r} +Value & Format & Result \\ +2/3 & default &$\frac{2}{3}$ \\ +-2/3 & default &$-\frac{2}{3}$ \\ +0/1 & default &$0$ \\ +-23/1 & default &$-23$ \\ +-7949582/565 & default &$-\frac{7949582}{565}$ \\ +-7949582/565 & latex\_as\_text &-\textsuperscript{7949582}/\textsubscript{565} \\ +\end{tabular} + +\textbf{Polynomial Values} + +\begin{tabular}{r r} +Type & Result \\ +Integer & $2 - 3x + 4x^{2} + 5x^{3}$ \\ +Float & $2.4 - 34.25x + 4.2\times10^{-06}x^{2} - 5.34\times10^{-67}x^{3}$ \\ +Complex & $(2.4 + 3.25\mathrm{i}) - 34.25x + 4.2\times10^{-06}\mathrm{i}x^{2} - (5.34\times10^{-67} - 4.65\times10^{-20}\mathrm{i})x^{3}$ \\ +Complex (latex\_as\_text) & (2.4 + 3.25i) - 34.25\textit{x} + 4.2$\times$10\textsuperscript{-06}i\textit{x}\textsuperscript{2} - (5.34$\times$10\textsuperscript{-67} - 4.65$\times$10\textsuperscript{-20}i)\textit{x}\textsuperscript{3} \\ +Complex (multiply\_dot) & $(2.4 + 3.25\mathrm{i}) - 34.25x + 4.2\cdot10^{-06}\mathrm{i}x^{2} - (5.34\cdot10^{-67} - 4.65\cdot10^{-20}\mathrm{i})x^{3}$ \\ +Rational & $(\frac{2}{3}) - (\frac{3}{23})x + (\frac{1}{14})x^{2} + (\frac{5}{32})x^{3}$ \\ +\end{tabular} + +\end{document} + diff --git a/example/formatter_snips.cpp b/example/formatter_snips.cpp new file mode 100644 index 0000000000..0e37a8a717 --- /dev/null +++ b/example/formatter_snips.cpp @@ -0,0 +1,82 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include + + +int main(int argc, const char* argv[]) +{ + + //[formatting_eg1 + //` By way of example, lets suppose we have a polynomial with complex coefficients: + boost::math::tools::polynomial > poly; + //` And then do something to populate those coefficients... + //<- + poly = boost::math::tools::polynomial >{ {2.25, -3.5 }, {-12.5, -4.5 }, { 23.34 }, { 0, 34.5 } }; + //-> + //` For debugging purposes, we may wish to output the polynomial to std::cout. + //` Using `text_printer` we can do just that: + + boost::math::tools::text_printer printer(std::cout); + printer << poly << std::endl; + + //` By default, `text_printer` outputs using Unicode, so even console output is properly formatted: + //` + //` [$../images/console1.png] + //` + //` Note however, that not all platforms support Unicode console output, so if required + //` we can use the `ascii_text_output` format manipulator to switch to plain ASCII output: + + printer << boost::math::tools::ascii_text_output << poly << std::endl; + + //` The result is rather less pretty, but the best we can do under the circumstances: + //` + //` [$../images/console2.png] + //` + //] + { + //[formatting_eg2 + //` + //`Later, lets suppose we've now finalised our polynomial and wish to format it for print, + //`in that case we can simply change the printer to `latex_printer` and stream out as before: + //` + boost::math::tools::latex_printer printer(std::cout); + printer << poly << std::endl; + //` + //` After running the output through your favorite Tex processor the result is a nicely formatted + //` equation: + //` + //` [$../images/polynomial_latex_1.svg] + //` + //] + } + { + //[formatting_eg3 + //` + //` The output though may not quite be as we would like, let's suppose + //` instead we wish to write a complete LaTex document to file and change the + //` formatting so that the values are printed to 2 decimal places, and the + //` imaginary unit i is italisized as is common in many historical texts. + //` The code now looks like: + //` + std::ofstream fs("polynomial.tex"); + boost::math::tools::latex_printer printer(fs); + // Document preamble: + printer << "\\documentclass{article}" << std::endl; + printer << "\\begin{document}" << std::endl << std::endl; + // + // Stream out some manipulators to set the formatting: + // + printer << std::setprecision(2) << std::fixed << boost::math::tools::slanted_i; + printer << poly << std::endl; + printer << "\\end{document}\n\n"; + + //] + } + return 0; +} diff --git a/example/formatter_text_output.cpp b/example/formatter_text_output.cpp new file mode 100644 index 0000000000..c3006ba670 --- /dev/null +++ b/example/formatter_text_output.cpp @@ -0,0 +1,195 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +template +void print(std::basic_ostream& os) +{ + boost::math::tools::basic_numeric_printer printer(os); + + printer << "Integers:\n\n"; + + int ival = 0; + printer << std::setw(20) << "Value" << std::setw(20) << "Base" << std::setw(20) << "Result" << std::endl; + printer.stream() << std::setw(20) << ival << std::setw(20) << "default" << std::setw(20); + printer << ival << std::endl; + ival = -23; + printer.stream() << std::setw(20) << ival << std::setw(20) << "default" << std::setw(20); + printer << ival << std::endl; + ival = 23; + printer.stream() << std::setw(20) << ival << std::setw(20) << "hex" << std::setw(20); + printer << std::hex << ival << std::endl; + printer.stream() << std::setw(20) << ival << std::setw(20) << "oct" << std::setw(20); + printer << std::oct << ival << std::endl << std::dec; + + printer << std::endl << std::endl; + + printer << "Basic floating point values:\n\n"; + double fval = 3; + printer << std::setw(20) << "Value" << std::setw(20) << "Precision" << std::setw(20) << "Format" << std::setw(20) << "Result" << std::endl; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = 3.14; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = -1.2345678765e-24; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + printer.stream() << std::scientific << std::setw(20) << fval << std::setw(20) << "3" << std::setw(20) << "scientific" << std::setw(20); + printer << std::setprecision(3) << fval << std::endl << std::defaultfloat; + fval = 0; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = -fval; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = 0; + printer.stream() << std::scientific << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "scientific" << std::setw(20); + printer << fval << std::endl; + fval = -fval; + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "scientific" << std::setw(20); + printer << fval << std::endl << std::defaultfloat; + fval = std::numeric_limits::infinity(); + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = -std::numeric_limits::infinity(); + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + fval = std::numeric_limits::quiet_NaN(); + printer.stream() << std::setw(20) << fval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(20); + printer << fval << std::endl; + + printer << std::endl << std::endl; + + printer << "Complex Values:\n\n"; + std::complex cval(3.25, 4.67); + printer << std::setw(20) << "Value" << std::setw(20) << "Precision" << std::setw(20) << "Format" << std::setw(30) << "Result" << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(30); + printer << cval << std::endl; + cval = 3.14; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(1.23, -1.2345678765e-24); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(20) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "3" << std::setw(20) << "scientific" << std::setw(30); + printer << std::scientific << std::setprecision(3) << cval << std::endl << std::endl << std::defaultfloat; + printer.stream() << std::setw(20) << cval << std::setw(20) << "slanted_i" << std::setw(20) << "default" << std::setw(30); + printer << boost::math::tools::slanted_i << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "doublestruck_i" << std::setw(20) << "default" << std::setw(30); + printer << boost::math::tools::doublestruck_i << cval << std::endl << boost::math::tools::upright_i; + + std::cout << std::endl << std::endl; + + printer << "Complex Zeros:\n\n"; + cval = std::complex(0); + printer << std::setw(20) << "Value" << std::setw(20) << "Precision" << std::setw(23) << "Format" << std::setw(30) << "Result" << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "show_zero_components" << std::setw(30); + printer << boost::math::tools::show_zero_components << cval << std::endl << boost::math::tools::hide_zero_components; + cval = 3.14; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "show_zero_components" << std::setw(30); + printer << boost::math::tools::show_zero_components << cval << std::endl << boost::math::tools::hide_zero_components; + cval = -3.14; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "show_zero_components" << std::setw(30); + printer << boost::math::tools::show_zero_components << cval << std::endl << boost::math::tools::hide_zero_components; + cval = std::complex(0, 25.25); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "show_zero_components" << std::setw(30); + printer << boost::math::tools::show_zero_components << cval << std::endl << boost::math::tools::hide_zero_components; + cval = std::complex(0, -25.25); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "show_zero_components" << std::setw(30); + printer << boost::math::tools::show_zero_components << cval << std::endl << boost::math::tools::hide_zero_components; + // Infinities: + cval = std::complex(std::numeric_limits::infinity(), -25.25); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(2, std::numeric_limits::infinity()); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(-std::numeric_limits::infinity(), std::numeric_limits::infinity()); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + // NaN's: + cval = std::complex(std::numeric_limits::quiet_NaN(), -25.25); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(3, std::numeric_limits::quiet_NaN()); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::infinity()); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + cval = std::complex(std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()); + printer.stream() << std::setw(20) << cval << std::setw(20) << "default" << std::setw(23) << "default" << std::setw(30); + printer << cval << std::endl; + + + printer << "\nRationals:\n\n"; + boost::rational rat(1, 3); + printer << std::setw(20) << "Value" << std::setw(20) << "Result" << std::endl; + printer.stream() << std::setw(20) << rat; + printer << std::setw(20) << rat << std::endl; + rat = -rat; + printer.stream() << std::setw(20) << rat; + printer << std::setw(20) << rat << std::endl; + rat *= 345634; + rat /= 565; + printer.stream() << std::setw(20) << rat; + printer << std::setw(20) << rat << std::endl; + boost::multiprecision::cpp_rational rat2(1); + for (unsigned i = 1; i < 20; i += 2) + { + rat2 *= i; + rat2 /= i + 1; + } + printer.stream() << std::setw(20) << rat2; + printer << std::setw(20) << rat2 << std::endl; + + printer << "\nPolynomials:\n\n"; + boost::math::tools::polynomial poly1 = { 2, -3, 4, 5 }; + printer << "Integer: " << poly1 << std::endl; + boost::math::tools::polynomial poly2 = { 2.4, -34.25, 4.2e-6, -5.34e-67 }; + printer << "Float: " << poly2 << std::endl; + boost::math::tools::polynomial > poly3 = { { 2.4, 3.25 }, {-34.25 }, { 0, 4.2e-6 }, { -5.34e-67, 4.65e-20 } }; + printer << "Complex: " << poly3 << std::endl; + boost::math::tools::polynomial> poly4 = { {2, 3}, {-3, 23}, {4, 56}, {5, 32} }; + printer << "Rational: " << poly4 << std::endl; +} + +#ifdef _WIN32 +#include +#endif + +int main(int argc, const char* argv[]) +{ + if (argc > 1) + { + std::ofstream ofs(argv[1]); + print(ofs); + } + else + { +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); +#endif + print(std::cout); + } + return 0; +} diff --git a/example/formatter_text_output.txt b/example/formatter_text_output.txt new file mode 100644 index 0000000000..046ce52491 --- /dev/null +++ b/example/formatter_text_output.txt @@ -0,0 +1,70 @@ +Integers: + + Value Base Result + 0 default 0 + -23 default -23 + 23 hex 17 + 17 oct 27 + + +Basic floating point values: + + Value Precision Format Result + 3 default default 3 + 3.14 default default 3.14 + -1.23457e-24 default default -1.23457×10⁻²⁴ + -1.234568e-24 3 scientific -1.235×10⁻²⁴ + 0 default default 0 + -0 default default -0 + 0.000e+00 default scientific 0.000×10⁺⁰⁰ + -0.000e+00 default scientific -0.000×10⁺⁰⁰ + inf default default ∞ + -inf default default -∞ + nan default default NaN + + +Complex Values: + + Value Precision Format Result + (3.25,4.67) default default 3.25 + 4.67i + (3.14,0) default default 3.14 + (1.23,-1.23e-24) default default 1.23 - 1.23×10⁻²⁴i + (1.23,-1.23e-24) 3 scientific 1.230×10⁺⁰⁰ - 1.235×10⁻²⁴i + + (1.23,-1.23e-24) slanted_i default 1.23 - 1.23×10⁻²⁴𝑖 + (1.23,-1.23e-24) doublestruck_i default 1.23 - 1.23×10⁻²⁴ⅈ +Complex Zeros: + + Value Precision Format Result + (0,0) default default 0 + (0,0) default show_zero_components 0 + 0i + (3.14,0) default default 3.14 + (3.14,0) default show_zero_components 3.14 + 0i + (-3.14,0) default default -3.14 + (-3.14,0) default show_zero_components -3.14 + 0i + (0,25.3) default default 25.3i + (0,25.3) default show_zero_components 0 + 25.3i + (0,-25.3) default default -25.3i + (0,-25.3) default show_zero_components 0 - 25.3i + (inf,-25.3) default default ∞ + (2,inf) default default ∞ + (-inf,inf) default default ∞ + (nan,-25.3) default default NaN + (3,nan) default default NaN + (nan,inf) default default NaN + (inf,nan) default default NaN + +Rationals: + + Value Result + 1/3 ¹⁄₃ + -1/3 -¹⁄₃ + -345634/1695 -³⁴⁵⁶³⁴⁄₁₆₉₅ + 46189/262144 ⁴⁶¹⁸⁹⁄₂₆₂₁₄₄ + +Polynomials: + +Integer: 2 - 3x + 4x² + 5x³ +Float: 2.4 - 34.3x + 4.2×10⁻⁰⁶x² - 5.34×10⁻⁶⁶x³ +Complex: (2.4 + 3.25i) - 34.3x + 4.2×10⁻⁰⁶ix² - (5.34×10⁻⁶⁶ - 4.65×10⁻²⁰i)x³ +Rational: (²⁄₃) - (³⁄₂₃)x + (¹⁄₁₄)x² + (⁵⁄₃₂)x³ diff --git a/include/boost/math/interpolators/barycentric_rational.hpp b/include/boost/math/interpolators/barycentric_rational.hpp index 5419c70af3..cccf85c7f9 100644 --- a/include/boost/math/interpolators/barycentric_rational.hpp +++ b/include/boost/math/interpolators/barycentric_rational.hpp @@ -56,6 +56,11 @@ class barycentric_rational return m_imp->return_y(); } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const barycentric_rational& bar) + { + print(os, *bar.m_imp); + } private: std::shared_ptr> m_imp; }; diff --git a/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp b/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp index b1bd6666ad..259226e556 100644 --- a/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_cubic_b_spline.hpp @@ -47,6 +47,12 @@ class cardinal_cubic_b_spline Real double_prime(Real x) const; + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_cubic_b_spline& v) + { + print(os, *v.m_imp); + } + private: std::shared_ptr> m_imp; }; diff --git a/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp b/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp index a5b150f2f1..9530bbf20e 100644 --- a/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_quadratic_b_spline.hpp @@ -49,6 +49,11 @@ class cardinal_quadratic_b_spline return impl_->t_max(); } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_quadratic_b_spline& spline) + { + print(os, *spline.impl_); + } private: std::shared_ptr> impl_; }; diff --git a/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp b/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp index 3d72865d93..9b2df809d2 100644 --- a/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp +++ b/include/boost/math/interpolators/cardinal_quintic_b_spline.hpp @@ -54,6 +54,12 @@ class cardinal_quintic_b_spline return impl_->t_max(); } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_quintic_b_spline& spline) + { + print(os, *spline.impl_); + } + private: std::shared_ptr> impl_; }; diff --git a/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp b/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp index b4199ea266..d0f278a553 100644 --- a/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp +++ b/include/boost/math/interpolators/detail/barycentric_rational_detail.hpp @@ -16,7 +16,18 @@ #include #include -namespace boost{ namespace math{ namespace detail{ +namespace boost{ namespace math{ + +namespace tools +{ + // Forward declaration only, we don't need the formatter's + // definition to be able to define a print function (only if + // we actually use it). + template + class basic_numeric_printer_base; +} + +namespace detail{ template class barycentric_rational_imp @@ -44,6 +55,161 @@ class barycentric_rational_imp return std::move(m_y); } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const barycentric_rational_imp& bar) + { + typedef boost::math::tools::basic_numeric_printer_base printer_t; + // + // scoped_prolog is responsible for writing the prolog/epilog code + // to the stream, if the output format requires it. Not a number in it's own + // right, but an expression, so set the name to the empty string and let each + // individual number style itself. + // + typename printer_t::scoped_prolog prolog(&os, ""); + // + // scoped_parenthesis instructs nested types to wrap themselves in () + // if they are compound rather than atomic number types (for example complex numbers): + // + typename printer_t::scoped_parenthesis param(&os); + + { + // This just prints: + // P(x) / Q(x) + std::basic_stringstream ss; + ss.copyfmt(os.stream()); + ss.imbue(os.stream().getloc()); + ss.width(0); + std::unique_ptr > fmt(os.clone(ss)); + fmt->print_name("P"); + fmt->stream() << "("; + fmt->print_variable('x'); + fmt->stream() << ")"; + + std::basic_stringstream ss2; + ss2.copyfmt(os.stream()); + ss2.imbue(os.stream().getloc()); + ss2.width(0); + std::unique_ptr > fmt2(os.clone(ss2)); + fmt2->print_name("Q"); + fmt2->stream() << "("; + fmt2->print_variable('x'); + fmt2->stream() << ")"; + + os.print_fraction(ss.str(), ss2.str()); + } + // " ; P(x) = " + os.stream() << " ; "; + os.print_name("P"); + os.stream() << "("; + os.print_variable('x'); + os.stream() << ") = "; + + for (size_t i = 0; i < bar.m_x.size(); ++i) + { + auto y = bar.m_y[i]; + if (i) + { + if (y > 0) + os.stream() << " + "; + else + { + y = -y; + os.stream() << " - "; + } + } + std::basic_string num, denom; + { + // m_y[i] * m_w[i] + // + std::basic_stringstream ss; + ss.copyfmt(os.stream()); + ss.imbue(os.stream().getloc()); + ss.width(0); + std::unique_ptr > fmt(os.clone(ss)); + print(*fmt, y); + fmt->print_times(); + print(*fmt, bar.m_w[i]); + num = ss.str(); + } + { + // (x - m_x[i]) + // + auto x = bar.m_x[i]; + std::basic_stringstream ss; + ss.copyfmt(os.stream()); + ss.imbue(os.stream().getloc()); + ss.width(0); + std::unique_ptr > fmt(os.clone(ss)); + ss << "("; + fmt->print_variable('x'); + if (x < 0) + { + x = -x; + ss << " + "; + } + else + ss << " - "; + print(*fmt, x); + ss << ")"; + denom = ss.str(); + } + os.print_fraction(num, denom); + } + // " Q(x) = " + os.stream() << " "; + os.print_special_character(0x2227); + os.stream() << " "; + os.print_name("Q"); + os.stream() << "("; + os.print_variable('x'); + os.stream() << ") = "; + + for (size_t i = 0; i < bar.m_x.size(); ++i) + { + auto y = bar.m_y[i]; + if (i) + { + if (y > 0) + os.stream() << " + "; + else + { + y = -y; + os.stream() << " - "; + } + } + std::basic_string num, denom; + num = os.part_as_string(y); + { + // (x - m_x[i]) + // + auto x = bar.m_x[i]; + std::basic_stringstream ss; + ss.copyfmt(os.stream()); + ss.imbue(os.stream().getloc()); + ss.width(0); + std::unique_ptr > fmt(os.clone(ss)); + ss << "("; + fmt->print_variable('x'); + if (x < 0) + { + x = -x; + ss << " + "; + } + else + ss << " - "; + print(*fmt, x); + ss << ")"; + denom = ss.str(); + } + os.print_fraction(num, denom); + } +#if 0 + Real t = m_w[i] / (x - m_x[i]); + numerator += t * m_y[i]; + denominator += t; +#endif + } + private: void calculate_weights(size_t approximation_order); diff --git a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp index 4b543641a2..82b781008d 100644 --- a/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp @@ -14,7 +14,18 @@ #include #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +namespace boost{ namespace math{ + + namespace tools + { + // Forward declaration only, we don't need the formatter's + // definition to be able to define a print function (only if + // we actually use it). + template + class basic_numeric_printer_base; + } + +namespace interpolators{ namespace detail{ template @@ -34,6 +45,80 @@ class cardinal_cubic_b_spline_imp Real double_prime(Real x) const; + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_cubic_b_spline_imp& spline) + { + typedef boost::math::tools::basic_numeric_printer_base printer_t; + // + // scoped_prolog is responsible for writing the prolog/epilog code + // to the stream, if the output format requires it. Not a number in it's own + // right, but an expression, so set the name to the empty string and let each + // individual number style itself. + // + typename printer_t::scoped_prolog prolog(&os, ""); + // + // scoped_parenthesis instructs nested types to wrap themselves in () + // if they are compound rather than atomic number types (for example complex numbers): + // + typename printer_t::scoped_parenthesis param(&os); + // + // scoped_styling: turns off styling for nested types: + // this means that this whole thing will be styled as one + // "number" rather than as several seperate ones. + // Disabled here, as we'll leave the sub-components to style themselves. + // + // typename printer_t::scoped_styling style(&os); + + print(os, spline.m_avg); + for (int64_t k = 0; k < int64_t(spline.m_beta.size()); ++k) + { + auto alpha = spline.m_beta[k]; + if (alpha < 0) + { + os.stream() << " - "; + alpha = -alpha; + } + else + { + os.stream() << " + "; + } + if (os.part_as_plain_text(alpha) != "1") + { + print(os, alpha); + os.print_times(); + } + os.print_name("B"); + os.print_subscript("3"); + os.stream() << "("; + print(os, spline.m_h_inv); + os.stream() << "("; + os.print_variable('x'); + if (spline.m_a < 0) + { + os.stream() << " + "; + print(os, -spline.m_a); + } + else + { + os.stream() << " - "; + print(os, spline.m_a); + } + os.stream() << ")"; + auto t = 1 - k; + if (t > 0) + { + os.stream() << " + "; + print(os, t); + } + else if (t < 0) + { + os.stream() << " - "; + print(os, -t); + } + os.stream() << ")"; + } + } + private: std::vector m_beta; Real m_h_inv; @@ -112,7 +197,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B if (length < 5) { - if (boost::math::isnan(left_endpoint_derivative) || boost::math::isnan(right_endpoint_derivative)) + if ((boost::math::isnan)(left_endpoint_derivative) || (boost::math::isnan)(right_endpoint_derivative)) { throw std::logic_error("Interpolation using a cubic b spline with derivatives estimated at the endpoints requires at least 5 points.\n"); } @@ -122,7 +207,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B } } - if (boost::math::isnan(left_endpoint)) + if ((boost::math::isnan)(left_endpoint)) { throw std::logic_error("Left endpoint is NAN; this is disallowed.\n"); } @@ -144,7 +229,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B // to construct high-order estimates for one-sided derivatives: // https://en.wikipedia.org/wiki/Finite_difference_coefficient#Forward_and_backward_finite_difference // Here, we estimate then to O(h^4), as that is the maximum accuracy we could obtain from this method. - if (boost::math::isnan(a1)) + if ((boost::math::isnan)(a1)) { // For simple functions (linear, quadratic, so on) // almost all the error comes from derivative estimation. @@ -155,7 +240,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B } Real b1 = right_endpoint_derivative; - if (boost::math::isnan(b1)) + if ((boost::math::isnan)(b1)) { size_t n = length - 1; Real t0 = 4*(f[n-3] + third()*f[n - 1]); @@ -177,7 +262,7 @@ cardinal_cubic_b_spline_imp::cardinal_cubic_b_spline_imp(BidiIterator f, B Real t = 1; for (size_t i = 0; i < length; ++i) { - if (boost::math::isnan(f[i])) + if ((boost::math::isnan)(f[i])) { std::string err = "This function you are trying to interpolate is a nan at index " + std::to_string(i) + "\n"; throw std::logic_error(err); diff --git a/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp index 4998348ce6..cc105ec92b 100644 --- a/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_quadratic_b_spline_detail.hpp @@ -8,7 +8,18 @@ #define BOOST_MATH_INTERPOLATORS_CARDINAL_QUADRATIC_B_SPLINE_DETAIL_HPP #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +namespace boost{ namespace math{ + +namespace tools +{ + // Forward declaration only, we don't need the formatter's + // definition to be able to define a print function (only if + // we actually use it). + template + class basic_numeric_printer_base; +} + +namespace interpolators{ namespace detail{ template Real b2_spline(Real x) { @@ -72,7 +83,7 @@ class cardinal_quadratic_b_spline_detail using std::isnan; Real a; - if (isnan(left_endpoint_derivative)) { + if ((isnan)(left_endpoint_derivative)) { // http://web.media.mit.edu/~crtaylor/calculator.html a = -3*y[0] + 4*y[1] - y[2]; } @@ -81,7 +92,7 @@ class cardinal_quadratic_b_spline_detail } Real b; - if (isnan(right_endpoint_derivative)) { + if ((isnan)(right_endpoint_derivative)) { b = 3*y[n-1] - 4*y[n-2] + y[n-3]; } else { @@ -196,6 +207,85 @@ class cardinal_quadratic_b_spline_detail return m_t0 + (m_alpha.size()-3)/m_inv_h; } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_quadratic_b_spline_detail& spline) + { + typedef boost::math::tools::basic_numeric_printer_base printer_t; + // + // scoped_prolog is responsible for writing the prolog/epilog code + // to the stream, if the output format requires it. Not a number in it's own + // right, but an expression, so set the name to the empty string and let each + // individual number style itself. + // + typename printer_t::scoped_prolog prolog(&os, ""); + // + // scoped_parenthesis instructs nested types to wrap themselves in () + // if they are compound rather than atomic number types (for example complex numbers): + // + typename printer_t::scoped_parenthesis param(&os); + + bool have_first = false; + + for (size_t j = 0; j < spline.m_alpha.size(); ++j) + { + auto alpha = spline.m_alpha[j]; + if (have_first) + { + if (alpha < 0) + { + alpha = -alpha; + os.stream() << " - "; + } + else + os.stream() << " + "; + } + else + have_first = true; + + auto sa = os.part_as_plain_text(alpha); + if (sa == "1") { } + else if (sa == "-1") + { + os.stream() << "-"; + } + else + { + print(os, alpha); + os.print_times(); + } + os.print_name("B"); + os.print_subscript("2"); + os.stream() << "("; + print(os, spline.m_inv_h); + os.stream() << "("; + os.print_variable('x'); + if (spline.m_t0 < 0) + { + os.stream() << " + "; + print(os, -spline.m_t0); + } + else + { + os.stream() << " - "; + print(os, spline.m_t0); + } + os.stream() << ")"; + std::ptrdiff_t k = 1 - j; + if (k < 0) + { + os.stream() << " - "; + print(os, -k); + } + else if (k > 0) + { + os.stream() << " + "; + print(os, k); + } + os.stream() << ")"; + } + } + + private: std::vector m_alpha; Real m_inv_h; diff --git a/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp b/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp index 09ce63d827..a4f325348c 100644 --- a/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp +++ b/include/boost/math/interpolators/detail/cardinal_quintic_b_spline_detail.hpp @@ -11,7 +11,19 @@ #include #include -namespace boost{ namespace math{ namespace interpolators{ namespace detail{ +namespace boost{ namespace math{ + +namespace tools +{ + // Forward declaration only, we don't need the formatter's + // definition to be able to define a print function (only if + // we actually use it). + template + class basic_numeric_printer_base; +} + + +namespace interpolators{ namespace detail{ template @@ -42,19 +54,19 @@ class cardinal_quintic_b_spline_detail using std::isnan; // This interpolator has error of order h^6, so the derivatives should be estimated with the same error. // See: https://en.wikipedia.org/wiki/Finite_difference_coefficient - if (isnan(left_endpoint_derivatives.first)) { + if ((isnan)(left_endpoint_derivatives.first)) { Real tmp = -49*y[0]/20 + 6*y[1] - 15*y[2]/2 + 20*y[3]/3 - 15*y[4]/4 + 6*y[5]/5 - y[6]/6; left_endpoint_derivatives.first = tmp/h; } - if (isnan(right_endpoint_derivatives.first)) { + if ((isnan)(right_endpoint_derivatives.first)) { Real tmp = 49*y[n-1]/20 - 6*y[n-2] + 15*y[n-3]/2 - 20*y[n-4]/3 + 15*y[n-5]/4 - 6*y[n-6]/5 + y[n-7]/6; right_endpoint_derivatives.first = tmp/h; } - if(isnan(left_endpoint_derivatives.second)) { + if((isnan)(left_endpoint_derivatives.second)) { Real tmp = 469*y[0]/90 - 223*y[1]/10 + 879*y[2]/20 - 949*y[3]/18 + 41*y[4] - 201*y[5]/10 + 1019*y[6]/180 - 7*y[7]/10; left_endpoint_derivatives.second = tmp/(h*h); } - if (isnan(right_endpoint_derivatives.second)) { + if ((isnan)(right_endpoint_derivatives.second)) { Real tmp = 469*y[n-1]/90 - 223*y[n-2]/10 + 879*y[n-3]/20 - 949*y[n-4]/18 + 41*y[n-5] - 201*y[n-6]/10 + 1019*y[n-7]/180 - 7*y[n-8]/10; right_endpoint_derivatives.second = tmp/(h*h); } @@ -186,6 +198,84 @@ class cardinal_quintic_b_spline_detail return s; } + template + friend void print(boost::math::tools::basic_numeric_printer_base& os, const cardinal_quintic_b_spline_detail& spline) + { + typedef boost::math::tools::basic_numeric_printer_base printer_t; + // + // scoped_prolog is responsible for writing the prolog/epilog code + // to the stream, if the output format requires it. Not a number in it's own + // right, but an expression, so set the name to the empty string and let each + // individual number style itself. + // + typename printer_t::scoped_prolog prolog(&os, ""); + // + // scoped_parenthesis instructs nested types to wrap themselves in () + // if they are compound rather than atomic number types (for example complex numbers): + // + typename printer_t::scoped_parenthesis param(&os); + + bool have_first = false; + + for (size_t j = 0; j < spline.m_alpha.size(); ++j) + { + auto alpha = spline.m_alpha[j]; + if (have_first) + { + if (alpha < 0) + { + alpha = -alpha; + os.stream() << " - "; + } + else + os.stream() << " + "; + } + else + have_first = true; + + auto sa = os.part_as_plain_text(alpha); + if (sa == "1") {} + else if (sa == "-1") + { + os.stream() << "-"; + } + else + { + print(os, alpha); + os.print_times(); + } + os.print_name("B"); + os.print_subscript("5"); + os.stream() << "("; + print(os, spline.m_inv_h); + os.stream() << "("; + os.print_variable('x'); + if (spline.m_t0 < 0) + { + os.stream() << " + "; + print(os, -spline.m_t0); + } + else + { + os.stream() << " - "; + print(os, spline.m_t0); + } + os.stream() << ")"; + std::ptrdiff_t k = j + 2; + if (k < 0) + { + os.stream() << " - "; + print(os, -k); + } + else if (k > 0) + { + os.stream() << " + "; + print(os, k); + } + os.stream() << ")"; + } + } + Real prime(Real t) const { using std::ceil; using std::floor; diff --git a/include/boost/math/tools/formatting.hpp b/include/boost/math/tools/formatting.hpp new file mode 100644 index 0000000000..126acb44c4 --- /dev/null +++ b/include/boost/math/tools/formatting.hpp @@ -0,0 +1,1197 @@ +// (C) Copyright John Maddock 2019. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MATH_TOOLS_FORMATTING_HPP +#define BOOST_MATH_TOOLS_FORMATTING_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma once +#endif + +namespace boost { + + template + struct rational; + + namespace math { + namespace tools { + + template + T numerator(const boost::rational& r) { return r.numerator(); } + template + T denominator(const boost::rational& r) { return r.denominator(); } + + namespace detail { + + template ::value || boost::is_class::value> + struct is_integer_like + { + static const bool value = false; + }; + template + struct is_integer_like + { + static const bool value = std::numeric_limits::is_integer; + }; + + template ::value || boost::is_class::value> + struct is_float_like + { + // The point "floats": + static const bool value = false; + }; + + template + using real_t = decltype(std::declval().real(std::declval().imag())); + template + using imag_t = decltype(std::declval().imag(std::declval().real())); + template + using polynomial_t = decltype(std::declval()(std::declval()[0])); + template + using polynomial2_t = decltype(std::declval().degree()); + template + using rational_t = decltype(numerator(std::declval()) + denominator(std::declval())); + template + using interval_t = decltype(singleton(std::declval()) + intersect(std::declval(), std::declval()) + median(std::declval())); + + template + struct is_complex_like + { + static const bool value = boost::is_detected_v && boost::is_detected_v; + }; + + template + struct is_polynomial_like + { + static const bool value = boost::is_detected_v && boost::is_detected_v; + }; + + template + struct is_rational_like + { + static const bool value = boost::is_detected_v; + }; + + template + struct is_interval_like + { + static const bool value = boost::is_detected_v; + }; + + template + struct is_float_like + { + // The point "floats": + static const bool value = (std::numeric_limits::max_exponent != std::numeric_limits::min_exponent) && !is_interval_like::value; + }; + + template + struct is_unhandled_type + { + static const bool value = !is_complex_like::value && !is_float_like::value && !is_integer_like::value && !is_polynomial_like::value && !is_rational_like::value; + }; + + template + typename boost::enable_if_c::type print_unicode_char(std::basic_ostream & os, std::uint32_t code_point) + { + std::uint32_t u[2] = { code_point, 0 }; + boost::u32_to_u8_iterator i(u), j(&u[0] + 1); + while (i != j) + { + os.put(*i++); + } + } + template + typename boost::enable_if_c::type print_unicode_char(std::basic_ostream & os, std::uint32_t code_point) + { + std::uint32_t u[2] = { code_point, 0 }; + boost::u32_to_u16_iterator i(u), j(&u[0] + 1); + while (i != j) + { + os.put(*i++); + } + } + template + typename boost::enable_if_c::type print_unicode_char(std::basic_ostream & os, std::uint32_t code_point) + { + os.put(code_point); + } + + template + void print_unicode_superscript(std::basic_ostream & os, std::basic_string digits) + { + for (std::size_t i = 0; i < digits.size(); ++i) + { + switch (digits[i]) + { + case '0': + print_unicode_char(os, 0x2070); + break; + case '1': + print_unicode_char(os, 0xB9); + break; + case '2': + print_unicode_char(os, 0xB2); + break; + case '3': + print_unicode_char(os, 0xB3); + break; + case '4': + print_unicode_char(os, 0x2074); + break; + case '5': + print_unicode_char(os, 0x2075); + break; + case '6': + print_unicode_char(os, 0x2076); + break; + case '7': + print_unicode_char(os, 0x2076); + break; + case '8': + print_unicode_char(os, 0x2078); + break; + case '9': + print_unicode_char(os, 0x2079); + break; + case '+': + print_unicode_char(os, 0x207A); + break; + case '-': + print_unicode_char(os, 0x207B); + break; + case '(': + print_unicode_char(os, 0x207D); + break; + case ')': + print_unicode_char(os, 0x207E); + break; + case 'n': + print_unicode_char(os, 0x207F); + break; + case '=': + print_unicode_char(os, 0x207C); + break; + case 'i': + print_unicode_char(os, 0x2071); + break; + case 'x': + print_unicode_char(os, 0x02e3); + break; + case '.': + print_unicode_char(os, 0x22C5); + break; + default: + os.put(digits[i]); + } + } + } + + template + void print_unicode_subscript(std::basic_ostream & os, std::basic_string digits) + { + for (std::size_t i = 0; i < digits.size(); ++i) + { + if ((digits[i] >= '0') && (digits[i] <= '9')) + print_unicode_char(os, 0x2080 + (digits[i] - '0')); + else if (digits[i] == '-') + print_unicode_char(os, 0x208B); + else if (digits[i] == '+') + print_unicode_char(os, 0x208A); + else if (digits[i] == '(') + print_unicode_char(os, 0x208D); + else if (digits[i] == ')') + print_unicode_char(os, 0x208E); + else if (digits[i] == 'n') + print_unicode_char(os, 0x2099); + else if (digits[i] == 'x') + print_unicode_char(os, 0x2093); + else + os.put(digits[i]); + } + } + + template + typename boost::enable_if_c::type unicode_character_len(const charT* p) + { + std::size_t l = 0; + for (unsigned i = 0; p && p[i]; ++i) + ++l; + boost::u8_to_u32_iterator i(p), j(p + l); + return std::distance(i, j); + } + template + typename boost::enable_if_c::type unicode_character_len(const charT* p) + { + std::size_t l = 0; + for (unsigned i = 0; p && p[i]; ++i) + ++l; + boost::u16_to_u32_iterator i(p), j(p + l); + return std::distance(i, j); + } + template + typename boost::enable_if_c::type unicode_character_len(const charT* p) + { + std::size_t l = 0; + for (unsigned i = 0; p && p[i]; ++i) + ++l; + return l; + } + + template + typename boost::enable_if_c::value, bool>::type iszero(const T& val) + { + return (val.real() == 0) && (val.imag() == 0); + } + template + typename boost::disable_if_c::value, bool>::type iszero(const T& val) + { + return val == 0; + } + template + typename boost::enable_if_c::value, bool>::type isneg(const T& val) + { + return (val.real() < 0); + } + template + typename boost::disable_if_c::value, bool>::type isneg(const T& val) + { + return val < 0; + } + + } // namespace detail + + enum output_print_t + { + text_format, + docbook_format, + latex_format, + html_format + }; + + enum styling_level_t + { + no_styling = 0, + minimal_styling = 1, + full_styling = 6 + }; + + enum multiplyer_t + { + multiply_times = 0, + multiply_dot = 1, + multiply_x = 2 + }; + + enum imaginary_i_t + { + upright_i = 0, + slanted_i = 1, + doublestruck_i = 2 + }; + + enum zero_component_t + { + hide_zero_components = 0, + show_zero_components = 1 + }; + + enum latex_t + { + latex_as_text = 1, + latex_as_equation = 0 + }; + + enum unicode_text_t + { + unicode_text_output = 0, + ascii_text_output = 1 + }; + + template > + class basic_numeric_printer; + template + class basic_numeric_printer_base; + + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Value& value) + { + typename basic_numeric_printer_base::scoped_prolog s(&os, "integer"); + os.stream() << value; + } + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Value& f) + { + using std::isinf; + using std::isnan; + + typename basic_numeric_printer_base::scoped_prolog s(&os, "float"); + + if ((isinf)(f)) + { + if (f < 0) + os.stream() << "-"; + os.print_special_character(0x221E); + return; + } + if ((isnan)(f)) + { + os.print_name("NaN"); + return; + } + std::basic_string mantissa, exponent; + os.decompose_float(os.stream(), f, mantissa, exponent); + os.stream() << mantissa; + if (exponent.size()) + { + os.print_times(); + os.stream() << "10"; + os.print_superscript(exponent); + } + return; + } + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Complex& f) + { + using std::isnan; + using std::isinf; + + typename basic_numeric_printer_base::scoped_prolog s1(&os, "complex"); + typename basic_numeric_printer_base::scoped_styling s2(&os); + + if ((isnan)(f.real()) || (isnan)(f.imag())) + { + os.print_name("NaN"); + return; + } + else if ((isinf)(f.real()) || (isinf)(f.imag())) + { + os.print_complex_infinity(); + return; + } + else if ((!os.show_zero_components()) && (f.imag() == 0)) + { + print(os, f.real()); + return; + } + else if ((!os.show_zero_components()) && (f.real() == 0)) + { + print(os, f.imag()); + } + else + { + if (os.parenthesis()) + os.stream() << "("; + print(os, f.real()); + typename Complex::value_type i(f.imag()); + bool isneg = i < 0; + if (isneg) + { + i = -i; + os.stream() << " - "; + } + else + os.stream() << " + "; + print(os, i); + } + os.print_imaginary_unit(); + if (os.parenthesis() && !((!os.show_zero_components()) && (f.real() == 0))) + os.stream() << ")"; + return; + } + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Value& f) + { + typename basic_numeric_printer_base::scoped_prolog s1(&os, "polynomial"); + typename basic_numeric_printer_base::scoped_parenthesis s2(&os); + typename basic_numeric_printer_base::scoped_styling s3(&os); + + bool have_first = false; + for (unsigned i = 0; i <= f.degree(); ++i) + { + auto coef = f[i]; + if (os.show_zero_components() || (!detail::iszero(coef))) + { + if (have_first) + { + if (!detail::isneg(coef)) + os.stream() << " + "; + else + { + os.stream() << " - "; + coef = -coef; + } + } + auto s = os.part_as_plain_text(coef); + if((s != "1") || !i) + print(os, coef); + have_first = true; + if (i) + { + os.print_variable('x'); + if (i > 1) + { + std::basic_stringstream ss; + ss << i; + std::basic_string s = ss.str(); + os.print_superscript(s); + } + } + } + } + } + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Value& rat) + { + typename basic_numeric_printer_base::scoped_prolog s1(&os, "rational"); + typename basic_numeric_printer_base::scoped_styling s3(&os); + + auto num = numerator(rat); + auto denom = denominator(rat); + + if ((num == 0) || (denom == 1)) + { + print(os, num); + return; + } + else + { + if (detail::isneg(num)) + { + os.stream() << "-"; + num = -num; + } + if (os.parenthesis()) + os.stream() << "("; + { + typename basic_numeric_printer_base::scoped_parenthesis s2(&os); + + auto str1 = os.part_as_string(num); + auto str2 = os.part_as_string(denom); + + os.print_fraction(str1, str2); + } + if (os.parenthesis()) + os.stream() << ")"; + } + } + + template + typename boost::enable_if_c::value>::type print(basic_numeric_printer_base& os, const Value& val) + { + typename basic_numeric_printer_base::scoped_prolog s1(&os, "interval"); + typename basic_numeric_printer_base::scoped_styling s3(&os); + + if (singleton(val)) + { + print(os, lower(val)); + return; + } + else + { + auto med = median(val); + auto rad = width(val); + rad /= 2; + + if (os.parenthesis()) + os.stream() << "("; + { + typename basic_numeric_printer_base::scoped_parenthesis s2(&os); + print(os, med); + os.stream() << " "; + os.print_special_character(0xB1); + os.stream() << " "; + print(os, rad); + } + if (os.parenthesis()) + os.stream() << ")"; + } + } + + template + using printable_t = decltype(print(std::declval(), std::declval())); + + template + struct is_printable + { + static const bool value = boost::is_detected_v; + }; + + + template + class basic_numeric_printer_base + { + styling_level_t styling_level; + imaginary_i_t i_style; + multiplyer_t multiply_style; + std::size_t m_parenthesis; + bool m_show_zero_components; + bool m_use_unicode; + std::basic_ostream* p_stream; + public: + template + static void decompose_float(std::basic_ostream& os, const Float& f, std::basic_string& mantissa, std::basic_string& exponent) + { + static const charT exponent_string[3] = { 'e', 'E', 0 }; + std::basic_stringstream ss; + ss.copyfmt(os); + ss.imbue(os.getloc()); + ss << f; + std::basic_string s = ss.str(); + typename std::basic_string::size_type pos = s.find_first_of(exponent_string); + if (pos != std::basic_string::npos) + { + mantissa.assign(s, 0, pos); + exponent.assign(s, pos + 1, s.size() - pos - 1); + } + else + mantissa = s; + } + basic_numeric_printer_base(std::basic_ostream& os) + : styling_level(full_styling), i_style(upright_i), multiply_style(multiply_times), + m_parenthesis(0), m_show_zero_components(false), m_use_unicode(true), p_stream(&os) {} + basic_numeric_printer_base(std::basic_ostream& os, const basic_numeric_printer_base& o) + : styling_level(o.styling_level), i_style(o.i_style), multiply_style(o.multiply_style), + m_parenthesis(o.m_parenthesis), m_show_zero_components(o.m_show_zero_components), m_use_unicode(o.m_use_unicode), p_stream(&os) {} + + void styling(styling_level_t i) + { + styling_level = i; + } + styling_level_t styling()const + { + return styling_level; + } + void imaginary_style(imaginary_i_t i) + { + i_style = i; + } + imaginary_i_t imaginary_style()const + { + return i_style; + } + void multiply(multiplyer_t t) + { + multiply_style = t; + } + multiplyer_t multiply()const + { + return multiply_style; + } + void parenthesis(std::size_t b) + { + m_parenthesis = b; + } + std::size_t parenthesis()const + { + return m_parenthesis; + } + void show_zero_components(bool b) + { + m_show_zero_components = b; + } + bool show_zero_components()const + { + return m_show_zero_components; + } + void use_unicode(bool b) + { + m_use_unicode = b; + } + bool use_unicode()const + { + return m_use_unicode; + } + + std::basic_ostream& stream() + { + return *p_stream; + } + + struct scoped_parenthesis + { + basic_numeric_printer_base* m_formatter; + scoped_parenthesis(basic_numeric_printer_base* formatter) : m_formatter(formatter) + { + m_formatter->parenthesis(1 + m_formatter->parenthesis()); + } + ~scoped_parenthesis() + { + m_formatter->parenthesis(m_formatter->parenthesis() - 1); + } + }; + struct scoped_styling + { + basic_numeric_printer_base* m_formatter; + styling_level_t saved_style; + scoped_styling(basic_numeric_printer_base* formatter) : m_formatter(formatter) + { + saved_style = m_formatter->styling(); + m_formatter->styling(no_styling); + } + ~scoped_styling() + { + m_formatter->styling(saved_style); + } + }; + struct scoped_prolog + { + basic_numeric_printer_base* m_formatter; + const char* m_type; + scoped_prolog(basic_numeric_printer_base* formatter, const char* number_type) : m_formatter(formatter), m_type(number_type) + { + m_formatter->print_prolog(number_type); + } + ~scoped_prolog() + { + m_formatter->print_epilog(m_type); + } + }; + + virtual void print_prolog(const char*) {} + virtual void print_epilog(const char*) {} + virtual void print_special_character(boost::uint32_t unicode_value) + { + if (use_unicode()) + detail::print_unicode_char(this->stream(), unicode_value); + else + { + switch (unicode_value) + { + case 0x221E: + stream() << "INFINITY"; + break; + case 0xD7: + case 0x22C5: + stream() << "x"; + break; + case 0x2044: + stream() << "/"; + break; + default: + throw std::runtime_error("Unsuported Unicode character encountered in plain text output"); + } + } + } + virtual void print_times() + { + if (multiply() == multiply_times) + print_special_character(0xD7); + else if (multiply() == multiply_dot) + print_special_character(0x22C5); + else + print_name("x"); + } + virtual void print_superscript(const std::basic_string& s) + { + if (use_unicode()) + detail::print_unicode_superscript(stream(), s); + else + stream() << "^" << s; + } + virtual void print_imaginary_unit() + { + if ((use_unicode()) && (this->imaginary_style() == doublestruck_i)) + detail::print_unicode_char(stream(), 0x2148); + else if ((use_unicode()) && (this->imaginary_style() == slanted_i)) + detail::print_unicode_char(stream(), 0x1D456); + else + stream().put(stream().widen('i')); + } + virtual void print_complex_infinity() + { + if (use_unicode()) + { + detail::print_unicode_char(stream(), 0x221E); + } + else + stream() << "COMPLEX INFINITY"; + } + virtual void print_variable(charT c) + { + stream().put(c); + } + virtual void print_name(const std::basic_string& s) + { + stream() << s; + } + virtual void print_fraction(const std::basic_string& s1, const std::basic_string& s2) + { + print_superscript(s1); + print_special_character(0x2044); + print_subscript(s2); + } + virtual void print_subscript(const std::basic_string& s) + { + detail::print_unicode_subscript(stream(), s); + } + virtual std::unique_ptr clone(std::basic_ostream&) = 0; + + bool latex_as_equation()const { return false; } + void latex_as_equation(bool) {} + + template + std::basic_string part_as_string(const Value& value) + { + std::basic_ostringstream ss; + ss.copyfmt(stream()); + ss.imbue(stream().getloc()); + ss.width(0); + std::unique_ptr fmt(clone(ss)); + print(*fmt, value); + return ss.str(); + } + template + std::basic_string part_as_plain_text(const Value& value) + { + std::basic_ostringstream ss; + ss.copyfmt(stream()); + ss.imbue(stream().getloc()); + ss.width(0); + basic_numeric_printer fmt(ss, *this); + fmt.use_unicode(false); + print(fmt, value); + return ss.str(); + } + }; + + template + class basic_numeric_printer : public basic_numeric_printer_base + { + public: + basic_numeric_printer(std::basic_ostream& os) : basic_numeric_printer_base(os) {} + basic_numeric_printer(std::basic_ostream& os, basic_numeric_printer_base const& fmt) : basic_numeric_printer_base(os, fmt) {} + virtual std::unique_ptr > clone(std::basic_ostream& os) + { + return std::unique_ptr >(new basic_numeric_printer(os, *this)); + } + }; + + template + class basic_numeric_printer : public basic_numeric_printer_base + { + friend class basic_numeric_printer_base; + public: + basic_numeric_printer(std::basic_ostream& os) : basic_numeric_printer_base(os) {} + basic_numeric_printer(std::basic_ostream& os, basic_numeric_printer const& fmt) : basic_numeric_printer_base(os, fmt) {} + + virtual void print_prolog(const char* name) + { + if (name && *name) + { + if (this->styling() >= minimal_styling) + this->stream() << ""; + if (this->styling() > minimal_styling) + this->stream() << ""; + } + } + virtual void print_epilog(const char* name) + { + if (name && *name) + { + if (this->styling() > minimal_styling) + this->stream() << ""; + if (this->styling() >= minimal_styling) + this->stream() << ""; + } + } + + virtual void print_special_character(boost::uint32_t unicode_value) + { + std::ios_base::fmtflags f = this->stream().flags() & std::ios_base::basefield; + this->stream() << std::hex << "&#x" << unicode_value << ";"; + this->stream().setf(f, std::ios_base::basefield); + BOOST_ASSERT(f == (this->stream().flags() & std::ios_base::basefield)); + } + virtual void print_superscript(const std::basic_string& s) + { + this->stream() << "" << s << ""; + } + virtual void print_imaginary_unit() + { + if (this->styling() >= minimal_styling) + this->stream() << ""; + if (this->imaginary_style() == doublestruck_i) + this->stream() << "ⅈ"; + else if (this->imaginary_style() == slanted_i) + this->stream() << "i"; + else + this->stream().put(this->stream().widen('i')); + if (this->styling() >= minimal_styling) + this->stream() << ""; + } + virtual void print_complex_infinity() + { + this->stream() << "∞̃"; + } + virtual void print_variable(charT c) + { + this->stream() << ""; + this->stream().put(c); + this->stream() << ""; + } + virtual void print_subscript(const std::basic_string& s) + { + this->stream() << "" << s << ""; + } + virtual std::unique_ptr > clone(std::basic_ostream& os) + { + return std::unique_ptr >(new basic_numeric_printer(os, *this)); + } + }; + + template + class basic_numeric_printer : public basic_numeric_printer_base + { + friend class basic_numeric_printer_base; + + bool is_latex_as_equation; + unsigned inside_equation; + + public: + basic_numeric_printer(std::basic_ostream& os) : basic_numeric_printer_base(os), is_latex_as_equation(true), inside_equation(false) {} + basic_numeric_printer(std::basic_ostream& os, basic_numeric_printer const& fmt) : basic_numeric_printer_base(os, fmt), is_latex_as_equation(fmt.is_latex_as_equation), inside_equation(fmt.inside_equation) {} + + void latex_as_equation(bool b) { is_latex_as_equation = b; } + bool latex_as_equation()const { return is_latex_as_equation; } + + virtual void print_prolog(const char*) + { + if (latex_as_equation()) + { + if(inside_equation++ == 0) + this->stream().put(this->stream().widen('$')); + } + } + virtual void print_epilog(const char*) + { + if (latex_as_equation()) + { + if(--inside_equation == 0) + this->stream().put(this->stream().widen('$')); + } + } + + virtual void print_special_character(boost::uint32_t unicode_value) + { + if (!inside_equation) + this->stream() << "$"; + switch (unicode_value) + { + case 0x221E: + this->stream() << "\\infty"; + break; + case 0xD7: + this->stream() << "\\times"; + break; + case 0x22C5: + this->stream() << "\\cdot"; + break; + case 0xB1: + this->stream() << "\\pm"; + break; + case 0x2213: + this->stream() << "\\mp"; + break; + case 0x221A: + this->stream() << "\\surd"; + break; + case 0x3B4: + this->stream() << "\\delta"; + break; + case 0x394: + this->stream() << "\\Delta"; + break; + case 0x1D70B: + this->stream() << "\\pi"; + break; + case 0x03C0: + this->stream() << "\\pi"; + break; + case 0x1D70E: + this->stream() << "\\sigma"; + break; + case 0x3c3: + this->stream() << "\\sigma"; + break; + case 0x2227: + this->stream() << "\\land"; + break; + case 0x2228: + this->stream() << "\\lor"; + break; + default: + throw std::runtime_error("Unsuported Unicode character encountered in LaTex output"); + } + if (!inside_equation) + this->stream() << "$"; + } + virtual void print_superscript(const std::basic_string& s) + { + if (inside_equation) + this->stream() << "^{" << s << "}"; + else + this->stream() << "\\textsuperscript{" << s << "}"; + } + virtual void print_imaginary_unit() + { + if (this->imaginary_style() == doublestruck_i) + BOOST_THROW_EXCEPTION(std::runtime_error("Doublestruck imaginary i not implemented for LaTex output.")); + else if ((this->imaginary_style() == upright_i) && inside_equation) + this->stream() << "\\mathrm{i}"; + else if ((this->imaginary_style() == slanted_i) && !inside_equation) + this->stream() << "\\textit{i}"; + else + this->stream().put(this->stream().widen('i')); + } + virtual void print_complex_infinity() + { + if (!inside_equation) + this->stream().put(this->stream().widen('$')); + this->stream() << "\\tilde{\\infty}"; + if (!inside_equation) + this->stream().put(this->stream().widen('$')); + } + virtual void print_variable(charT c) + { + if (inside_equation) + this->stream().put(c); + else + { + this->stream() << "\\textit{"; + this->stream().put(c); + this->stream() << "}"; + } + } + virtual void print_name(const std::basic_string& s) + { + if (!inside_equation) + this->stream() << s; + else + { + this->stream() << "\\mathrm{"; + this->stream() << s; + this->stream() << "}"; + } + } + virtual void print_fraction(const std::basic_string& s1, const std::basic_string& s2) + { + if (inside_equation) + { + this->stream() << "\\frac{" << s1 << "}{" << s2 << "}"; + } + else + { + this->print_superscript(s1); + this->stream() << "/"; + this->print_subscript(s2); + } + } + virtual void print_subscript(const std::basic_string& s) + { + if (inside_equation) + this->stream() << "_{" << s << "}"; + else + this->stream() << "\\textsubscript{" << s << "}"; + } + virtual std::unique_ptr > clone(std::basic_ostream& os) + { + return std::unique_ptr >(new basic_numeric_printer(os, *this)); + } + }; + + template + class basic_numeric_printer : public basic_numeric_printer_base + { + friend class basic_numeric_printer_base; + public: + basic_numeric_printer(std::basic_ostream& os) : basic_numeric_printer_base(os) {} + basic_numeric_printer(std::basic_ostream& os, basic_numeric_printer const & fmt) : basic_numeric_printer_base(os, fmt) {} + + virtual void print_prolog(const char* name) + { + if (name && *name) + { + if (this->styling() >= minimal_styling) + this->stream() << ""; + if (this->styling() > minimal_styling) + this->stream() << ""; + } + } + virtual void print_epilog(const char* name) + { + if (name && *name) + { + if (this->styling() > minimal_styling) + this->stream() << ""; + if (this->styling() >= minimal_styling) + this->stream() << ""; + } + } + + virtual void print_special_character(boost::uint32_t unicode_value) + { + std::ios_base::fmtflags f = this->stream().flags() & std::ios_base::basefield; + this->stream() << std::hex << "&#x" << unicode_value << ";"; + this->stream().setf(f, std::ios_base::basefield); + BOOST_ASSERT(f == (this->stream().flags() & std::ios_base::basefield)); + } + virtual void print_superscript(const std::basic_string& s) + { + this->stream() << "" << s << ""; + } + virtual void print_imaginary_unit() + { + if (this->styling() >= minimal_styling) + this->stream() << ""; + if (this->imaginary_style() == doublestruck_i) + this->stream() << "ⅈ"; + else if (this->imaginary_style() == slanted_i) + this->stream() << "i"; + else + this->stream().put(this->stream().widen('i')); + if (this->styling() >= minimal_styling) + this->stream() << ""; + } + virtual void print_complex_infinity() + { + this->stream() << "∞̃"; + } + virtual void print_variable(charT c) + { + this->stream() << ""; + this->stream().put(c); + this->stream() << ""; + } + virtual void print_subscript(const std::basic_string& s) + { + this->stream() << "" << s << ""; + } + virtual std::unique_ptr > clone(std::basic_ostream& os) + { + return std::unique_ptr >(new basic_numeric_printer(os, *this)); + } + }; + + typedef basic_numeric_printer<> text_printer; + typedef basic_numeric_printer docbook_printer; + typedef basic_numeric_printer latex_printer; + typedef basic_numeric_printer html_printer; + + typedef basic_numeric_printer wtext_printer; + typedef basic_numeric_printer wdocbook_printer; + typedef basic_numeric_printer wlatex_printer; + typedef basic_numeric_printer whtml_printer; + + template + typename boost::enable_if_c, Value>::value, basic_numeric_printer&>::type operator << (basic_numeric_printer& os, const Value& i) + { + std::size_t w = (std::size_t)os.stream().width(); + if (w) + { + std::basic_string s = os.part_as_string(i); + std::size_t len = detail::unicode_character_len(s.c_str()); + if (len < w) + { + auto pos = os.stream().flags() & std::ios_base::adjustfield; + s.insert(pos == std::ios_base::left ? s.end() : s.begin(), w - len, os.stream().fill()); + } + os.stream() << s; + } + else + print(os, i); + return os; + } + + template + typename boost::disable_if_c, T>::value, basic_numeric_printer&>::type operator<< (basic_numeric_printer& os, const T& unhandled) + { + os.stream() << unhandled; + return os; + } + // + // Manipulators: + // + template + basic_numeric_printer& operator << (basic_numeric_printer& os, styling_level_t s) + { + os.styling(s); + return os; + } + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, multiplyer_t s) + { + os.multiply(s); + return os; + } + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, latex_t l) + { + os.latex_as_equation(l == latex_as_equation); + return os; + } + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, const imaginary_i_t i) + { + os.imaginary_style(i); + return os; + } + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, const zero_component_t z) + { + os.show_zero_components(z == ::boost::math::tools::show_zero_components ? true : false); + return os; + } + + template + basic_numeric_printer& operator << (basic_numeric_printer& os, const unicode_text_t z) + { + os.use_unicode(z == ::boost::math::tools::unicode_text_output ? true : false); + return os; + } + + // + // Output formatters: + // + template + basic_numeric_printer& operator<< (basic_numeric_printer& os, std::basic_ostream& (*pf)(std::basic_ostream&)) + { + pf(os.stream()); + return os; + } + template + basic_numeric_printer& operator<< (basic_numeric_printer& os, std::basic_ios& (*pf)(std::basic_ios&)) + { + pf(os.stream()); + return os; + } + template + basic_numeric_printer& operator<< (basic_numeric_printer& os, std::ios_base& (*pf)(std::ios_base&)) + { + pf(os.stream()); + return os; + } + } + } +} + +#endif // BOOST_MATH_TOOLS_FORMATTING_HPP + diff --git a/test/.temps/boost-no-inspect b/test/.temps/boost-no-inspect deleted file mode 100644 index e69de29bb2..0000000000