From 3cc6ba9a664af32839b7860d87ad13e1ab6317a1 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 17 Apr 2024 21:23:20 -0400 Subject: [PATCH 01/38] xo-ratio: initial commit --- CMakeLists.txt | 57 +++ LICENSE | 29 ++ README.md | 26 ++ cmake/xo-bootstrap-macros.cmake | 15 + cmake/xo_ratioConfig.cmake.in | 17 + example/CMakeLists.txt | 3 + example/ex1/CMakeLists.txt | 15 + example/ex1/ex1.cpp | 194 ++++++++++ include/xo/ratio/numeric_concept.hpp | 39 ++ include/xo/ratio/ratio.hpp | 547 +++++++++++++++++++++++++++ include/xo/ratio/ratio_concept.hpp | 29 ++ include/xo/ratio/ratio_iostream.hpp | 42 ++ 12 files changed, 1013 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/xo-bootstrap-macros.cmake create mode 100644 cmake/xo_ratioConfig.cmake.in create mode 100644 example/CMakeLists.txt create mode 100644 example/ex1/CMakeLists.txt create mode 100644 example/ex1/ex1.cpp create mode 100644 include/xo/ratio/numeric_concept.hpp create mode 100644 include/xo/ratio/ratio.hpp create mode 100644 include/xo/ratio/ratio_concept.hpp create mode 100644 include/xo/ratio/ratio_iostream.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..077f1267 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,57 @@ +# xo-ratio/CMakeLists.txt + +cmake_minimum_required(VERSION 3.10) + +project(xo_ratio VERSION 1.0) +enable_language(CXX) + +# common XO cmake macros (see proj/xo-cmake) +include(cmake/xo-bootstrap-macros.cmake) + +# ---------------------------------------------------------------- +# unit test setup + +enable_testing() +# activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON) +add_code_coverage() + +# 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc. +# we're not interested in code coverage for these sources. +# 2. exclude the utest/ subdir, we don't need coverage on the unit tests themselves; +# rather, want coverage on the code that the unit tests exercise. +# +# NOTE: this seems to work only with the 'ccov-all' target. In particular, doesn't seem to do anything with the 'ccov' target +# +add_code_coverage_all_targets(EXCLUDE /nix/store/* ${PROJECT_SOURCE_DIR}/utest/* ${PROJECT_BINARY_DIR}/local/* ${PROJECT_SOURCE_DIR}/repo/*) + +# ---------------------------------------------------------------- +# c++ settings + +# one-time project-specific c++ flags. usually empty +set(PROJECT_CXX_FLAGS "") +#set(PROJECT_CXX_FLAGS "-fconcepts-diagnostics-depth=2") +add_definitions(${PROJECT_CXX_FLAGS}) + +xo_toplevel_compile_options() + +# ---------------------------------------------------------------- + +add_subdirectory(example) +#add_subdirectory(utest) +#add_subdirectory(docs) + +# ---------------------------------------------------------------- +# provide find_package() support for projects using this library + +set(SELF_LIB xo_ratio) +xo_add_headeronly_library(${SELF_LIB}) +xo_install_library4(${SELF_LIB} ${PROJECT_NAME}Targets) +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# ---------------------------------------------------------------- +# dependencies + +#xo_headeronly_dependency(${SELF_LIB} randomgen) +# etc.. + +# end CMakeLists.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..cae3cb5d --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2024 Roland Conybeare , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. diff --git a/README.md b/README.md new file mode 100644 index 00000000..722ea8bf --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# ratio library + +Header-only, constexpr library providing exact representation for rational numbers. + +Relative to `std::ratio`: +1. Uses `constexpr` instead of creating new types. + This means it can be used seamlessly at runtime. +2. Supports a few more arithmetic operations, + for example exponentiation to integer powers. +3. Provides concept support (with c++20) +4. Requires modern (c++17) support to achieve this + +## Getting Started + +### install dependencies + +- [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake) cmake macros + +### build + install +``` +$ cd xo-ratio +$ PREFIX=/usr/local # for example +$ BUILDDIR=.build # for example +$ make ${BUILDDIR} +$ cmake -DCMAKE_PREFIX_PATH=${PREFIX} -B ${BUILDDIR} +``` diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..936a1810 --- /dev/null +++ b/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,15 @@ +if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL "prefix")) + # default to typical install location for xo-project-macros + set(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/cmake) +endif() + +if (NOT XO_SUBMODULE_BUILD) + message("-- GUESSED_CMAKE_CMD=cmake -DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -B ${CMAKE_BINARY_DIR}") + message("-- CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") + message("-- CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") +endif() + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo-project-macros) diff --git a/cmake/xo_ratioConfig.cmake.in b/cmake/xo_ratioConfig.cmake.in new file mode 100644 index 00000000..e5ee1778 --- /dev/null +++ b/cmake/xo_ratioConfig.cmake.in @@ -0,0 +1,17 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# note: changes to find_dependency() calls here +# must coordinate with xo_dependency() calls +# in xo-reactor/src/reactor/CMakeLists.txt +# +#find_dependency(reflect) +#find_dependency(subsys) +#find_dependency(Eigen3) +#find_dependency(webutil) +#find_dependency(printjson) +#find_dependency(callback) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..36200e18 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,3 @@ +# xo-ratio/example/CMakeLists.txt + +add_subdirectory(ex1) diff --git a/example/ex1/CMakeLists.txt b/example/ex1/CMakeLists.txt new file mode 100644 index 00000000..b7050cfc --- /dev/null +++ b/example/ex1/CMakeLists.txt @@ -0,0 +1,15 @@ +# xo-ratio/example/ex1/CMakeLists.txt + +set(SELF_EXE xo_ratio_ex1) +set(SELF_SRCS ex1.cpp) + +add_executable(${SELF_EXE} ${SELF_SRCS}) +xo_include_options2(${SELF_EXE}) + +# ---------------------------------------------------------------- +# dependencies.. + +xo_self_dependency(${SELF_EXE} xo_ratio) +xo_dependency(${SELF_EXE} reflect) + +# end CMakeLists.txt diff --git a/example/ex1/ex1.cpp b/example/ex1/ex1.cpp new file mode 100644 index 00000000..8aa3c82d --- /dev/null +++ b/example/ex1/ex1.cpp @@ -0,0 +1,194 @@ +/** @file ex1.cpp **/ + +#include "xo/ratio/ratio_iostream.hpp" +#include + +int +main() { + using xo::ratio::make_ratio; + using xo::ratio::ratio; + using xo::ratio::ratio_concept; + using namespace std; + + constexpr auto r1 = make_ratio(2, 3); + cerr << "r1=make_ratio(2,3): " << r1 << endl; // output + + static_assert(r1.num() == 2); + static_assert(r1.den() == 3); + + static_assert(r1.compare(r1, r1) == 0); + static_assert(xo::ratio::detail::op_aux_type::compare(r1,r1) == 0); + + static_assert(r1 == r1); + static_assert(!(r1 != r1)); + static_assert(r1 != 0); + static_assert(r1 != 1); + static_assert(r1 != 2); + static_assert(r1 != 3); + + static_assert(r1 >= r1); + static_assert(r1 <= r1); + + static_assert(r1 > 0); + static_assert(r1 >= 0); + static_assert(r1 < 1); + static_assert(r1 <= 1); + + constexpr auto r2 = make_ratio(2, 4); + cerr << "r2=make_ratio(2,4): " << r2 << endl; // output + + static_assert(r2.num() == 1); + static_assert(r2.den() == 2); + + static_assert(r2 == r2); + static_assert(r2 != r1); + static_assert(!(r2 > r1)); + static_assert(!(r2 >= r1)); + static_assert(r2 <= r1); + static_assert(r2 < r1); + static_assert(r1 > r2); + static_assert(r1 >= r2); + static_assert(!(r1 < r2)); + static_assert(!(r1 <= r2)); + + constexpr auto r3 = make_ratio(2, 3) - make_ratio(1, 2); + cerr << "r3=r1-r2: " << r1 - r2 << endl; // output + + static_assert(r3.num() == 1); + static_assert(r3.den() == 6); + + static_assert(r3 == r3); + static_assert(r3 != 0); + static_assert(r3 != 1); + static_assert(r3 < r2); + static_assert(r3 <= r2); + static_assert(r3 < r1); + static_assert(r3 <= r1); + + constexpr auto r4 = r1 + r2; + cerr << "r4=r1+r2: " << r1 + r2 << endl; // output + + static_assert(r4.num() == 7); + static_assert(r4.den() == 6); + static_assert(r4 > 1); + static_assert(r4 < 2); + + constexpr auto r5 = r1 + 3; + cerr << "r5=r1+3: " << r5 << endl; // output + + static_assert(r5.num() == 11); + static_assert(r5.den() == 3); + + constexpr auto r6 = 3 + r1; + cerr << "r5=3+r1: " << r6 << endl; // output + + static_assert(r6.num() == 11); + static_assert(r6.den() == 3); + + static_assert(r5 == r6); + static_assert(r5 > 3); + static_assert(r5 < 4); + static_assert(r5 > r1); + + constexpr auto r7 = r6 - 3; + cerr << "r7=r6-3: " << r7 << endl; // output + + static_assert(r7 == r1); + static_assert(r7 >= r1); + static_assert(r7 <= r1); + + constexpr auto r8 = 3 - r6; + cerr << "r8=3-r6: " << r8 << endl; // output + + static_assert(r8 == r8); + static_assert(r8 > -1); + static_assert(r8 < 0); + static_assert(-1 < r8); + static_assert(-1 <= r8); + static_assert(0 >= r8); + + constexpr auto r9 = r8 * r8; + cerr << "r9=r8*r8: " << r9 << endl; // output + + static_assert(r9 == make_ratio(4, 9)); + + constexpr auto r10 = r9 * 9; + cerr << "r10=r9*9: " << r10 << endl; // output + + static_assert(r10 == 4); + static_assert(r10.to() == 4); + + constexpr auto r11 = r9 * 3; + cerr << "r11=r9*3: " << r11 << endl; // output + + static_assert(r11 == make_ratio(4, 3)); + static_assert(r11.to() == 1); + + constexpr auto r12 = 9 * r9; + cerr << "r12=9*r9: " << r12 << endl; + + static_assert(r12 == r10); + static_assert(r12 == make_ratio(4, 1)); + static_assert(r12.to() == 4); + + constexpr auto r13 = 3 * r9; + cerr << "r13=3*r9: " << r13 << endl; // output + + static_assert(r13 == make_ratio(4, 3)); + static_assert(r13 == make_ratio(-4, -3)); + static_assert(r13 == r11); + static_assert(r13.to() == 1); + + constexpr auto r14 = r9 / r9; + cerr << "r14=r9/r9: " << r14 << endl; // output + + static_assert(r14 == 1); + static_assert(r14.to() == 1); + + constexpr auto r15 = r9 / r8; + cerr << "r15=r9/r8: " << r15 << endl; // (4/9) / (-2/3) = (4/9) * (3/-2) = 12/-18 = -2/3 + + static_assert(r15 == make_ratio(-2, 3)); + static_assert(r15 == make_ratio(2, -3)); + + constexpr auto r16 = r9 / 2; + cerr << "r16=r9/2: " << r16 << endl; + + static_assert(r16 == ratio(2, 9)); + static_assert(!r16.is_integer()); + + constexpr auto r17 = 2 / r9; + cerr << "r17=2/r9: " << r17 << endl; + + static_assert(r17 == ratio(9, 2)); + static_assert(!r17.is_integer()); + + constexpr auto r18 = r12 / r8; + cerr << "r18=r12/r8: " << r12/r8 << endl; + + static_assert(r18.is_integer()); + + constexpr auto r19 = r18.power(2); + cerr << "r19=r18^2: " << r19 << endl; + + static_assert(r19.is_integer()); + static_assert(r19 == ratio(36, 1)); + + constexpr auto r20 = r17.power(-3); + cerr << "r20=r17^-3: " << r20 << endl; + + static_assert(!r20.is_integer()); + static_assert(r20 == ratio(8, 729)); + + /* verify constexpr working */ + static_assert(ratio(2,3).num() == 2); + static_assert(ratio(2,3).den() == 3); + static_assert(make_ratio(-1,2).num() == -1); + static_assert(make_ratio(-1,2).den() == 2); + static_assert(make_ratio(-2,4).num() == -1); + static_assert(make_ratio(-2,4).den() == 2); + static_assert(make_ratio(1,-2).num() == -1); + static_assert(make_ratio(1,-2).den() == 2); + static_assert(make_ratio(-4,-6).num() == 2); + static_assert(make_ratio(-4,-6).den() == 3); +} diff --git a/include/xo/ratio/numeric_concept.hpp b/include/xo/ratio/numeric_concept.hpp new file mode 100644 index 00000000..02ad5894 --- /dev/null +++ b/include/xo/ratio/numeric_concept.hpp @@ -0,0 +1,39 @@ +/** @file numeric_concept.hpp **/ + +#pragma once + +#include + +namespace xo { + namespace ratio { + /** @concept numeric_concept + * @brief Concept for values that participate in arithmetic operations (+,-,*,/) and comparisons + * + * Intended to include at least: + * - built-in integral and floating-point types + * - big_int from ctbignum + * - boost::rational + * - std::complex + * - xo::unit::quantity + * + * Accepting complex numbers --> we don't require T to be totally ordered, + * and don't require (<,<=,>=,>) operators. + * + * Intend numeric_concept to apply to types T suitable for + * xo::ratio::ratio + **/ + template + concept numeric_concept = requires(T x, U y) + { + { -x }; + { x - y }; + { x + y }; + { x * y }; + { x / y }; + { x == y }; + { x != y }; + }; + } /*namespace ratio*/ +} /*namespace xo*/ + +/* end numeric_concept.hpp */ diff --git a/include/xo/ratio/ratio.hpp b/include/xo/ratio/ratio.hpp new file mode 100644 index 00000000..60aad611 --- /dev/null +++ b/include/xo/ratio/ratio.hpp @@ -0,0 +1,547 @@ +/** @file ratio.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "ratio_concept.hpp" +#include +#include +//#include + +namespace xo { + namespace ratio { + namespace detail { + /** @brief converts ratio to lowest terms when feasible + * + * Falls back to identity function for non-totally-ordered Ratio::component_type + */ + template > + struct reducer_type; + + /** @brief promote value to ratio type **/ + template > + struct promoter_type; + } + + /** @brief represent a ratio of two Int values. **/ + template + requires std::totally_ordered + struct ratio + { + public: + using component_type = Int; + + public: + constexpr ratio(Int n, Int d) : num_{n}, den_{d} {} + + /** @brief ratio in lowest commono terms + * + **/ + static constexpr ratio reduce(Int n, Int d) { + return ratio(n, d).reduce(); + } + + /** @brief add two ratios **/ + static constexpr ratio add(const ratio & x, + const ratio & y) { + /* (a/b) + (c/d) + * = a.d / (b.d) + b.c / (b.d) + * = (a.d + b.c) / (b.d) + */ + + auto a = x.num(); + auto b = x.den(); + auto c = y.num(); + auto d = y.den(); + + auto num = a*d + b*c; + auto den = b*d; + + return ratio(num, den).maybe_reduce(); + } + + /** @brief subtract two ratios **/ + static constexpr ratio subtract(const ratio & x, + const ratio & y) { + return add(x, y.negate()); + } + + /** @brief multiply two ratios **/ + static constexpr ratio multiply(const ratio & x, + const ratio & y) { + /* (a/b) * (c/d) = a.c / b.d */ + + /* if x,y normalized, + * opportunity to cancel common factor between (a, d) or (c, b) + * + * want to do this before multiplying to avoid overflow involving intermediate terms + */ + + auto a1 = x.num(); + auto b1 = x.den(); + auto c1 = y.num(); + auto d1 = y.den(); + + auto ad_gcf = std::gcd(a1, d1); + auto bc_gcf = std::gcd(b1, c1); + + auto a = a1 / ad_gcf; + auto b = b1 / bc_gcf; + auto c = c1 / bc_gcf; + auto d = d1 / ad_gcf; + + auto num = a*c; + auto den = b*d; + + return ratio(num, den).maybe_reduce(); + } + + /** @brief divide two ratios **/ + static constexpr ratio divide(const ratio & x, + const ratio & y) { + return multiply(x, y.reciprocal()); + } + + /** @brief compute integer power of a ratio **/ + constexpr ratio power(int p) const { + + constexpr ratio retval = ratio(1, 1); + + if (p == 0) + return ratio(1, 1); + + if (p < 0) + return this->reciprocal().power(-p); + + /* inv: x^p = aj.xj^pj */ + ratio aj = ratio(1, 1); + ratio xj = *this; + int pj = p; + + while (pj > 0) { + if (pj % 2 == 0) { + /* a.x^(2q) = a.(x^2)^q */ + xj = xj * xj; + pj = pj / 2; + } else { + /* a.x^(2q+1) = (a.x).x^(2q) */ + aj = aj * xj; + pj = (pj - 1); + } + } + + /* pj = 0, so: x^p = aj.xj^pj = aj.xj^0 = aj */ + return aj; + } + + /** @brief 3-way compare two ratios **/ + static constexpr auto compare(ratio x, ratio y) { + /* ensure minus signs in numerators only */ + if (x.den() < 0) + return compare_aux(ratio(-x.num(), -x.den()), y); + if (y.den() < 0) + return compare_aux(x, ratio(-y.num(), -y.den())); + + return compare_aux(x, y); + } + + constexpr Int num() const { return num_; } + constexpr Int den() const { return den_; } + + constexpr bool is_integer() const { return den_ == 1 || den_ == -1; } + + constexpr ratio negate() const { return ratio(-num_, den_); } + constexpr ratio reciprocal() const { return ratio(den_, num_); } + + /** @brief requires component_type is totally ordered **/ + constexpr Int floor() const { return (num_ / den_); } + + /** @brief requires component_type is totally ordered **/ + constexpr Int ceil() const { return floor() + 1; } + + /** @brief reduce to lowest terms + * + * @pre @c Int type must be totally ordered + **/ + constexpr ratio reduce() const requires std::totally_ordered { + if (den_ < 0) + return ratio(-num_, -den_).reduce(); + + auto factor = std::gcd(num_, den_); + + return ratio(num_ / factor, + den_ / factor); + } + + /** @brief reduce to lowest terms, if Int representation admits + * + * Otherwise fallback to identity function + **/ + constexpr ratio maybe_reduce() const { + return detail::reducer_type::attempt_reduce(*this); + } + + /** @brief return fractional part of this ratio + * + * @pre @c Int type must be totally ordered + **/ + constexpr ratio frac() const requires std::totally_ordered { + return ratio::subtract(*this, this->floor()); + } + + /** @brief convert to non-ratio representation + * + * For example: to int or double + **/ + template + constexpr Repr to() const { return num_ / static_cast(den_); } + + /** @brief convert to representation using different integer types **/ + template + constexpr operator Ratio2 () const requires ratio_concept { + return Ratio2(num_, den_); + } + + private: + /** @brief 3-way compare auxiliary function. + * + * @pre @p x, @p y have non-negative denominator + **/ + static constexpr auto compare_aux(ratio x, ratio y) { + /* control here: b>=0, d>=0 */ + + /* (a/b) <=> (c/d) + * (a.d/b) <=> c no sign change, since d >= 0 + * (a.d) <=> (b.c) no sign change, since b >= 0 + */ + auto a = x.num(); + auto b = x.den(); + auto c = y.num(); + auto d = y.den(); + + auto lhs = a*d; + auto rhs = b*c; + + return lhs <=> rhs; + } + + private: + /** @brief numerator **/ + Int num_; + /** @brief denominator **/ + Int den_; + }; + + namespace detail { + template + struct reducer_type {}; + + template + struct reducer_type { + static constexpr Ratio attempt_reduce(Ratio x) { return x.reduce(); } + }; + + template + struct reducer_type { + static constexpr Ratio attempt_reduce(Ratio x) { return x; } + }; + } + + namespace detail { + template + struct promoter_type; + + template + struct promoter_type { + /* to 'promote' a ratio, rely on its conversion operator */ + static constexpr Ratio promote(FromType x) { return x; } + }; + + template + struct promoter_type { + /* to 'promote' a non-ratio, use denominator=1 */ + static constexpr Ratio promote(FromType x) { return Ratio(x, 1); } + }; + } + + template + constexpr auto + make_ratio (Int1 n, Int2 d = 1) -> ratio> + { + return ratio>(n, d).maybe_reduce(); + } + + namespace detail { + /** @brief auxiliary function for binary ratio operations + * + * Support binary ratio operations on combinations: + * - (ratio, ratio) + * - (ratio, U) // where U is not a ratio + * - (T, ratio(U)) // where T is not a ratio + * + * Goals: + * + * 1. Support expressions like + * + * @code + * auto x = 1 + make_ratio(2,3); + * @endcode + * + * 2. promote to wider types as needed + * + * @code + * auto x = make_ratio(2,3) + make_ratio(1ul,2ul); + * static_assert(std::same_as); + * @endcode + * + * 3. avoid interfering with other templates that may overload operator+ + * + * @pre at least one of (Left,Right) must be known to be a ratio + **/ + template , + bool RightIsRatio = ratio_concept> + struct op_aux_type; + + /** @brief specialization for two ratio types **/ + template + requires (ratio_concept && ratio_concept) + struct op_aux_type { + using component_type = std::common_type_t; + + using ratio_type = ratio; + + static constexpr ratio_type add (const LeftRatio & x, + const RightRatio & y) + { + return ratio_type::add(x, y); + } + + static constexpr ratio_type subtract (const LeftRatio & x, + const RightRatio & y) + { + return ratio_type::subtract(x, y); + } + + static constexpr ratio_type multiply (const LeftRatio & x, + const RightRatio & y) + { + return ratio_type::multiply(x, y); + } + + static constexpr ratio_type divide (const LeftRatio & x, + const RightRatio & y) + { + return ratio_type::divide(x, y); + } + + static constexpr auto compare (const LeftRatio & x, + const RightRatio & y) + { + return ratio_type::compare(x, y); + } + }; + + /** @brief specialization for left-hand ratio and right-hand integer value **/ + template + requires (ratio_concept && !ratio_concept) + struct op_aux_type { + using component_type = std::common_type_t; + + using ratio_type = ratio; + + static constexpr ratio_type add (const LeftRatio & x, + const Right & y) + { + /* reminder: adding an integer can't introduce reduced terms */ + return ratio_type(x.num() + x.den() * y, x.den()); + } + + static constexpr ratio_type subtract (const LeftRatio & x, + const Right & y) + { + /* reminder: subtracting an integer can't introduce reduced terms */ + return ratio_type(x.num() - x.den() * y, x.den()); + } + + static constexpr ratio_type multiply (const LeftRatio & x, + const Right & yp) + { + auto gcf = std::gcd(x.den(), yp); + + auto a = x.num(); + auto b = x.den() / gcf; + auto y = yp / gcf; + + return ratio_type(a*y, b); + } + + static constexpr ratio_type divide (const LeftRatio & x, + const Right & yp) + { + auto gcf = std::gcd(x.num(), yp); + + auto a = x.num() / gcf; + auto b = x.den(); + auto y = yp / gcf; + + return ratio_type(a*y, b); + } + + static constexpr auto compare (const LeftRatio & x, + const Right & y) + { + /* note: in c++26 std::signof is constexpr, usable here */ + if (x.den() >= 0) + return compare_aux(x, y); + else + return compare_aux(LeftRatio(-x.num(), -x.den()), y); + } + + private: + static constexpr auto compare_aux (const LeftRatio & x, const Right & y) { + return (x.num() <=> x.den() * y); + } + }; + + /** @brief specialization for left-hand integer value and right-hand ratio **/ + template + requires (!ratio_concept && ratio_concept) + struct op_aux_type { + using component_type = std::common_type_t; + + using ratio_type = ratio; + + static constexpr ratio_type add(const Left & x, + const RightRatio & y) + { + /* reminder: adding an integer can't introduce reduced terms */ + return ratio_type(x * y.den() + y.num(), y.den()); + } + + static constexpr ratio_type subtract(const Left & x, + const RightRatio & y) + { + /* reminder: subtracting an integer can't introduce reduced terms */ + return ratio_type(x * y.den() - y.num(), y.den()); + } + + static constexpr ratio_type multiply (const Left & xp, + const RightRatio & y) + { + auto gcf = std::gcd(xp, y.den()); + + auto x = xp / gcf; + auto c = y.num(); + auto d = y.den() / gcf; + + return ratio_type(x*c, d); + } + + static constexpr ratio_type divide (const Left & x, + const RightRatio & y) + { + return multiply(x, y.reciprocal()); + } + + static constexpr auto compare(const Left & x, + const RightRatio & y) + { + if (y.den() >= 0) + return compare_aux(x, y); + else + return compare_aux(x, RightRatio(-y.num(), -y.den())); + } + + private: + static constexpr auto compare_aux (const Left & x, + const RightRatio & y) + { + return (x * y.den() <=> y.num()); + }; + }; + } /*namespace detail*/ + + /** @brief add two ratios. + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr auto + operator+ (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return detail::op_aux_type::add(x, y); + } + + /** @brief subtract two ratios. + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr auto + operator- (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return detail::op_aux_type::subtract(x, y); + } + + /** @brief multiply two ratios + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr auto + operator* (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return detail::op_aux_type::multiply(x, y); + } + + /** @brief divide two ratios + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr auto + operator/ (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return detail::op_aux_type::divide(x, y); + } + + /** @brief compare two ratios for equality + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr bool + operator== (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return (detail::op_aux_type::compare(x, y) == 0); + } + + /** @brief compare two ratios + * + * One argument may be a non-ratio type if it can be promoted to a ratio + **/ + template + inline constexpr auto + operator<=> (const Ratio1 & x, const Ratio2 & y) + requires (ratio_concept || ratio_concept) + { + return detail::op_aux_type::compare(x, y); + } + + } /*namespace ratio*/ +} /*namespace xo*/ + +/** end ratio.hpp **/ diff --git a/include/xo/ratio/ratio_concept.hpp b/include/xo/ratio/ratio_concept.hpp new file mode 100644 index 00000000..8ca1d438 --- /dev/null +++ b/include/xo/ratio/ratio_concept.hpp @@ -0,0 +1,29 @@ +/** @file ratio_concept.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "numeric_concept.hpp" + +namespace xo { + namespace ratio { + /* also expect: + * Ratio::num_type / Ratio::den_type rounds towards -inf + */ + template + concept ratio_concept = requires(Ratio ratio) + { + typename Ratio::component_type; + typename Ratio::component_type; + + { ratio.num() } -> std::same_as; + { ratio.den() } -> std::same_as; + } && numeric_concept; + + } /*namespace ratio*/ +} /*namespace xo*/ + + +/** end ratio_concept.hpp **/ diff --git a/include/xo/ratio/ratio_iostream.hpp b/include/xo/ratio/ratio_iostream.hpp new file mode 100644 index 00000000..fc898b36 --- /dev/null +++ b/include/xo/ratio/ratio_iostream.hpp @@ -0,0 +1,42 @@ +/** @file ratio_iostream.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "ratio.hpp" +#include + +namespace xo { + namespace ratio { + /** @brief print ratio x on stream os. + * + * Example: + * @code + * print_ratio(std::cerr, make_ratio(1,2); // outputs "" + * @endcode + **/ + template + void + print_ratio (std::ostream & os, const Ratio & x) { + os << ""; + } + + /** @brief print ratio x on stream os. + * + * Example: + * @code + * std::cout << make_ratio(2,3); // outputs "" + * @endcode + **/ + template + inline std::ostream & + operator<< (std::ostream & os, const Ratio & x) { + print_ratio(os, x); + return os; + } + } +} + +/** end ratio_iostream.hpp **/ From 978af419b30bf495863aea6563847c9f6f6b4031 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 17 Apr 2024 21:23:47 -0400 Subject: [PATCH 02/38] xo-ratio: + .gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..13c0afb7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# clangd working space (see emacs+lsp) +.cache +# typical cmake build directory (source-tree-nephew) +.build* +# symlink to builddir/compile_commands.json; should be set manually in dev sandbox +compile_commands.json From 787e19ae409a0bec2ee6e3bd29ac5366b3dfb28a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:05:45 -0400 Subject: [PATCH 03/38] xo-ratio: mark several methods noexcept --- include/xo/ratio/ratio.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/xo/ratio/ratio.hpp b/include/xo/ratio/ratio.hpp index 60aad611..a7848518 100644 --- a/include/xo/ratio/ratio.hpp +++ b/include/xo/ratio/ratio.hpp @@ -147,10 +147,10 @@ namespace xo { return compare_aux(x, y); } - constexpr Int num() const { return num_; } - constexpr Int den() const { return den_; } + constexpr Int num() const noexcept { return num_; } + constexpr Int den() const noexcept { return den_; } - constexpr bool is_integer() const { return den_ == 1 || den_ == -1; } + constexpr bool is_integer() const noexcept { return den_ == 1 || den_ == -1; } constexpr ratio negate() const { return ratio(-num_, den_); } constexpr ratio reciprocal() const { return ratio(den_, num_); } @@ -200,7 +200,7 @@ namespace xo { /** @brief convert to representation using different integer types **/ template - constexpr operator Ratio2 () const requires ratio_concept { + constexpr operator Ratio2 () const noexcept requires ratio_concept { return Ratio2(num_, den_); } @@ -209,7 +209,7 @@ namespace xo { * * @pre @p x, @p y have non-negative denominator **/ - static constexpr auto compare_aux(ratio x, ratio y) { + static constexpr auto compare_aux(ratio x, ratio y) noexcept { /* control here: b>=0, d>=0 */ /* (a/b) <=> (c/d) From c0b2e832116ecc09df6fb5ffe4fe14c5b6086128 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:06:29 -0400 Subject: [PATCH 04/38] xo-ratio: + .to_str() method using xo-flatstring --- CMakeLists.txt | 1 + cmake/xo_ratioConfig.cmake.in | 2 +- include/xo/ratio/ratio.hpp | 38 ++++++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 077f1267..ca9e8c95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets # ---------------------------------------------------------------- # dependencies +xo_headeronly_dependency(${SELF_LIB} xo_flatstring) #xo_headeronly_dependency(${SELF_LIB} randomgen) # etc.. diff --git a/cmake/xo_ratioConfig.cmake.in b/cmake/xo_ratioConfig.cmake.in index e5ee1778..b7a5a0a2 100644 --- a/cmake/xo_ratioConfig.cmake.in +++ b/cmake/xo_ratioConfig.cmake.in @@ -6,7 +6,7 @@ include(CMakeFindDependencyMacro) # must coordinate with xo_dependency() calls # in xo-reactor/src/reactor/CMakeLists.txt # -#find_dependency(reflect) +find_dependency(xo_flatstring) #find_dependency(subsys) #find_dependency(Eigen3) #find_dependency(webutil) diff --git a/include/xo/ratio/ratio.hpp b/include/xo/ratio/ratio.hpp index a7848518..a8f09e58 100644 --- a/include/xo/ratio/ratio.hpp +++ b/include/xo/ratio/ratio.hpp @@ -6,6 +6,7 @@ #pragma once #include "ratio_concept.hpp" +#include "xo/flatstring/flatstring.hpp" #include #include //#include @@ -196,7 +197,42 @@ namespace xo { * For example: to int or double **/ template - constexpr Repr to() const { return num_ / static_cast(den_); } + constexpr Repr to() const noexcept { return num_ / static_cast(den_); } + + /** @brief convert to short human-friendly flatstring representation + * + * Example: + * @code + * ratio(7,1).to_str<5>(); // "7" + * ratio(1,7).to_str<5>(); // "(1/7)" + * ratio(-1,7).to_str<10>(); // "(-1/7)" + * ratio(-1,7).to_str<5>(); // "(-1/" + * @endcode + **/ + template + constexpr flatstring to_str() const noexcept { + if (this->is_integer()) { + return flatstring::from_int(num_); + } else { + auto num_str = flatstring::from_int(num_); + auto den_str = flatstring::from_int(den_); + + /* tmp capacity will be about 2N+3 */ + auto tmp = flatstring_concat(flatstring("("), + num_str, + flatstring("/"), + den_str, + flatstring(")")); + + flatstring retval; + retval.assign(tmp); + + return retval; + } + } + + /** @brief negate operator **/ + constexpr ratio operator-() const { return ratio(-num_, den_); } /** @brief convert to representation using different integer types **/ template From d907f4eaff9d8cd1095d171b13ac34fde58fcaba Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:07:01 -0400 Subject: [PATCH 05/38] xo-ratio: + unit test --- utest/CMakeLists.txt | 57 +++++++++ utest/ratio.test.cpp | 235 +++++++++++++++++++++++++++++++++++++ utest/ratio_utest_main.cpp | 6 + 3 files changed, 298 insertions(+) create mode 100644 utest/CMakeLists.txt create mode 100644 utest/ratio.test.cpp create mode 100644 utest/ratio_utest_main.cpp diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt new file mode 100644 index 00000000..2da04264 --- /dev/null +++ b/utest/CMakeLists.txt @@ -0,0 +1,57 @@ +# xo-ratio/utest/CMakeLists.txt + +set(SELF_EXE utest.ratio) +set(SELF_SRCS + ratio_utest_main.cpp + ratio.test.cpp) + +add_executable(${SELF_EXE} ${SELF_SRCS}) +xo_include_options2(${SELF_EXE}) +add_test(NAME ${SELF_EXE} COMMAND ${SELF_EXE}) + +# ---------------------------------------------------------------- +# in coverage build, target to build+install coverage report + +if (XO_SUBMODULE_BUILD) + # in submodule build, generate aggregate coverage report + # for all xo libraries +else() + set(CCOV_OUTPUT_DIR ${PROJECT_BINARY_DIR}/ccov/html) + set(CCOV_INDEX_FILE ${CCOV_OUTPUT_DIR}/index.html) + set(CCOV_REPORT_EXE ${PROJECT_BINARY_DIR}/gen-ccov) + # CMAKE_INSTALL_DOCDIR + # =default=> DATAROOTDIR/doc/PROJECT_NAME + # =default=> CMAKE_INSTALL_PREFIX/share/doc/xo_flatstring + set(CCOV_INSTALL_DOCDIR ${CMAKE_INSTALL_DOCDIR}/ccov) + + # 'test' target should always be out-of-date + # + # DEPENDS: reminder - can't put 'test' here, requires 'all' target + # + add_custom_command( + OUTPUT ${CCOV_INDEX_FILE} + DEPENDS ${SELF_EXE} + COMMAND ${CCOV_REPORT_EXE} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Generating coverage report -> [${CCOV_OUTPUT_DIR}]") + + add_custom_target( + ccov + DEPENDS ${CCOV_INDEX_FILE} ${SELF_EXE}) + + # OPTIONAL: quietly skip this step if ccov report not generated + install( + DIRECTORY ${CCOV_OUTPUT_DIR} + FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + DESTINATION ${CCOV_INSTALL_DOCDIR} + COMPONENT Documentation + OPTIONAL) +endif() + +# ---------------------------------------------------------------- +# dependencies.. + +xo_self_headeronly_dependency(${SELF_EXE} xo_ratio) +xo_dependency(${SELF_EXE} randomgen) +xo_dependency(${SELF_EXE} indentlog) +xo_external_target_dependency(${SELF_EXE} Catch2 Catch2::Catch2) diff --git a/utest/ratio.test.cpp b/utest/ratio.test.cpp new file mode 100644 index 00000000..918f9b50 --- /dev/null +++ b/utest/ratio.test.cpp @@ -0,0 +1,235 @@ +/** @file ratio.utest.cpp **/ + +#include "xo/ratio/ratio.hpp" +#include "xo/ratio/ratio_iostream.hpp" +#include "xo/randomgen/random_seed.hpp" +#include "xo/randomgen/xoshiro256.hpp" +#include "xo/indentlog/scope.hpp" +#include "xo/indentlog/print/vector.hpp" +#include "xo/indentlog/print/array.hpp" +#include "xo/indentlog/print/tag.hpp" +//#include "xo/indentlog/print/hex.hpp" +#include +#include +#include + +namespace xo { + + using std::exponential_distribution; + using std::bernoulli_distribution; + + namespace ut { + template + struct ratio_distribution { + ratio_distribution(double sign_prob, double int_lambda) + : sign_dist_{sign_prob}, int_dist_{int_lambda} {} + + template + xo::ratio::ratio + random_ratio(Rng & rng) { + Int num_sign = sign_dist_(rng) ? -1 : +1; + Int num = num_sign * (1 + int_dist_(rng)); + Int den_sign = sign_dist_(rng) ? -1 : +1; + Int den = den_sign * (1 + int_dist_(rng)); + + return xo::ratio::ratio(num, den).reduce(); + } + + template + xo::ratio::ratio operator()(Rng & rng) { + return random_ratio(rng); + } + + /* generate negative numbers some of the time */ + bernoulli_distribution sign_dist_; + /* create ratios involving integers, but don't need integers to be too large */ + exponential_distribution int_dist_; + }; + + template + void + ratio_tests(Rng & rng) + { + constexpr bool debug_flag = true; + + std::size_t n_ratio = 25; + std::size_t n_experiment = n_ratio * n_ratio / 4; + /* want to avoid integer overflow when exponentiating */ + constexpr int max_pwr = 5; + + scope log(XO_DEBUG2(debug_flag, "ratio_tests")); + log && log(xtag("n_ratio", n_ratio)); + + ratio_distribution ratio_dist(0.25 /*sign_prob*/, + 0.05 /*lambda */); + bernoulli_distribution sign_dist(0.5); + exponential_distribution power_dist(0.2 /*lambda*/); + + std::vector> ratio_v; + + /* ensure 0, 1, -1 all present */ + ratio_v.push_back(xo::ratio::ratio(0,1)); + ratio_v.push_back(xo::ratio::ratio(1,1)); + ratio_v.push_back(xo::ratio::ratio(-1,1)); + + for (std::uint32_t i=0, n=n_ratio - ratio_v.size(); i(ratio1.den()); + double ratio2_approx = ratio2.num() / static_cast(ratio2.den()); + + { + auto sum = ratio1 + ratio2; + + double sum_approx = sum.num() / static_cast(sum.den()); + + log && log(XTAG(ratio1), XTAG(ratio2), XTAG(sum)); + + REQUIRE(sum_approx == Approx(ratio1_approx + ratio2_approx).epsilon(1e-6)); + REQUIRE(std::gcd(sum.num(), sum.den()) == 1); + REQUIRE(sum.den() > 0); + + /* comparison tests. piggyback on sum */ + { + auto cmp_approx = (sum_approx <=> ratio1_approx); + REQUIRE(cmp_approx == (sum <=> ratio1)); + } + { + bool eq = (sum == ratio1); + bool eq_approx = (sum_approx == ratio1_approx); + REQUIRE(eq == eq_approx); + } + { + bool ne = (sum != ratio1); + bool ne_approx = (sum_approx != ratio1_approx); + REQUIRE(ne == ne_approx); + } + { + bool gt = (sum > ratio1); + bool gt_approx = (sum_approx > ratio1_approx); + REQUIRE(gt == gt_approx); + } + { + bool ge = (sum >= ratio1); + bool ge_approx = (sum_approx >= ratio1_approx); + REQUIRE(ge == ge_approx); + } + { + bool lt = (sum > ratio1); + bool lt_approx = (sum_approx > ratio1_approx); + REQUIRE(lt == lt_approx); + } + { + bool le = (sum >= ratio1); + bool le_approx = (sum_approx >= ratio1_approx); + REQUIRE(le == le_approx); + } + } + + { + auto neg = -ratio1; + + double neg_approx = neg.num() / static_cast(neg.den()); + + log && log(XTAG(ratio1), XTAG(neg)); + + REQUIRE(neg_approx == Approx(-ratio1_approx).epsilon(1e-06)); + REQUIRE(std::gcd(neg.num(), neg.den()) == 1); + REQUIRE(neg.den() > 0); + } + + { + auto diff = ratio1 - ratio2; + + double diff_approx = diff.num() / static_cast(diff.den()); + + log && log(XTAG(ratio1), XTAG(ratio2), XTAG(diff)); + + REQUIRE(diff_approx == Approx(ratio1_approx - ratio2_approx).epsilon(1e-6)); + REQUIRE(std::gcd(diff.num(), diff.den()) == 1); + REQUIRE(diff.den() > 0); + } + + { + auto prod = ratio1 * ratio2; + + double prod_approx = prod.num() / static_cast(prod.den()); + + log && log(XTAG(ratio1), XTAG(ratio2), XTAG(prod)); + + REQUIRE(prod_approx == Approx(ratio1_approx * ratio2_approx).epsilon(1e-6)); + REQUIRE(std::gcd(prod.num(), prod.den()) == 1); + REQUIRE(prod.den() > 0); + } + + { + auto div = ratio1 * ratio2; + + double div_approx = div.num() / static_cast(div.den()); + + log && log(XTAG(ratio1), XTAG(ratio2), XTAG(div)); + + REQUIRE(div_approx == Approx(ratio1_approx * ratio2_approx).epsilon(1e-6)); + REQUIRE(std::gcd(div.num(), div.den()) == 1); + REQUIRE(div.den() > 0); + } + + { + int exp = (sign_dist(rng) ? -1 : +1) * power_dist(rng); + + if (std::abs(exp) >= max_pwr) { + exp = (std::signbit(exp) ? -1 : +1) * max_pwr; + } + + auto pwr = ratio1.power(exp); + + double pwr_approx = pwr.num() / static_cast(pwr.den()); + + log && log(XTAG(ratio1), XTAG(exp), XTAG(pwr)); + + REQUIRE(pwr_approx == Approx(::pow(ratio1_approx, exp)).epsilon(1e-6)); + REQUIRE(std::gcd(pwr.num(), pwr.den()) == 1); + REQUIRE(pwr.den() >= 0); + } + + { + auto ratio1_str = ratio1.template to_str<20>(); + + log && log(XTAG(ratio1_str)); + } + } + + } + + TEST_CASE("ratio", "[ratio]") { + //constexpr bool c_debug_flag = false; + + // can get bits from /dev/random by uncommenting the 2nd line below + uint64_t seed = 5521646833469436535ul; + //rng::Seed seed; + + //std::cerr << "ratio: seed=" << seed << std::endl; + + auto rng = rng::xoshiro256ss(seed); + + ratio_tests(rng); + } /*TEST_CASE(ratio)*/ + + } /*namespace ut*/ + +} /*namespace xo*/ + + +/** end ratio.utest.cpp **/ diff --git a/utest/ratio_utest_main.cpp b/utest/ratio_utest_main.cpp new file mode 100644 index 00000000..1bf5bace --- /dev/null +++ b/utest/ratio_utest_main.cpp @@ -0,0 +1,6 @@ +/** @file ratio_utest_main.cpp **/ + +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" + +/** end ratio_utest_main.cpp **/ From 0c7cb8c37e18b395bf2e5aa609d01cca5b5cf19f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:07:50 -0400 Subject: [PATCH 06/38] xo-ratio: expand example ex1.cpp --- example/ex1/ex1.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/example/ex1/ex1.cpp b/example/ex1/ex1.cpp index 8aa3c82d..144d3ed9 100644 --- a/example/ex1/ex1.cpp +++ b/example/ex1/ex1.cpp @@ -1,13 +1,75 @@ /** @file ex1.cpp **/ #include "xo/ratio/ratio_iostream.hpp" +#include "xo/indentlog/scope.hpp" +#include "xo/indentlog/print/hex.hpp" #include +namespace { + using xo::xtag; + using xo::hex_view; + +#ifdef NOT_USING + template + xo::flatstring + flatstring_from_int(int x) + { + XO_SCOPE(log, always); + + constexpr size_t buf_z = 20; + + bool negative_flag = (x < 0); + std::size_t i = buf_z; + char buf[buf_z]; + std::fill_n(buf, N, '\0'); + + if (negative_flag) + x = -x; + + buf[--i] = '\0'; + + while ((i > 0) && (x != 0)) { + buf[--i] = ('0' + x % 10); + x = x / 10; + } + + if ((i > 0) && negative_flag) + buf[--i] = '-'; + + char retv[N]; + std::fill_n(retv, N, '\0'); + std::copy_n(buf + i, buf_z - i, retv); + + log && log(xtag("i",i), xtag("buf[i..]", hex_view(buf+i, buf+buf_z, true))); + + return retv; + } +#endif + + template + constexpr xo::flatstring + ratio_to_str(Ratio x) noexcept + { + if (x.is_integer()) { + return xo::flatstring::from_int(x.num()); + } else { + constexpr auto num_str = xo::flatstring::from_int(x.num()); + constexpr auto den_str = xo::flatstring::from_int(x.den()); + + constexpr auto tmp = flatstring_concat("(", num_str, "/", den_str, ")"); + + return tmp; + } + } + +} + int main() { using xo::ratio::make_ratio; using xo::ratio::ratio; using xo::ratio::ratio_concept; + using xo::flatstring; using namespace std; constexpr auto r1 = make_ratio(2, 3); @@ -158,11 +220,24 @@ main() { static_assert(!r16.is_integer()); constexpr auto r17 = 2 / r9; - cerr << "r17=2/r9: " << r17 << endl; + cerr << "r17=2/r9: " << r17 << endl; // 9/2 static_assert(r17 == ratio(9, 2)); static_assert(!r17.is_integer()); + constexpr auto s17_num_str = flatstring<20>::from_int(r17.num()); + static_assert(s17_num_str == flatstring("9")); + constexpr auto s17_den_str = flatstring<20>::from_int(r17.den()); + static_assert(s17_den_str == flatstring("2")); + constexpr auto s17_str = flatstring_concat(flatstring_concat(flatstring("("), + s17_num_str), + flatstring_concat(flatstring("/"), + s17_den_str), + flatstring(")")); + cerr << "s17_str=" << s17_str << endl; + + //constexpr auto s17 = ratio_to_str(r17); + constexpr auto r18 = r12 / r8; cerr << "r18=r12/r8: " << r12/r8 << endl; @@ -180,6 +255,15 @@ main() { static_assert(!r20.is_integer()); static_assert(r20 == ratio(8, 729)); + //cerr << flatstring_from_int<10>(1) << endl; + + constexpr auto s20 = flatstring<10>::from_int(-123); + cerr << "s20=" << s20 << endl; + + static_assert(s20.size() > 0); + static_assert(s20 == flatstring("-123")); + + /* verify constexpr working */ static_assert(ratio(2,3).num() == 2); static_assert(ratio(2,3).den() == 3); From ec73e10c56c5bd1ae0a097aafd2f708f98c1001b Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:08:04 -0400 Subject: [PATCH 07/38] xo-ratio: build: + utest dir (!) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca9e8c95..44a7c278 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ xo_toplevel_compile_options() # ---------------------------------------------------------------- add_subdirectory(example) -#add_subdirectory(utest) +add_subdirectory(utest) #add_subdirectory(docs) # ---------------------------------------------------------------- From 413c84d65e27fe1b17a39e4393d8bcf0d102aed4 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:12:22 -0400 Subject: [PATCH 08/38] xo-ratio: README: ++ elaborate --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 722ea8bf..cf8b2de2 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Relative to `std::ratio`: This means it can be used seamlessly at runtime. 2. Supports a few more arithmetic operations, for example exponentiation to integer powers. +3. Provides constexpr conversion to fixed-capacity strings (using xo-flatstring) 3. Provides concept support (with c++20) 4. Requires modern (c++17) support to achieve this @@ -15,6 +16,7 @@ Relative to `std::ratio`: ### install dependencies - [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake) cmake macros +- [github/Rconybea/xo-flatstring](https://github.com/Rconybea/xo-flatstring) fixed-capacity strings ### build + install ``` From 96e50d0a6b5d93b4b58e6607349b8e91b8e399fc Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:19:29 -0400 Subject: [PATCH 09/38] xo-ratio: README elaboration --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf8b2de2..2ed3e4e5 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ Relative to `std::ratio`: 3. Provides concept support (with c++20) 4. Requires modern (c++17) support to achieve this +Relative to `boost::ratio`: +1. Streamlined, assumes modern compiler support + ## Getting Started ### install dependencies @@ -18,11 +21,45 @@ Relative to `std::ratio`: - [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake) cmake macros - [github/Rconybea/xo-flatstring](https://github.com/Rconybea/xo-flatstring) fixed-capacity strings +### clone xo-ratio + +``` +$ cd ~/proj # for example +$ git clone https://github.com/Rconybea/xo-ratio +``` + ### build + install ``` $ cd xo-ratio $ PREFIX=/usr/local # for example $ BUILDDIR=.build # for example $ make ${BUILDDIR} -$ cmake -DCMAKE_PREFIX_PATH=${PREFIX} -B ${BUILDDIR} +$ cmake --build .build +$ cmake --install .build +``` + +### build with unit test coverage +``` +$ cd xo-ratio +$ mkdir .build-ccov +$ cmake -DCMAKE_BUILD_TYPE=coverage -B .build-ccov +$ cmake --build .build-ccov +``` + +run coverage-enabled unit tests +``` +$ cmake --build .build-ccov -- test +``` + +generate html+text coverage report +``` +$ cmake --build .build-ccov -- ccov +``` + +browse to `.build-ccov/ccov/html/index.html` + +### LSP support +``` +$ cd xo-ratio +$ ln -s .build/compile_commands.json ``` From a848e5ea67ebe8713cd339b6a7cf8a6b0ab40b6a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:25:54 -0400 Subject: [PATCH 10/38] xo-ratio: ++ README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ed3e4e5..5b6dda3a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Relative to `boost::ratio`: ### install dependencies - [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake) cmake macros +- [github/rconybea/xo-indentlog](https://github.com/Rconybea/xo-indentlog) logging (used by unit tests) - [github/Rconybea/xo-flatstring](https://github.com/Rconybea/xo-flatstring) fixed-capacity strings ### clone xo-ratio From fd305ffe8f928cd4736a6870cdeb28738a6ac511 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:26:02 -0400 Subject: [PATCH 11/38] xo-ratio: github: + ubuntu build --- .github/workflows/ubuntu-main.yml | 186 ++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 .github/workflows/ubuntu-main.yml diff --git a/.github/workflows/ubuntu-main.yml b/.github/workflows/ubuntu-main.yml new file mode 100644 index 00000000..260a8310 --- /dev/null +++ b/.github/workflows/ubuntu-main.yml @@ -0,0 +1,186 @@ +name: build xo-ratio + dependencies + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - name: checkout source + uses: actions/checkout@v3 + + - name: Install dependencies + run: | + # install catch2, doxygen. see + # [[https://stackoverflow.com/questions/57982945/how-to-apt-get-install-in-a-github-actions-workflow]] + + echo "::group::install catch2" + sudo apt-get install -y catch2 + echo "::endgroup" + + echo "::group::install doxygen" + sudo apt-get install -y doxygen + echo "::endgroup" + + echo "::group::install sphinx" + sudo apt-get install -y python3-sphinx + echo "::endgroup" + + echo "::group::install sphinx readthedocs theme" + sudo apt-get install -y python3-sphinx-rtd-theme + echo "::endgroup" + + #echo "::group::install pybind11" + #sudo apt-get install -y pybind11-dev + #echo "::endgroup" + + # ---------------------------------------------------------------- + + - name: clone xo-cmake + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-cmake + path: repo/xo-cmake + + - name: build xo-cmake + run: | + XONAME=xo-cmake + XOSRC=repo/${XONAME} + BUILDDIR=${{github.workspace}}/build_${XONAME} + PREFIX=${{github.workspace}}/local + + echo "::group::configure ${XONAME}" + cmake -B ${BUILDDIR} -DCMAKE_INSTALL_PREFIX=${PREFIX} ${XOSRC} + echo "::endgroup" + + echo "::group::compile ${XONAME}" + cmake --build ${BUILDDIR} --config ${{env.BUILD_TYPE}} + echo "::endgroup" + + echo "::group::local install ${XONAME}" + cmake --install ${BUILDDIR} + echo "::endgroup" + + echo "::group::local dir tree" + tree ${PREFIX} + echo "::endgroup" + + # ---------------------------------------------------------------- + + - name: clone xo-indentlog + uses: actions/checkout@v3 + with: + repository: Rconybea/indentlog + path: repo/xo-indentlog + + - name: build xo-indentlog + run: | + XONAME=xo-indentlog + XOSRC=repo/${XONAME} + BUILDDIR=${{github.workspace}}/build_${XONAME} + PREFIX=${{github.workspace}}/local + + echo "::group::repo dir tree" + tree -L 2 repo + echo "::endgroup" + + echo "::group::configure ${XONAME}" + cmake -B ${BUILDDIR} -DCMAKE_INSTALL_PREFIX=${PREFIX} ${XOSRC} + echo "::endgroup" + + echo "::group::compile ${XONAME}" + cmake --build ${BUILDDIR} --config ${{env.BUILD_TYPE}} -j + echo "::endgroup" + + echo "::group::local install ${XONAME}" + cmake --install ${BUILDDIR} + echo "::endgroup" + + echo "::group::local dir tree" + tree -L 3 ${PREFIX} + echo "::endgroup" + + # ---------------------------------------------------------------- + + - name: clone xo-flatstring + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-flatstring + path: repo/xo-flatstring + + - name: build xo-flatstring + run: | + XONAME=xo-flatstring + XOSRC=repo/${XONAME} + BUILDDIR=${{github.workspace}}/build_${XONAME} + PREFIX=${{github.workspace}}/local + + echo "::group::repo dir tree" + tree -L 2 repo + echo "::endgroup" + + echo "::group::configure ${XONAME}" + cmake -B ${BUILDDIR} -DCMAKE_INSTALL_PREFIX=${PREFIX} ${XOSRC} + echo "::endgroup" + + echo "::group::compile ${XONAME}" + cmake --build ${BUILDDIR} --config ${{env.BUILD_TYPE}} -j + echo "::endgroup" + + echo "::group::local install ${XONAME}" + cmake --install ${BUILDDIR} + echo "::endgroup" + + echo "::group::local dir tree" + tree -L 3 ${PREFIX} + echo "::endgroup" + + # ---------------------------------------------------------------- + + - name: build self (xo-ratio) + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: | + XONAME=xo-ratio + BUILDDIR=${{github.workspace}}/build_${XONAME} + PREFIX=${{github.workspace}}/local + + echo "::group::repo dir tree" + tree -L 2 repo + echo "::endgroup" + + echo "::group::configure ${XONAME}" + cmake -B ${BUILDDIR} -DCMAKE_MODULE_PATH=${PREFIX}/share/cmake -DCMAKE_PREFIX_PATH=${PREFIX} -DCMAKE_INSTALL_PREFIX=${PREFIX} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + echo "::endgroup" + + echo "::group::compile ${XONAME}" + cmake --build ${BUILDDIR} --config ${{env.BUILD_TYPE}} + echo "::endgroup" + + echo "::group::run unit tests ${XONAME}" + cmake --build ${BUILDDIR} -- test + echo "::endgroup" + + echo "::group::local install ${XONAME}" + cmake --install ${BUILDDIR} + echo "::endgroup" + + echo "::group::local dir tree" + tree -L 3 ${PREFIX} + echo "::endgroup" + + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + (cd ${BUILDDIR} && ctest -C ${{env.BUILD_TYPE}}) From cef1f81f5f32a2bf01e52308ce4463e90fa26428 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:28:18 -0400 Subject: [PATCH 12/38] xo-ratio: build: drop unused xo-reflect dep --- example/ex1/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/ex1/CMakeLists.txt b/example/ex1/CMakeLists.txt index b7050cfc..224e5690 100644 --- a/example/ex1/CMakeLists.txt +++ b/example/ex1/CMakeLists.txt @@ -10,6 +10,6 @@ xo_include_options2(${SELF_EXE}) # dependencies.. xo_self_dependency(${SELF_EXE} xo_ratio) -xo_dependency(${SELF_EXE} reflect) +#xo_dependency(${SELF_EXE} reflect) # end CMakeLists.txt From 24df33c505435a17caae2f1ee0b0b784ca29ecc8 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:30:47 -0400 Subject: [PATCH 13/38] xo-ratio: github: + randomgen dep --- .github/workflows/ubuntu-main.yml | 35 +++++++++++++++++++++++++++++++ README.md | 3 ++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu-main.yml b/.github/workflows/ubuntu-main.yml index 260a8310..4b5f22cd 100644 --- a/.github/workflows/ubuntu-main.yml +++ b/.github/workflows/ubuntu-main.yml @@ -114,6 +114,41 @@ jobs: # ---------------------------------------------------------------- + - name: clone xo-randomgen + uses: actions/checkout@v3 + with: + repository: Rconybea/randomgen + path: repo/xo-randomgen + + - name: build xo-randomgen + run: | + XONAME=xo-randomgen + XOSRC=repo/${XONAME} + BUILDDIR=${{github.workspace}}/build_${XONAME} + PREFIX=${{github.workspace}}/local + + echo "::group::repo dir tree" + tree -L 2 repo + echo "::endgroup" + + echo "::group::configure ${XONAME}" + cmake -B ${BUILDDIR} -DCMAKE_INSTALL_PREFIX=${PREFIX} ${XOSRC} + echo "::endgroup" + + echo "::group::compile ${XONAME}" + cmake --build ${BUILDDIR} --config ${{env.BUILD_TYPE}} -j + echo "::endgroup" + + echo "::group::local install ${XONAME}" + cmake --install ${BUILDDIR} + echo "::endgroup" + + echo "::group::local dir tree" + tree -L 3 ${PREFIX} + echo "::endgroup" + + # ---------------------------------------------------------------- + - name: clone xo-flatstring uses: actions/checkout@v3 with: diff --git a/README.md b/README.md index 5b6dda3a..a5047565 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Relative to `boost::ratio`: ### install dependencies - [github/Rconybea/xo-cmake](https://github.com/Rconybea/xo-cmake) cmake macros -- [github/rconybea/xo-indentlog](https://github.com/Rconybea/xo-indentlog) logging (used by unit tests) - [github/Rconybea/xo-flatstring](https://github.com/Rconybea/xo-flatstring) fixed-capacity strings +- [github/rconybea/xo-indentlog](https://github.com/Rconybea/xo-indentlog) logging (used by unit tests) +- [github/rconybea/xo-randomgen](https://github.com/Rconybea/xo-randomgen) rng (used by unit tests) ### clone xo-ratio From 54cb306903e3662774d3df62d0c21ef9c292fa80 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:35:53 -0400 Subject: [PATCH 14/38] xo-ratio: bugfix: narrow operator<< template --- include/xo/ratio/ratio_iostream.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/xo/ratio/ratio_iostream.hpp b/include/xo/ratio/ratio_iostream.hpp index fc898b36..9d1c9939 100644 --- a/include/xo/ratio/ratio_iostream.hpp +++ b/include/xo/ratio/ratio_iostream.hpp @@ -17,9 +17,9 @@ namespace xo { * print_ratio(std::cerr, make_ratio(1,2); // outputs "" * @endcode **/ - template + template void - print_ratio (std::ostream & os, const Ratio & x) { + print_ratio (std::ostream & os, const ratio & x) { os << ""; } @@ -30,9 +30,9 @@ namespace xo { * std::cout << make_ratio(2,3); // outputs "" * @endcode **/ - template + template inline std::ostream & - operator<< (std::ostream & os, const Ratio & x) { + operator<< (std::ostream & os, const ratio & x) { print_ratio(os, x); return os; } From 75f78b45d3a8a89c46223033be75420816969119 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 17:48:40 -0400 Subject: [PATCH 15/38] xo-ratio: ccov: renovate coverage generation -> 2nd gen scheme --- CMakeLists.txt | 38 +++++++++++---- README.md | 5 ++ cmake/gen-ccov.in | 20 ++++++++ cmake/lcov-harness | 114 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 cmake/gen-ccov.in create mode 100755 cmake/lcov-harness diff --git a/CMakeLists.txt b/CMakeLists.txt index 44a7c278..df36a04d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,17 +12,37 @@ include(cmake/xo-bootstrap-macros.cmake) # unit test setup enable_testing() -# activate code coverage for all executables + libraries (when configured with -DCODE_COVERAGE=ON) -add_code_coverage() -# 1. assuming that /nix/store/ prefixes .hpp files belonging to gcc, catch2 etc. -# we're not interested in code coverage for these sources. -# 2. exclude the utest/ subdir, we don't need coverage on the unit tests themselves; -# rather, want coverage on the code that the unit tests exercise. +# ---------------------------------------------------------------- +# cmake -DCMAKE_BUILD_TYPE=coverage + +if (NOT DEFINED PROJECT_CXX_FLAGS_COVERAGE) + # note: for clang would use -fprofile-instr-generate -fcoverage-mapping here instead and also at link time + set(PROJECT_CXX_FLAGS_COVERAGE ${PROJECT_CXX_FLAGS} -ggdb -Og -fprofile-arcs -ftest-coverage + CACHE STRING "coverage c++ compiler flags") +endif() +message("-- PROJECT_CXX_FLAGS_COVERAGE: coverage c++ flags are [${PROJECT_CXX_FLAGS_COVERAGE}]") + +add_compile_options("$<$:${PROJECT_CXX_FLAGS_COVERAGE}>") +# when -DCMAKE_BUILD_TYPE=coverage, link executables with gcov +link_libraries("$<$:gcov>") + +find_program(LCOV_EXECUTABLE NAMES lcov) +find_program(GENHTML_EXECUTABLE NAMES genhtml) + +# with coverage build: +# 1. invoke instrumented executables for which you want coverage: +# (cd path/to/build && ctest) +# 2. post-process low-level coverage data +# (path/to/build/gen-ccov) +# 3. point browser to generated html data +# file:///path/to/build/ccov/html/index.html # -# NOTE: this seems to work only with the 'ccov-all' target. In particular, doesn't seem to do anything with the 'ccov' target -# -add_code_coverage_all_targets(EXCLUDE /nix/store/* ${PROJECT_SOURCE_DIR}/utest/* ${PROJECT_BINARY_DIR}/local/* ${PROJECT_SOURCE_DIR}/repo/*) +configure_file( + ${PROJECT_SOURCE_DIR}/cmake/gen-ccov.in + ${PROJECT_BINARY_DIR}/gen-ccov) + +file(CHMOD ${PROJECT_BINARY_DIR}/gen-ccov PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # ---------------------------------------------------------------- # c++ settings diff --git a/README.md b/README.md index a5047565..09c36590 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ Relative to `std::ratio`: Relative to `boost::ratio`: 1. Streamlined, assumes modern compiler support +## Documentation + +- xo-ratio documentation under construction +- unit test coverage here: [coverage](https://rconybea.github.io/web/xo-ratio/ccov/html/index.html) + ## Getting Started ### install dependencies diff --git a/cmake/gen-ccov.in b/cmake/gen-ccov.in new file mode 100644 index 00000000..e335aed4 --- /dev/null +++ b/cmake/gen-ccov.in @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +srcdir=@PROJECT_SOURCE_DIR@ +builddir=@PROJECT_BINARY_DIR@ +lcov=@LCOV_EXECUTABLE@ +genhtml=@GENHTML_EXECUTABLE@ + +if [[ $lcov == "LCOV_EXECUTABLE-NOTFOUND" ]]; then + echo "gen-ccov: lcov executable not found" + exit 1 +fi + +if [[ $genhtml == "GENHTML_EXECUTABLE-NOTFOUND" ]]; then + echo "gen-ccov: genhtml executable not found" + exit 1 +fi + +mkdir $builddir/ccov + +$srcdir/cmake/lcov-harness $srcdir $builddir $builddir/ccov/out $lcov $genhtml diff --git a/cmake/lcov-harness b/cmake/lcov-harness new file mode 100755 index 00000000..27ac8be9 --- /dev/null +++ b/cmake/lcov-harness @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +srcdir=$1 +builddir=$2 +outputstem=$3 +lcov=$4 +genhtml=$5 + +if [[ -z "${srcdir}" ]]; then + echo "lcov-harness: expected non-empty srcdir" + exit 1 +fi + +if [[ -z ${builddir} ]]; then + echo "lcov-harness: expected non-empty builddir" + exit 1 +fi + +if [[ -z ${outputstem} ]]; then + echo "lcov-harness: expected non-empty outputstem" + exit 1 +fi + +if [[ -z ${lcov} ]]; then + echo "lcov-harness: exepcted non-empty lcov" + exit 1 +fi + +if [[ -z ${genhtml} ]]; then + echo "lcov-harness: expected non-empty genhtml" + exit 1 +fi + +# directory stems for location of {.gcda, gcno} coverage information, +# +# if we have source tree: +# +# ${srcdir} +# +- foo +# | \- foo.cpp +# \- bar +# \- quux +# +- quux.cpp +# \- quux_main.cpp +# +# then we expect build tree: +# +# ${builddir} +# +- foo +# | \- CMakeFiles +# | \- foo_target.dir +# | +- foo.cpp.gcda +# | \- foo.cpp.gcno +# +- bar +# \- quux +# \- CMakeFiles +# \- target4quux.dir +# +- quux.cpp.gcda +# +- quux.cpp.gcno +# +- quux_main.cpp.gcda +# \- quux_main.cpp.gcno +# +# in which case will have cmd_body: +# +# ${primarydirs} +# ./foo/CMakeFiles/foo_target.dir +# ./bar/quux/CMakeFiles/target4quux.dir +# +# here foo_target, quux_target are whatever build is using for corresponding cmake target names. +# +# We want to invoke lcov like: +# +# lcov --capture \ +# --output ${builddir}/ccov \ +# --exclude /utest/ \ +# --base-directory ${srcdir}/foo --directory ${builddir}/foo/CMakeFiles/foo_target.dir \ +# --base-directory ${srcdir}/bar/quux --directory ${builddir}/bar/quux/CMakeFiles/target4quux.dir +# +primarydirs=$(cd ${builddir} && find -name '*.gcno' \ + | xargs --replace=xx dirname xx \ + | uniq \ + | sed -e 's:^\./::') + +#echo "primarydirs=${primarydirs}" + +cmd="${lcov} --output ${outputstem}.info --capture --ignore-errors source" + +for bdir in ${primarydirs}; do + sdir=$(dirname $(dirname ${bdir})) + + cmd="${cmd} --base-directory ${srcdir}/${sdir} --directory ${builddir}/${bdir}" +done + +#echo cmd=${cmd} + +set -x + +# capture +${cmd} + +# keep only files with paths under source tree +# (don't want coverage for external libraries such as libstdc++ etc) +${lcov} --extract ${outputstem}.info "${srcdir}/*" --output ${outputstem}2.info + +# remove unit test dirs +# (we're interested in coverage of our installed code, not of the unit tests that exercise it) +${lcov} --remove ${outputstem}2.info '*/utest/*' --output ${outputstem}3.info + +# generate .html tree +mkdir -p ${builddir}/ccov/html +${genhtml} --ignore-errors source --show-details --prefix ${srcdir} --output-directory ${builddir}/ccov/html ${outputstem}3.info + +# also send report to stdout +${lcov} --list ${outputstem}3.info From 06e230ebfddc606893d8342a30873ddec61e6d8c Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 18 Apr 2024 18:03:11 -0400 Subject: [PATCH 16/38] xo-ratio: docs: initial doxygen+sphinx scaffold --- CMakeLists.txt | 2 +- docs/CMakeLists.txt | 118 ++ docs/Doxyfile.in | 2816 ++++++++++++++++++++++++++++++++++ docs/_static/img/favicon.ico | Bin 0 -> 309803 bytes docs/_static/img/icon.svg | 77 + docs/_static/img/xo-icon.svg | 77 + docs/conf.py | 36 + docs/index.rst | 34 + docs/install.rst | 88 ++ 9 files changed, 3247 insertions(+), 1 deletion(-) create mode 100644 docs/CMakeLists.txt create mode 100644 docs/Doxyfile.in create mode 100644 docs/_static/img/favicon.ico create mode 100644 docs/_static/img/icon.svg create mode 100644 docs/_static/img/xo-icon.svg create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/install.rst diff --git a/CMakeLists.txt b/CMakeLists.txt index df36a04d..882e9914 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ xo_toplevel_compile_options() add_subdirectory(example) add_subdirectory(utest) -#add_subdirectory(docs) +add_subdirectory(docs) # ---------------------------------------------------------------- # provide find_package() support for projects using this library diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 00000000..57a99c20 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,118 @@ +# xo-ratio/docs/CMakeLists.txt + +if (XO_SUBMODULE_BUILD) + # in submodule build, rely on toplevel docs/CMakeLists.txt file instead +else() + # build docs starting from here only in standalone build. + # otherwise use top-level doxygen setup instead. + + set(ALL_LIBRARY_TARGETS xo_ratio) # todo: automate this from xo-cmake macros + set(ALL_UTEST_TARGETS utest.ratio xo_ratio_ex1 ) # todo: automate this from xo-cmake macros + + # look for doxygen executable + find_program(DOXYGEN_EXECUTABLE NAMES doxygen REQUIRED) + message("-- DOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE}") + + # look for sphinx-build executable + find_program(SPHINX_EXECUTABLE NAMES sphinx-build REQUIRED) + message("-- SPHINX_EXECUTABLE=${SPHINX_EXECUTABLE}") + + set(DOX_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + set(DOX_INPUT_DIR ${PROJECT_SOURCE_DIR}) + set(DOX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/dox) + + set(DOX_INDEX_FILE ${DOX_OUTPUT_DIR}/html/index.html) + + # .hpp files reachable from xo-ratio/include + # + # REMINDER: for reliability will need to re-run cmake when the set of .hpp files changes + # + file(GLOB_RECURSE DOX_HPP_FILES_GLOB ${PROJECT_SOURCE_DIR}/include *.hpp) + + set(SPHINX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/sphinx/html) + set(SPHINX_INDEX_FILE ${SPHINX_OUTPUT_DIR}/index.html) + # + # sphinx .rst files reachable from cmake-examples/docs + # + # REMINDER: for reliability will need to re-run cmake when the set of .rst files changes + # + file(GLOB_RECURSE SPHINX_RST_FILES_GLOB ${CMAKE_CURRENT_SOURCE_DIR} *.rst) + + set(SPHINX_RST_FILES index.rst + #install.rst + #lessons.rst + #flatstring-reference.rst + #flatstring-class.rst + ) + + # TODO: + # 1. move Doxyfile.in to xo-cmake project + # 2. replace this command section with xo-cmake macro + # + configure_file( + Doxyfile.in ${DOX_CONFIG_FILE} + FILE_PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + @ONLY) + + set(DOX_DEPS ${ALL_LIBRARY_TARGETS} ${ALL_UTEST_TARGETS} ${DOX_HPP_FILES_GLOB}) + + file(MAKE_DIRECTORY ${DOX_OUTPUT_DIR}) + add_custom_command( + OUTPUT ${DOX_INDEX_FILE} + DEPENDS ${DOX_DEPS} + COMMAND "${DOXYGEN_EXECUTABLE}" ${DOX_CONFIG_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + MAIN_DEPENDENCY ${DOX_CONFIG_FILE} + COMMENT "Generating docs (doxygen)") + + # To build this target + # $ cmake --build .build -j -- doxygen + # or + # $ cd .build + # $ make doxygen + # + add_custom_target( + doxygen + DEPENDS ${DOX_INDEX_FILE} ${DOX_DEPS} + ) + + # root of sphinx doc tree + set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) + set(SPHINX_DEPS doxygen conf.py ${SPHINX_RST_FILES} ${SPHINX_RST_FILES_GLOB} ${DOX_DEPS}) + + add_custom_command( + OUTPUT ${SPHINX_INDEX_FILE} + DEPENDS ${SPHINX_DEPS} + COMMAND ${SPHINX_EXECUTABLE} + -b html -Dbreathe_projects.xodoxxml=${CMAKE_CURRENT_BINARY_DIR}/dox/xml + ${SPHINX_SOURCE} ${SPHINX_OUTPUT_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating docs (sphinx) -> [${SPHINX_OUTPUT_DIR}]") + + # make sphinx --> generate sphinx documentation + # + add_custom_target( + sphinx + DEPENDS ${SPHINX_INDEX_FILE}) + + # - html docs generated in build/docs/sphinx + # - copy the doc tree to share/doc/xo_unit/html + # + # DESTINATION: CMAKE_INSTALL_DOCDIR + # => DATAROOTDIR/doc/PROJECT_NAME + # => CMAKE_INSTALL_PREFIX/share/doc/xo_flatstring + # OPTIONAL: install directory tree if it exists, + # but don't complain if it's missing + install( + DIRECTORY ${SPHINX_OUTPUT_DIR} + FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT Documentation + OPTIONAL) + + # make docs --> generate sphinx documentation + add_custom_target( + docs + DEPENDS sphinx) +endif() diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 00000000..13dfb0fa --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,2816 @@ +# If filename is Doxyfile.in: +# template (to be expanded by cmake) for real doxyfile +# @SOMEVAR@ expands to value of cmake variable SOMEVAR +# +# expressions to be expanded include: +# @DOX_INPUT_DIR@ +# @DOX_OUTPUT_DIR@ +# +# if filename is Doxyfile: +# expanded template in build directory, to configure doxygen + +# Doxyfile 1.9.7 +# + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Cmake Examples" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = @DOX_OUTPUT_DIR@ + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = @DOX_INPUT_DIR@ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN Use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0. and GITHUB Use the lower case version of title +# with any whitespace replaced by '-' and punctations characters removed.. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = YES + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. + +CASE_SENSE_NAMES = SYSTEM + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @DOX_INPUT_DIR@ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = */utest/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# ANamespace::AClass, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /