├── .gitignore ├── docs ├── _Sidebar.md ├── Home.md ├── Mathematical-constants.md ├── Bitwise-operations.md ├── Vectors.md ├── Trigonometric-and-hyperbolic-functions.md ├── Integral-constants.md ├── Miscellaneous-functions.md ├── Common-mathematical-functions.md ├── Rational-numbers.md └── Complex-numbers.md ├── .github └── workflows │ └── deploy-to-wiki.yml ├── license.txt ├── test ├── trigonometry.cpp ├── vector.cpp ├── bit.cpp ├── rational.cpp ├── complex.cpp ├── constant.cpp ├── formula.cpp └── cmath.cpp ├── CMakeLists.txt ├── include └── static_math │ ├── detail │ ├── trigonometry.inl │ ├── logical_traits.h │ ├── parse.h │ ├── bit.inl │ ├── vector.inl │ ├── can_fit.h │ ├── formula.inl │ ├── constant.inl │ ├── core.h │ └── rational.inl │ ├── static_math.h │ ├── constants.h │ ├── bit.h │ ├── trigonometry.h │ ├── vector.h │ ├── formula.h │ ├── cmath.h │ ├── constant.h │ ├── rational.h │ └── complex.h ├── .travis.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Executables 8 | *.exe 9 | *.out 10 | *.app 11 | 12 | # Code::Blocks files 13 | *.cbp 14 | *.depend 15 | *.layout 16 | 17 | # CMake 18 | build* 19 | CMakeCache.txt 20 | -------------------------------------------------------------------------------- /docs/_Sidebar.md: -------------------------------------------------------------------------------- 1 | * [[Home]] 2 | * [[Mathematical constants]] 3 | * Mathematical functions 4 | * [[Common mathematical functions]] 5 | * [[Trigonometric and hyperbolic functions]] 6 | * [[Miscellaneous functions]] 7 | * [[Bitwise operations]] 8 | * [[Rational numbers]] 9 | * [[Complex numbers]] 10 | * [[Integral constants]] 11 | * [[Vectors]] -------------------------------------------------------------------------------- /.github/workflows/deploy-to-wiki.yml: -------------------------------------------------------------------------------- 1 | name: Wiki Deployment 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'docs/**' 9 | 10 | jobs: 11 | sync-wiki-files: 12 | name: Sync Wiki Files 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout /docs 18 | uses: actions/checkout@master 19 | - name: Merge to .wiki 20 | uses: SwiftDocOrg/github-wiki-publish-action@rsync 21 | with: 22 | path: docs/ 23 | env: 24 | GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.DEPLOY_TO_WIKI_ACCESS_TOKEN }} 25 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Morwenn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/Home.md: -------------------------------------------------------------------------------- 1 | Welcome to the `static_math` wiki! 2 | 3 | You probably already read all the promotional stuff in the project's README, so I we won't be repeating that here. The library is rather simple and small so the documentation will be a bit boring and straightforward while probably really close to a regular Doxygen documentation. To be honest, if you want to know more about one of the library features, you might as well directly read the source code, which should be readable enough. There is *one* notable exception to this rule: the return type of some functions is fully specified in this documentation while it may be `decltype(auto)` in the source code. This is because some of these functions support [[integral constants]] and their return type may be a bit more tricky; the documented return type is the one you can expect when you are not using integral constants. 4 | 5 | Also, note that this documentation documents what functions or classes you should expect to find when including a header, even if you are bound to include more because of headers interdependencies. This problem would be solved by modules, but they are still not in the standard. 6 | 7 | If you ever feel that this wiki is incomplete, that it needs more examples or more detailed explanation about stuff, PRs are welcome: the `docs` subdirectory of the sources is automatically uploaded to the GitHub Wiki. 8 | 9 | Hope this will be useful! 10 | -------------------------------------------------------------------------------- /docs/Mathematical-constants.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | `static_math` provides a few mathematical constants exposed as `constexpr` variable template with a default `double` precision, mainly corresponding to the ones defined in a POSIX-compliant ``. The constants provided mostly correspond to the ones that can't be created by the library's function. All the constants in this module live in the namespace `smath::constants`. 6 | 7 | ### POSIX-compliant constants 8 | 9 | ```cpp 10 | /** e */ 11 | template 12 | constexpr T e = static_cast(2.71828182845904523540L); 13 | 14 | /** log2(e) */ 15 | template 16 | constexpr T log2e = static_cast(1.44269504088896340740L); 17 | 18 | /** log10(e) */ 19 | template 20 | constexpr T log10e = static_cast(0.43429448190325182765L); 21 | 22 | /** ln(2) */ 23 | template 24 | constexpr T ln2 = static_cast(0.69314718055994530942L); 25 | 26 | /** ln(10) */ 27 | template 28 | constexpr T ln10 = static_cast(2.30258509299404568402L); 29 | 30 | /** pi */ 31 | template 32 | constexpr T pi = static_cast(3.14159265358979323846L); 33 | ``` 34 | 35 | ### Other mathematical constants 36 | 37 | ```cpp 38 | /** Golden ratio */ 39 | template 40 | constexpr T phi = static_cast(1.61803398874989484820L); 41 | ``` -------------------------------------------------------------------------------- /docs/Bitwise-operations.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | The functions in this header correspond to ones in the C++20 standard library header . Those are mostly bitwise operations that work on unsigned integer types. 6 | 7 | ### Integral power-of-2 operations 8 | 9 | ```cpp 10 | template 11 | constexpr auto ispow2(Unsigned x) noexcept 12 | -> bool; 13 | ``` 14 | 15 | Computes whether the unsigned integer `x` is a power of two. 16 | 17 | *This function is overloaded so that it can handle [[integral constants]].* 18 | 19 | ```cpp 20 | template 21 | constexpr auto ceil2(Unsigned x) noexcept 22 | -> Unsigned; 23 | ``` 24 | 25 | Computes the minimal value `y` such that `ispow2(y)` is `true` and `y >= x`; if `y` is not representable as a value of type `Unsigned`, the result is an unspecified value. 26 | 27 | *This function is overloaded so that it can handle [[integral constants]].* 28 | 29 | ```cpp 30 | template 31 | constexpr auto floor2(Unsigned x) noexcept 32 | -> Unsigned; 33 | ``` 34 | 35 | If `x == 0`, returns `0`; otherwise computes the maximal value `y` such that `ispow2(y)` is `true` and `y <= x`. 36 | 37 | *This function is overloaded so that it can handle [[integral constants]].* 38 | 39 | ```cpp 40 | template 41 | constexpr auto log2p1(Unsigned x) noexcept 42 | -> Unsigned; 43 | ``` 44 | 45 | If `x == 0`, returns `0`; otherwise one plus the base-2 logarithm of `x`, with any fractional part discarded. 46 | 47 | *This function is overloaded so that it can handle [[integral constants]].* -------------------------------------------------------------------------------- /test/trigonometry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * This file is the work of theLOLflashlight's GitHub account. 27 | */ 28 | #include 29 | #include 30 | 31 | int main() 32 | { 33 | using namespace smath; 34 | 35 | // TODO: make this more exhaustive. 36 | static_assert(smath::sin(constants::pi<> / 2) == 1, ""); 37 | static_assert(smath::cos(constants::pi<> / 2) == 0, ""); 38 | } 39 | -------------------------------------------------------------------------------- /docs/Vectors.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | Vectors are a work-in-progress feature. The long-term goal is to add some basic [linear algebra](https://en.wikipedia.org/wiki/Linear_algebra) features to `static_math`, including vector and matrix operations. As of now, `smath::vector` is but a thin wrapper around `std::array`. Some features will be added in the future; some features may disappear too, such as regular container operations that have little to do with linear algebra. 6 | 7 | ```cpp 8 | template 9 | struct vector; 10 | ``` 11 | 12 | ### Types 13 | 14 | ```cpp 15 | using value_type = typename std::array::value_type; 16 | using size_type = typename std::array::size_type; 17 | using const_pointer = typename std::array::const_pointer; 18 | ``` 19 | 20 | ### Element access 21 | 22 | ``` 23 | constexpr auto operator[](size_type i) const 24 | -> value_type; 25 | 26 | constexpr auto at(size_type i) const 27 | -> value_type; 28 | 29 | constexpr auto front() const 30 | -> value_type; 31 | 32 | constexpr auto back() const 33 | -> value_type; 34 | 35 | constexpr auto data() const 36 | -> const_pointer; 37 | ``` 38 | 39 | ### Capacity 40 | 41 | ```cpp 42 | constexpr auto empty() const 43 | -> bool; 44 | 45 | constexpr auto size() const 46 | -> size_type; 47 | 48 | constexpr auto max_size() const 49 | -> size_type; 50 | ``` 51 | 52 | ### Vectors algebra 53 | 54 | ```cpp 55 | template 56 | constexpr auto operator+(vector lhs, vector rhs) 57 | -> vector; 58 | 59 | template 60 | constexpr auto operator-(vector lhs, vector rhs) 61 | -> vector; 62 | ``` 63 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(static_math LANGUAGES CXX) 4 | 5 | option(STATIC_MATH_BUILD_TESTS "Build the tests them." ON) 6 | 7 | # Create static_math library and configure it 8 | add_library(static_math INTERFACE) 9 | target_include_directories(static_math INTERFACE 10 | $ 11 | $ 12 | ) 13 | 14 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.8.0") 15 | target_compile_features(static_math INTERFACE cxx_std_14) 16 | else() 17 | set(CMAKE_CXX_STANDARD 14) 18 | endif() 19 | 20 | add_library(static_math::static_math ALIAS static_math) 21 | 22 | install( 23 | DIRECTORY "include/" 24 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 25 | ) 26 | 27 | if (STATIC_MATH_BUILD_TESTS) 28 | include(CTest) 29 | enable_testing() 30 | 31 | function(build_test test_tgt check_tgt) 32 | # Add executable for the example 33 | add_executable(test-${test_tgt} ${headers} ${detail_headers} test/${test_tgt}.cpp) 34 | target_link_libraries(test-${test_tgt} PRIVATE static_math::static_math) 35 | add_custom_target(run-test-${test_tgt} COMMAND $ ) 36 | add_test(NAME ${test_tgt} 37 | COMMAND test-${test_tgt}) 38 | 39 | if(TARGET ${check_tgt}) 40 | add_dependencies(${check_tgt} test-${test_tgt}) 41 | endif() 42 | endfunction(build_test) 43 | 44 | add_custom_target(all_tests ALL) 45 | 46 | build_test(bit all_tests) 47 | build_test(cmath all_tests) 48 | build_test(complex all_tests) 49 | build_test(constant all_tests) 50 | build_test(formula all_tests) 51 | build_test(rational all_tests) 52 | build_test(trigonometry all_tests) 53 | build_test(vector all_tests) 54 | 55 | add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C "${CMAKE_BUILD_TYPE}" --output-on-failure 56 | DEPENDS all_tests 57 | VERBATIM) 58 | endif() 59 | -------------------------------------------------------------------------------- /include/static_math/detail/trigonometry.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * This file is the work of theLOLflashlight's GitHub account. 27 | */ 28 | 29 | //////////////////////////////////////////////////////////// 30 | // Trigonometric functions 31 | 32 | template 33 | constexpr auto cot(Float x) 34 | -> Float 35 | { 36 | return smath::cos(x) / smath::sin(x); 37 | } 38 | 39 | template 40 | constexpr auto sec(Float x) 41 | -> Float 42 | { 43 | return 1 / smath::cos(x); 44 | } 45 | 46 | template 47 | constexpr auto csc(Float x) 48 | -> Float 49 | { 50 | return 1 / smath::sin(x); 51 | } 52 | 53 | //////////////////////////////////////////////////////////// 54 | // Hyperbolic functions 55 | 56 | template 57 | constexpr auto coth(Float x) 58 | -> Float 59 | { 60 | return smath::cosh(x) / smath::sinh(x); 61 | } 62 | 63 | template 64 | constexpr auto sech(Float x) 65 | -> Float 66 | { 67 | return 1 / smath::cosh(x); 68 | } 69 | 70 | template 71 | constexpr auto csch(Float x) 72 | -> Float 73 | { 74 | return 1 / smath::sinh(x); 75 | } 76 | -------------------------------------------------------------------------------- /include/static_math/static_math.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_STATIC_MATH_H_ 25 | #define SMATH_STATIC_MATH_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /** 40 | * @file static_math/static_math.h 41 | * @brief Main library file. 42 | * 43 | * This file includes the whole library (almost). 44 | */ 45 | 46 | /** 47 | * @namespace smath 48 | * Global namespace of static_math. 49 | * 50 | * Every function of static_math lives in this namespace. 51 | * The library does not contain any other namespace. 52 | * 53 | * All the functions in this library are meant to be used 54 | * at compile time. Even though can also be used at runtime, 55 | * but it's generally not a good idea: the ability to run at 56 | * compile time is often at the expense of runtime speed. 57 | */ 58 | 59 | #endif // SMATH_STATIC_MATH_H_ 60 | -------------------------------------------------------------------------------- /include/static_math/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2016 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_CONSTANTS_H_ 25 | #define SMATH_CONSTANTS_H_ 26 | 27 | namespace smath 28 | { 29 | namespace constants 30 | { 31 | //////////////////////////////////////////////////////////// 32 | // POSIX constants from cmath 33 | 34 | /** e */ 35 | template 36 | constexpr T e = static_cast(2.71828182845904523540L); 37 | 38 | /** log2(e) */ 39 | template 40 | constexpr T log2e = static_cast(1.44269504088896340740L); 41 | 42 | /** log10(e) */ 43 | template 44 | constexpr T log10e = static_cast(0.43429448190325182765L); 45 | 46 | /** ln(2) */ 47 | template 48 | constexpr T ln2 = static_cast(0.693147180559945309417232121L); 49 | 50 | /** ln(10) */ 51 | template 52 | constexpr T ln10 = static_cast(2.302585092994045684017991454L); 53 | 54 | /** pi */ 55 | template 56 | constexpr T pi = static_cast(3.14159265358979323846L); 57 | 58 | //////////////////////////////////////////////////////////// 59 | // Other mathematical constants 60 | 61 | /** Golden ratio */ 62 | template 63 | constexpr T phi = static_cast(1.61803398874989484820L); 64 | }} 65 | 66 | #endif // SMATH_CONSTANTS_H_ 67 | -------------------------------------------------------------------------------- /test/vector.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2017 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | 27 | int main() 28 | { 29 | using namespace smath; 30 | 31 | // TEST: basics 32 | // - construction 33 | // - accessors 34 | // - capacity 35 | { 36 | constexpr vector v0 { 5 }; 37 | constexpr vector v1 = { 1, 2, 3 }; 38 | 39 | static_assert(v0[0] == 5, ""); 40 | static_assert(v0.at(0) == 5, ""); 41 | static_assert(v0.front() == 5, ""); 42 | static_assert(v0.back() == 5, ""); 43 | static_assert(v1[2] == 3, ""); 44 | static_assert(v1.at(1) == 2, ""); 45 | static_assert(v1.front() == 1, ""); 46 | static_assert(v1.back() == 3, ""); 47 | 48 | static_assert(not v0.empty(), ""); 49 | static_assert(v0.size() == 1, ""); 50 | static_assert(v0.max_size() == 1, ""); 51 | static_assert(not v1.empty(), ""); 52 | static_assert(v1.size() == 3, ""); 53 | static_assert(v1.max_size() == v1.size(), ""); 54 | } 55 | 56 | // TEST: addition and subtraction 57 | { 58 | constexpr vector v0 = { 1, 2 }; 59 | constexpr vector v1 = { 3, 8 }; 60 | 61 | constexpr auto res0 = v0 + v1; 62 | static_assert(res0[0] == 4, ""); 63 | static_assert(res0[1] == 10, ""); 64 | 65 | constexpr auto res1 = v1 - v0; 66 | static_assert(res1[0] == 2, ""); 67 | static_assert(res1[1] == 6, ""); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /docs/Trigonometric-and-hyperbolic-functions.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | This header contains the standard [trigonometric functions](https://en.wikipedia.org/wiki/Trigonometric_functions) and [hyperbolic functions](https://en.wikipedia.org/wiki/Hyperbolic_function). The functions `sin`, `cos`, `tan`, `sinh`, `cosh` and `tanh` are also available in the header `` for consistency with the standard library header ``. 5 | 6 | ### Trigonometric functions 7 | 8 | ```cpp 9 | template 10 | constexpr auto sin(Float x) 11 | -> Float; 12 | ``` 13 | 14 | Computes the sine of `x` (measured in radians). 15 | 16 | ```cpp 17 | template 18 | constexpr auto cos(Float x) 19 | -> Float; 20 | ``` 21 | 22 | Computes the cosine of `x` (measured in radians). 23 | 24 | ```cpp 25 | template 26 | constexpr auto tan(Float x) 27 | -> Float; 28 | ``` 29 | 30 | Computes the tangent of `x` (measured in radians). 31 | 32 | ```cpp 33 | template 34 | constexpr auto cot(Float x) 35 | -> Float; 36 | ``` 37 | 38 | Computes the cotangent of `x` (measured in radians). 39 | 40 | ```cpp 41 | template 42 | constexpr auto sec(Float x) 43 | -> Float; 44 | ``` 45 | 46 | Computes the secant of `x` (measured in radians). 47 | 48 | ```cpp 49 | template 50 | constexpr auto csc(Float x) 51 | -> Float; 52 | ``` 53 | 54 | Computes the cosecant of `x` (measured in radians). 55 | 56 | ### Hyperbolic functions 57 | 58 | ```cpp 59 | template 60 | constexpr auto sinh(Float x) 61 | -> Float; 62 | ``` 63 | 64 | Computes hyperbolic the sine of `x` (measured in radians). 65 | 66 | ```cpp 67 | template 68 | constexpr auto cosh(Float x) 69 | -> Float; 70 | ``` 71 | 72 | Computes the hyperbolic cosine of `x` (measured in radians). 73 | 74 | ```cpp 75 | template 76 | constexpr auto tanh(Float x) 77 | -> Float; 78 | ``` 79 | 80 | Computes the hyperbolic tangent of `x` (measured in radians). 81 | 82 | ```cpp 83 | template 84 | constexpr auto coth(Float x) 85 | -> Float; 86 | ``` 87 | 88 | Computes the hyperbolic cotangent of `x` (measured in radians). 89 | 90 | ```cpp 91 | template 92 | constexpr auto sec(Float x) 93 | -> Float; 94 | ``` 95 | 96 | Computes the hyperbolic secant of `x` (measured in radians). 97 | 98 | ```cpp 99 | template 100 | constexpr auto csc(Float x) 101 | -> Float; 102 | ``` 103 | 104 | Computes the hyperbolic cosecant of `x` (measured in radians). 105 | -------------------------------------------------------------------------------- /include/static_math/bit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_BIT_H_ 25 | #define SMATH_BIT_H_ 26 | 27 | /** 28 | * @file static_math/bit.h 29 | * @brief compile-time clone of functions from . 30 | * 31 | * This header provides mathematical functions to work on unsigned 32 | * integers, mostly related to power-of-2 operations, which happen 33 | * to use bit tricks under the hood. Most of them are direct clones 34 | * of functions from the C++20 header. 35 | */ 36 | 37 | //////////////////////////////////////////////////////////// 38 | // Headers 39 | //////////////////////////////////////////////////////////// 40 | #include 41 | #include 42 | #include 43 | 44 | namespace smath 45 | { 46 | /** 47 | * @brief Returns whether \p x is a power of 2. 48 | */ 49 | template 50 | constexpr auto ispow2(Unsigned x) noexcept 51 | -> bool; 52 | 53 | /** 54 | * @brief Minimal power of 2 greater or equal to \p x. 55 | */ 56 | template 57 | constexpr auto ceil2(Unsigned x) noexcept 58 | -> Unsigned; 59 | 60 | /** 61 | * @brief Maximal power of two lesser or equal to \p x. 62 | */ 63 | template 64 | constexpr auto floor2(Unsigned x) noexcept 65 | -> Unsigned; 66 | 67 | /** 68 | * @brief 0 if \p x == 0, otherwise base-2 logarithm of \p x. 69 | */ 70 | template 71 | constexpr auto log2p1(Unsigned x) noexcept 72 | -> Unsigned; 73 | 74 | #include "detail/bit.inl" 75 | } 76 | 77 | #endif // SMATH_BIT_H_ 78 | -------------------------------------------------------------------------------- /include/static_math/detail/logical_traits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_DETAIL_LOGICAL_TRAITS_H_ 25 | #define SMATH_DETAIL_LOGICAL_TRAITS_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | 32 | namespace smath 33 | { 34 | namespace detail 35 | { 36 | //////////////////////////////////////////////////////////// 37 | // Conjunction 38 | 39 | template 40 | struct conjunction: 41 | std::true_type 42 | {}; 43 | 44 | template 45 | struct conjunction: 46 | Head 47 | {}; 48 | 49 | template 50 | struct conjunction: 51 | std::conditional_t, Head> 52 | {}; 53 | 54 | //////////////////////////////////////////////////////////// 55 | // Disjunction 56 | 57 | template 58 | struct disjunction: 59 | std::false_type 60 | {}; 61 | 62 | template 63 | struct disjunction: 64 | Head 65 | {}; 66 | 67 | template 68 | struct disjunction: 69 | std::conditional_t> 70 | {}; 71 | 72 | //////////////////////////////////////////////////////////// 73 | // Negation 74 | 75 | template 76 | struct negation: 77 | std::integral_constant 78 | {}; 79 | }} 80 | 81 | #endif // SMATH_DETAIL_LOGICAL_TRAITS_H_ 82 | -------------------------------------------------------------------------------- /include/static_math/trigonometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * This file is the work of theLOLflashlight's GitHub account. 27 | */ 28 | 29 | #ifndef SMATH_TRIGONOMETRY_H_ 30 | #define SMATH_TRIGONOMETRY_H_ 31 | 32 | //////////////////////////////////////////////////////////// 33 | // Headers 34 | //////////////////////////////////////////////////////////// 35 | #include 36 | 37 | namespace smath 38 | { 39 | //////////////////////////////////////////////////////////// 40 | // Trigonometric functions 41 | 42 | /** 43 | * @brief Cotangent function. 44 | * @param x Angle in radians 45 | */ 46 | template 47 | constexpr auto cot(Float x) 48 | -> Float; 49 | 50 | /** 51 | * @brief Secant function. 52 | * @param x Angle in radians 53 | */ 54 | template 55 | constexpr auto sec(Float x) 56 | -> Float; 57 | 58 | /** 59 | * @brief Cosecant function. 60 | * @param x Angle in radians 61 | */ 62 | template 63 | constexpr auto csc(Float x) 64 | -> Float; 65 | 66 | //////////////////////////////////////////////////////////// 67 | // Hyperbolic functions 68 | 69 | /** 70 | * @brief Hyperbolic cotangent function. 71 | * @param x Hyperbolic angle in radians 72 | */ 73 | template 74 | constexpr auto coth(Float x) 75 | -> Float; 76 | 77 | /** 78 | * @brief Hyperbolic secant function. 79 | * @param x Hyperbolic angle in radians 80 | */ 81 | template 82 | constexpr auto sech(Float x) 83 | -> Float; 84 | 85 | /** 86 | * @brief Hyperbolic cosecant function. 87 | * @param x Hyperbolic angle in radians 88 | */ 89 | template 90 | constexpr auto csch(Float x) 91 | -> Float; 92 | 93 | #include "detail/trigonometry.inl" 94 | } 95 | 96 | #endif // SMATH_TRIGONOMETRY_H_ 97 | -------------------------------------------------------------------------------- /include/static_math/detail/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_DETAIL_PARSE_H_ 25 | #define SMATH_DETAIL_PARSE_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include "can_fit.h" 32 | 33 | namespace smath 34 | { 35 | namespace detail 36 | { 37 | //////////////////////////////////////////////////////////// 38 | // Helper functions 39 | 40 | constexpr auto is_decimal_digit(char c) 41 | -> bool 42 | { 43 | return c >= '0' && c <= '9'; 44 | } 45 | 46 | template 47 | constexpr auto is_decimal_digit(char c, Chars... digits) 48 | -> bool 49 | { 50 | return is_decimal_digit(c) 51 | && is_decimal_digit(digits...); 52 | } 53 | 54 | constexpr auto combine(std::uintmax_t value) 55 | -> std::uintmax_t 56 | { 57 | return value; 58 | } 59 | 60 | template 61 | constexpr auto combine(std::uintmax_t value, std::uintmax_t first, Integers... digits) 62 | -> std::uintmax_t 63 | { 64 | return combine(value*10 + first, digits...); 65 | } 66 | 67 | //////////////////////////////////////////////////////////// 68 | // Parsing interface 69 | 70 | template 71 | class parse 72 | { 73 | static_assert(C != '0' || sizeof...(Digits) == 0, 74 | "parse cannot handle octal literals"); 75 | 76 | static_assert(is_decimal_digit(C, Digits...), 77 | "parse only handles decimal digits"); 78 | 79 | private: 80 | 81 | static constexpr std::uintmax_t raw_value = 82 | combine(0, C-'0', Digits-'0'...); 83 | 84 | public: 85 | 86 | using type = integer_fit_t; 87 | 88 | static constexpr type value = 89 | static_cast(raw_value); 90 | }; 91 | 92 | template 93 | using parse_t = typename parse::type; 94 | }} 95 | 96 | #endif // SMATH_DETAIL_PARSE_H_ 97 | -------------------------------------------------------------------------------- /include/static_math/detail/bit.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | template 26 | constexpr auto ispow2(Unsigned x) noexcept 27 | -> bool 28 | { 29 | return (x != 0) && !(x & (x - 1)); 30 | } 31 | 32 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 33 | template 34 | constexpr auto ispow2(constant) noexcept 35 | -> bool_constant 36 | { 37 | return {}; 38 | } 39 | #endif 40 | 41 | template 42 | constexpr auto ceil2(Unsigned x) noexcept 43 | -> Unsigned 44 | { 45 | if (x == 0) { 46 | return 1; 47 | } 48 | 49 | constexpr auto bound = std::numeric_limits::digits / 2u; 50 | --x; 51 | for (std::size_t i = 1 ; i <= bound ; i <<= 1) { 52 | x |= (x >> i); 53 | } 54 | return x + 1u; 55 | } 56 | 57 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 58 | template 59 | constexpr auto ceil2(constant) noexcept 60 | -> constant 61 | { 62 | return {}; 63 | } 64 | #endif 65 | 66 | template 67 | constexpr auto floor2(Unsigned x) noexcept 68 | -> Unsigned 69 | { 70 | constexpr auto bound = std::numeric_limits::digits / 2u; 71 | for (std::size_t i = 1 ; i <= bound ; i <<= 1) { 72 | x |= (x >> i); 73 | } 74 | return x & ~(x >> 1); 75 | } 76 | 77 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 78 | template 79 | constexpr auto floor2(constant) noexcept 80 | -> constant 81 | { 82 | return {}; 83 | } 84 | #endif 85 | 86 | template 87 | constexpr auto log2p1(Unsigned x) noexcept 88 | -> Unsigned 89 | { 90 | if (x == 0) { 91 | return 0; 92 | } 93 | 94 | Unsigned log = 1; 95 | while (x >>= 1) { 96 | ++log; 97 | } 98 | return log; 99 | } 100 | 101 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 102 | template 103 | constexpr auto log2p1(constant) noexcept 104 | -> constant 105 | { 106 | return {}; 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /docs/Integral-constants.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | This header defines the class template `constant` which is a mere wrapper around [`std::integral_constant`](http://en.cppreference.com/w/cpp/types/integral_constant). However, its arithmetic, logical, comparison and relational operators are overloaded so that `constant @ constant` returns an instance of `constant` where `@` represents any of the aforementioned operators. 6 | 7 | Some of the library's mathematical functions are overload so that, for any such function `func`, `func(constant)` returns an instance of `constant`. 8 | 9 | ```cpp 10 | template 11 | struct constant: 12 | std::integral_constant 13 | {}; 14 | 15 | template 16 | using bool_constant = constant; 17 | 18 | using true_type = bool_constant; 19 | using false_type = bool_constant; 20 | ``` 21 | 22 | While the library's main purpose is to provide `constexpr` value-level mathematical functions, this class template also provides type-level integer arithmetics with almost the same syntax as the value-level features. Moreover, this module defines user-defined literals so that it is possible to write things such as `3_c + sqr(2_c) == 7_c` (this expression returns a `true_type`). This achieves expressive type-level integer arithmetics. 23 | 24 | Since all the arithmetic, logical, comparison and relational operators are implemented exactly as described above, repeating them all here would be nothing but noise. The library functions overloaded for `constant` are marked as such in this documentation. If you think that more functions should be able to handle integral constants, don't hesitate to submit an issue. 25 | 26 | ### User-defined literals 27 | 28 | static_math provides user-defined literals for the class template `constant` when templated over standard integral types. To make them as usable as possible and to reflect the use of user-defined literals in the standard library, they are defined in the inline namespace `constant_literals` in the inline namespace `smath::literals`. 29 | 30 | ```cpp 31 | template 32 | constexpr auto operator"" _c() 33 | -> constant; 34 | 35 | template 36 | constexpr auto operator"" _cl() 37 | -> constant; 38 | 39 | template 40 | constexpr auto operator"" _cll() 41 | -> constant; 42 | 43 | template 44 | constexpr auto operator"" _cu() 45 | -> constant; 46 | 47 | template 48 | constexpr auto operator"" _cul() 49 | -> constant; 50 | 51 | template 52 | constexpr auto operator"" _cull() 53 | -> constant; 54 | ``` 55 | 56 | These user-defined literals do mostly what you would expect them to do: `_c` returns a `constant`, `_cul` returns a `constant`, etc... However, they are enhanced to behave a bit more like regular integer literals in the sense that, if the integer parsed by `_c` is too big to fit in an `int`, the returned type will be `constant` instead, then `constant`. These user-defined literals make this kind of thing possible: 57 | 58 | ```cpp 59 | static_assert(-8_c + 5_c == -3_c, ""); 60 | ``` 61 | 62 | ### Compatibility 63 | 64 | Integral constants do not work with MSVC++ versions older than 19.12 because of a few bugs and are thus automatically disabled for these versions. If needed, it can be manually disabled by defining the macro `STATIC_MATH_NO_INTEGRAL_CONSTANT`. -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | addons: 4 | apt: 5 | sources: 6 | - ubuntu-toolchain-r-test 7 | packages: 8 | - [cmake, cmake-data] 9 | - ninja-build 10 | - [g++-5, g++-6, g++-7, g++-8, g++-9] 11 | homebrew: 12 | update: true 13 | packages: 14 | - cmake 15 | - ninja 16 | 17 | matrix: 18 | include: 19 | # Linux 20 | 21 | ## Clang 22 | - os: linux 23 | env: COMPILER=clang++ CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 24 | compiler: clang 25 | 26 | - os: linux 27 | env: COMPILER=clang++ CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 28 | compiler: clang 29 | 30 | ## GCC 31 | - os: linux 32 | env: COMPILER=g++-5 CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 33 | compiler: gcc 34 | 35 | - os: linux 36 | env: COMPILER=g++-5 CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 37 | compiler: gcc 38 | 39 | - os: linux 40 | env: COMPILER=g++-6 CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 41 | compiler: gcc 42 | 43 | - os: linux 44 | env: COMPILER=g++-6 CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 45 | compiler: gcc 46 | 47 | - os: linux 48 | env: COMPILER=g++-7 CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 49 | compiler: gcc 50 | 51 | - os: linux 52 | env: COMPILER=g++-7 CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 53 | compiler: gcc 54 | 55 | - os: linux 56 | env: COMPILER=g++-8 CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 57 | compiler: gcc 58 | 59 | - os: linux 60 | env: COMPILER=g++-8 CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 61 | compiler: gcc 62 | 63 | - os: linux 64 | env: COMPILER=g++-9 CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 65 | compiler: gcc 66 | 67 | - os: linux 68 | env: COMPILER=g++-9 CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 69 | compiler: gcc 70 | 71 | # Mac OSX 72 | - os: osx 73 | osx_image: xcode7.3 74 | compiler: clang 75 | env: CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="Ninja" 76 | 77 | - os: osx 78 | osx_image: xcode7.3 79 | compiler: clang 80 | env: CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="Ninja" 81 | 82 | # Windows 83 | 84 | ## MinwGW-w64 85 | - os: windows 86 | env: CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="MinGW Makefiles" 87 | language: sh 88 | compiler: gcc 89 | 90 | - os: windows 91 | env: CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="MinGW Makefiles" 92 | language: sh 93 | compiler: gcc 94 | 95 | ## MSVC (using a pseudo-generator) 96 | - os: windows 97 | env: CMAKE_BUILD_TYPE=Debug CMAKE_GENERATOR="MSVC" 98 | compiler: msvc 99 | 100 | - os: windows 101 | env: CMAKE_BUILD_TYPE=Release CMAKE_GENERATOR="MSVC" 102 | compiler: msvc 103 | 104 | install: 105 | - if [[ $TRAVIS_OS_NAME = "linux" ]]; then 106 | case ${COMPILER} in 107 | clang*) 108 | export CXX=${COMPILER} 109 | ;; 110 | g++-*) 111 | export CXX=${COMPILER} 112 | ;; 113 | *) echo "Invalid compiler version" ; exit 2 ;; 114 | esac 115 | fi 116 | 117 | script: 118 | - cmake --version 119 | - if [[ $TRAVIS_OS_NAME != "windows" ]]; then 120 | ninja --version; 121 | fi 122 | - echo "CXX=${CXX}" 123 | - $CXX --version 124 | - if [[ $CMAKE_GENERATOR = "MSVC" ]]; then 125 | cmake -H. -Bbuild 126 | -DCMAKE_CONFIGURATION_TYPES="${CMAKE_BUILD_TYPE}"; 127 | else 128 | cmake -H. -Bbuild 129 | -DCMAKE_CONFIGURATION_TYPES="${CMAKE_BUILD_TYPE}" 130 | -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" 131 | -G"${CMAKE_GENERATOR}" 132 | -DCMAKE_SH="CMAKE_SH-NOTFOUND"; 133 | fi 134 | - cmake --build build --target check 135 | 136 | notifications: 137 | email: false 138 | -------------------------------------------------------------------------------- /include/static_math/vector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_VECTOR_H_ 25 | #define SMATH_VECTOR_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef __clang__ 35 | #pragma clang diagnostic push 36 | #pragma clang diagnostic ignored "-Wmissing-braces" 37 | #endif 38 | 39 | namespace smath 40 | { 41 | /** 42 | * @brief Fixed-size vector. 43 | */ 44 | template 45 | struct vector 46 | { 47 | //////////////////////////////////////////////////////////// 48 | // Types 49 | 50 | using value_type = typename std::array::value_type; 51 | using size_type = typename std::array::size_type; 52 | using const_pointer = typename std::array::const_pointer; 53 | 54 | //////////////////////////////////////////////////////////// 55 | // Operators 56 | 57 | constexpr auto operator[](size_type i) const 58 | -> value_type; 59 | 60 | //////////////////////////////////////////////////////////// 61 | // Accessors 62 | 63 | constexpr auto at(size_type i) const 64 | -> value_type; 65 | 66 | constexpr auto front() const 67 | -> value_type; 68 | 69 | constexpr auto back() const 70 | -> value_type; 71 | 72 | constexpr auto data() const 73 | -> const_pointer; 74 | 75 | //////////////////////////////////////////////////////////// 76 | // Capacity 77 | 78 | constexpr auto empty() const 79 | -> bool; 80 | 81 | constexpr auto size() const 82 | -> size_type; 83 | 84 | constexpr auto max_size() const 85 | -> size_type; 86 | 87 | //////////////////////////////////////////////////////////// 88 | // Member data 89 | 90 | // Internal array holding the elements. 91 | // Should be private, but that would prevent 92 | // aggregate initialization. 93 | const std::array elems; 94 | }; 95 | 96 | //////////////////////////////////////////////////////////// 97 | // Element-wise operations 98 | 99 | template 100 | constexpr auto operator+(vector lhs, vector rhs) 101 | -> vector; 102 | 103 | template 104 | constexpr auto operator-(vector lhs, vector rhs) 105 | -> vector; 106 | 107 | #include "detail/vector.inl" 108 | } 109 | 110 | #ifdef __clang__ 111 | #pragma clang diagnostic pop 112 | #endif 113 | 114 | #endif // SMATH_VECTOR_H_ 115 | -------------------------------------------------------------------------------- /include/static_math/detail/vector.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2014-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | //////////////////////////////////////////////////////////// 26 | // Details 27 | 28 | namespace detail 29 | { 30 | template 31 | constexpr auto add(vector lhs, vector rhs, std::index_sequence) 32 | -> vector 33 | { 34 | return { (lhs[Ind] + rhs[Ind])... }; 35 | } 36 | 37 | template 38 | constexpr auto sub(vector lhs, vector rhs, std::index_sequence) 39 | -> vector 40 | { 41 | return { (lhs[Ind] - rhs[Ind])... }; 42 | } 43 | } 44 | 45 | //////////////////////////////////////////////////////////// 46 | // In-class operators 47 | 48 | template 49 | constexpr auto vector::operator[](size_type i) const 50 | -> value_type 51 | { 52 | return elems[i]; 53 | } 54 | 55 | //////////////////////////////////////////////////////////// 56 | // Accessors 57 | 58 | template 59 | constexpr auto vector::at(size_type i) const 60 | -> value_type 61 | { 62 | return elems.at(i); 63 | } 64 | 65 | template 66 | constexpr auto vector::front() const 67 | -> value_type 68 | { 69 | return elems.front(); 70 | } 71 | 72 | template 73 | constexpr auto vector::back() const 74 | -> value_type 75 | { 76 | return elems.back(); 77 | } 78 | 79 | template 80 | constexpr auto vector::data() const 81 | -> const_pointer 82 | { 83 | return elems.data(); 84 | } 85 | 86 | //////////////////////////////////////////////////////////// 87 | // Capacity 88 | 89 | template 90 | constexpr auto vector::empty() const 91 | -> bool 92 | { 93 | return elems.empty(); 94 | } 95 | 96 | template 97 | constexpr auto vector::size() const 98 | -> size_type 99 | { 100 | return elems.size(); 101 | } 102 | 103 | template 104 | constexpr auto vector::max_size() const 105 | -> size_type 106 | { 107 | return elems.max_size(); 108 | } 109 | 110 | //////////////////////////////////////////////////////////// 111 | // Element-wise operations 112 | 113 | template 114 | constexpr auto operator+(vector lhs, vector rhs) 115 | -> vector 116 | { 117 | using Indices = std::make_index_sequence; 118 | return detail::add(lhs, rhs, Indices{}); 119 | } 120 | 121 | template 122 | constexpr auto operator-(vector lhs, vector rhs) 123 | -> vector 124 | { 125 | using Indices = std::make_index_sequence; 126 | return detail::sub(lhs, rhs, Indices{}); 127 | } 128 | -------------------------------------------------------------------------------- /include/static_math/detail/can_fit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_DETAIL_CAN_FIT_H_ 25 | #define SMATH_DETAIL_CAN_FIT_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | 34 | namespace smath 35 | { 36 | namespace detail 37 | { 38 | //////////////////////////////////////////////////////////// 39 | // Integer literals trait 40 | // 41 | // These functions are meant to help the parsing 42 | // of integer literals. 43 | 44 | /** 45 | * @brief Unsigned integer fit. 46 | * 47 | * This functions checks whether a given integer 48 | * value can fit in a given type of integer. 49 | */ 50 | template 51 | constexpr auto can_fit(std::uintmax_t n) 52 | -> bool 53 | { 54 | return n <= std::numeric_limits::max(); 55 | } 56 | 57 | /** 58 | * @brief Suitable integer type selection. 59 | * 60 | * This class will select the smallest type at least 61 | * as big as the given one where the given unsigned 62 | * long long value can fit. 63 | */ 64 | template 65 | struct integer_fit; 66 | 67 | template 68 | using integer_fit_t = typename integer_fit::type; 69 | 70 | template 71 | struct integer_fit 72 | { 73 | using type = std::conditional_t< 74 | can_fit(N), 75 | int, 76 | integer_fit_t 77 | >; 78 | }; 79 | 80 | template 81 | struct integer_fit 82 | { 83 | using type = std::conditional_t< 84 | can_fit(N), 85 | long, 86 | long long 87 | >; 88 | }; 89 | 90 | template 91 | struct integer_fit 92 | { 93 | using type = long long; 94 | }; 95 | 96 | template 97 | struct integer_fit 98 | { 99 | using type = std::conditional_t< 100 | can_fit(N), 101 | unsigned, 102 | integer_fit_t 103 | >; 104 | }; 105 | 106 | template 107 | struct integer_fit 108 | { 109 | using type = std::conditional_t< 110 | can_fit(N), 111 | unsigned long, 112 | unsigned long long 113 | >; 114 | }; 115 | 116 | template 117 | struct integer_fit 118 | { 119 | using type = unsigned long long; 120 | }; 121 | }} 122 | 123 | #endif // SMATH_DETAIL_CAN_FIT_H_ 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](http://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) 2 | [![Build Status](https://travis-ci.org/Morwenn/static_math.svg?branch=master)](https://travis-ci.org/Morwenn/static_math) 3 | 4 | `static_math` is a C++ library dedicated to compile time mathematics. 5 | 6 | ## Compatibility 7 | 8 | `static_math` heavily relies on C++ features from the C++14 standard - most notably 9 | extended `constexpr` -, therefore only somewhat recent compilers should be able to 10 | compile it. From the latest tests (no as good as they could be), it should work with 11 | at least the following compilers or more recent versions of them: 12 | * g++5 13 | * clang++4 14 | * MSVC++ 19.12 (corresponding to VS 2017 15.5) 15 | 16 | It should also work with older versions of VS 2017 minus a single feature (integral 17 | constants) which has been deactivated for these versions. 18 | 19 | ## Principle 20 | 21 | `static_math` makes a heavy use of the C++14 extended `constexpr` to reimplement 22 | a number of existing mathematical functions and some new ones. It also provides 23 | a range of classes (`rational`, `complex`, etc...) whose functions can be used 24 | at compile time too. The library also contains some common mathematical constants. 25 | 26 | The library also offers compile-time mathematics at the template parameter level 27 | thanks to it [`constant`](https://github.com/Morwenn/static_math/wiki/Integral-constants) 28 | class, which is a bit like `std::integral_constant` but with an explicit math 29 | support: for example `constant{} + constant{}` will return an 30 | instance of `constant`. One could also write `5_c + 3_c` thanks to the 31 | provided user-defined literals. 32 | 33 | ## Design choices 34 | 35 | ### Compile time library 36 | 37 | `static_math` has only been made to be usable at compile time and shall not be 38 | used at runtime. It's still possible to use it at runtime though, but it's not 39 | well advised. 40 | 41 | Since the library is only meant to be used at compile time, some design choices 42 | have been made to improve usability, convenience or safety over performance. For 43 | example, the rational numbers are simplified after each operation, which could 44 | badly alter the performance in a runtime context, but which greatly lessens the 45 | risk of overflow in rational operations. 46 | 47 | ### Intuitive feel 48 | 49 | One of `static_math`'s aims is to be easy to use. The functions are implemented 50 | so that they can be used in a straightforward way. This implies that the user will 51 | not have to deal with complex metaprogramming tricks - even though some are used in 52 | the implementation. 53 | 54 | This intuitive feel is the one reason why `static_math` needs a recent compiler 55 | since the library will need a heavy support for `constexpr`, `std::initializer_list` 56 | and variadic templates in order to work fine. 57 | 58 | Some classes (*e.g.* `rational` and `complex`) use public member variables instead 59 | of getters. This simplifies the access to the internals and also ensures that they 60 | cannot be modified after construction. 61 | 62 | ### Flexibility 63 | 64 | Some classes such as `rational` or `complex` make a heavy use of some type traits 65 | facilities such as `std::common_type` in order to offer some flexibility. Many 66 | functions accept different number types and return and instance of the common type 67 | of the arguments:: 68 | 69 | ```cpp 70 | // Two different types used to represent numbers 71 | int a = 5; 72 | long int b = 100000; 73 | 74 | // The bigger of them is used as the output type 75 | auto c = gcd(a, b); // type is long int 76 | ``` 77 | 78 | ## Documentation 79 | 80 | You can find some documentation in the [associated wiki](https://github.com/Morwenn/static_math/wiki). 81 | You can also generate some anemic documentation thanks to the Doxygen comments in 82 | the code. If you want to know more about the details, reading the source code might 83 | still be an interesting solution: the code should be pretty straightforward and 84 | readable enough. Never hesiste to open a documentation issue if you ever feel that 85 | some parts of the documentation are not complete enough or need more examples. 86 | -------------------------------------------------------------------------------- /docs/Miscellaneous-functions.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | This header includes mathematical functions that do not belong anywhere else in the library. 6 | 7 | ### Basic functions 8 | 9 | ```cpp 10 | template 11 | constexpr auto sign(Number x) 12 | -> int; 13 | ``` 14 | 15 | [Signum function](https://en.wikipedia.org/wiki/Sign_function). It returns the sign of `x`. 16 | 17 | ```cpp 18 | template 19 | constexpr auto is_close(T a, U b) 20 | -> bool; 21 | ``` 22 | 23 | Compares whether two floating point numbers `a` and `b` are close from each other. The formula used is similar to the one used by Python's [`math.isclose`](https://docs.python.org/3/library/math.html#math.isclose) function. For types other than floating point numbers, a regular comparison is performed. 24 | 25 | ```cpp 26 | template 27 | constexpr auto sum(T first, U second, Rest... rest) 28 | -> std::common_type_t; 29 | ``` 30 | 31 | Computes the sum of a collection of values. 32 | 33 | *This function is overloaded so that it can handle [[integral constants]].* 34 | 35 | ```cpp 36 | template 37 | constexpr auto mean(Numbers... args) 38 | -> decltype(sum(args...) / sizeof...(args)); 39 | ``` 40 | 41 | Computes the [mean](https://en.wikipedia.org/wiki/Mean) of a collection of values. 42 | 43 | ```cpp 44 | template 45 | constexpr auto sqr(Number x) 46 | -> Number; 47 | ``` 48 | 49 | Returns the square of `x`. 50 | 51 | *This function is overloaded so that it can handle [[integral constants]].* 52 | 53 | ```cpp 54 | template 55 | constexpr auto clamp(Number x, Number min, Number max) 56 | -> Number; 57 | ``` 58 | 59 | Returns the value of `x` [clamped](https://en.wikipedia.org/wiki/Clamping_%28graphics%29) to the range `[min, max]`. 60 | 61 | ### Integer-related functions 62 | 63 | ```cpp 64 | template 65 | constexpr auto is_even(Integer n) 66 | -> bool; 67 | ``` 68 | 69 | Computes whether the integer `n` is even. 70 | 71 | *This function is overloaded so that it can handle [[integral constants]].* 72 | 73 | ```cpp 74 | template 75 | constexpr auto is_odd(Integer n) 76 | -> bool; 77 | ``` 78 | 79 | Computes whether the integer `n` is odd. 80 | 81 | *This function is overloaded so that it can handle [[integral constants]].* 82 | 83 | ```cpp 84 | template 85 | constexpr auto is_prime(Integer n) 86 | -> bool; 87 | ``` 88 | 89 | Computes whether the integer `n` is a [prime number](https://en.wikipedia.org/wiki/Prime_number). 90 | 91 | *This function is overloaded so that it can handle [[integral constants]].* 92 | 93 | ```cpp 94 | template 95 | constexpr auto fibonacci(Integer n) 96 | -> Integer; 97 | ``` 98 | 99 | Computes the nth [Fibonacci number](https://en.wikipedia.org/wiki/Fibonacci_number). 100 | 101 | *This function is overloaded so that it can handle [[integral constants]].* 102 | 103 | ```cpp 104 | template 105 | constexpr auto factorial(Integer n) 106 | -> Integer; 107 | ``` 108 | 109 | Computes the [factorial](https://en.wikipedia.org/wiki/Factorial) of `n`. 110 | 111 | *This function is overloaded so that it can handle [[integral constants]].* 112 | 113 | ```cpp 114 | template 115 | constexpr auto gcd(T a, U b) 116 | -> std::common_type_t; 117 | ``` 118 | 119 | Computes the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of `a` and `b`. 120 | 121 | *This function is overloaded so that it can handle [[integral constants]].* 122 | 123 | ```cpp 124 | template 125 | constexpr auto lcm(T a, U b) 126 | -> std::common_type_t; 127 | ``` 128 | 129 | Computes the [least common multiple](https://en.wikipedia.org/wiki/Least_common_multiple) of `a` and `b`. 130 | 131 | *This function is overloaded so that it can handle [[integral constants]].* 132 | 133 | ### Angle conversions 134 | 135 | ```cpp 136 | template 137 | constexpr auto degrees(Float x) 138 | -> Float; 139 | ``` 140 | 141 | Converts an angle `x` in radians into an angle in degrees. 142 | 143 | ```cpp 144 | template 145 | constexpr auto radians(Float x) 146 | -> Float; 147 | ``` 148 | 149 | Converts an angle `x` in degrees into an angle in radians. 150 | -------------------------------------------------------------------------------- /test/bit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | int main() 31 | { 32 | //////////////////////////////////////////////////////////// 33 | // Regular functions 34 | 35 | static_assert(not smath::ispow2(0u), ""); 36 | static_assert(smath::ispow2(1u), ""); 37 | static_assert(smath::ispow2(2u), ""); 38 | static_assert(not smath::ispow2(255u), ""); 39 | static_assert(smath::ispow2(256u), ""); 40 | 41 | static_assert(smath::ceil2(0u) == 1u, ""); 42 | static_assert(smath::ceil2(1u) == 1u, ""); 43 | static_assert(smath::ceil2(2u) == 2u, ""); 44 | static_assert(smath::ceil2(3u) == 4u, ""); 45 | static_assert(smath::ceil2(4u) == 4u, ""); 46 | static_assert(smath::ceil2(123u) == 128u, ""); 47 | 48 | static_assert(smath::floor2(0u) == 0u, ""); 49 | static_assert(smath::floor2(1u) == 1u, ""); 50 | static_assert(smath::floor2(2u) == 2u, ""); 51 | static_assert(smath::floor2(3u) == 2u, ""); 52 | static_assert(smath::floor2(4u) == 4u, ""); 53 | static_assert(smath::floor2(5u) == 4u, ""); 54 | static_assert(smath::floor2(123u) == 64u, ""); 55 | 56 | static_assert(smath::log2p1(0u) == 0u, ""); 57 | static_assert(smath::log2p1(1u) == 1u, ""); 58 | static_assert(smath::log2p1(2u) == 2u, ""); 59 | static_assert(smath::log2p1(3u) == 2u, ""); 60 | static_assert(smath::log2p1(4u) == 3u, ""); 61 | static_assert(smath::log2p1(123u) == 7u, ""); 62 | 63 | //////////////////////////////////////////////////////////// 64 | // smath::constant overloads 65 | 66 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 67 | using namespace smath::constant_literals; 68 | 69 | static_assert( 70 | std::is_same< 71 | decltype(smath::ispow2(0_cu)), 72 | smath::false_type 73 | >::value, ""); 74 | static_assert( 75 | std::is_same< 76 | decltype(smath::ispow2(1_cu)), 77 | smath::true_type 78 | >::value, ""); 79 | static_assert( 80 | std::is_same< 81 | decltype(smath::ispow2(2_cu)), 82 | smath::true_type 83 | >::value, ""); 84 | static_assert( 85 | std::is_same< 86 | decltype(smath::ispow2(255_cu)), 87 | smath::false_type 88 | >::value, ""); 89 | static_assert( 90 | std::is_same< 91 | decltype(smath::ispow2(256_cu)), 92 | smath::true_type 93 | >::value, ""); 94 | 95 | static_assert(smath::ceil2(0_cu) == 1_cu, ""); 96 | static_assert(smath::ceil2(1_cu) == 1_cu, ""); 97 | static_assert(smath::ceil2(2_cu) == 2_cu, ""); 98 | static_assert(smath::ceil2(3_cu) == 4_cu, ""); 99 | static_assert(smath::ceil2(4_cu) == 4_cu, ""); 100 | static_assert(smath::ceil2(123_cu) == 128_cu, ""); 101 | 102 | static_assert(smath::floor2(0_cu) == 0_cu, ""); 103 | static_assert(smath::floor2(1_cu) == 1_cu, ""); 104 | static_assert(smath::floor2(2_cu) == 2_cu, ""); 105 | static_assert(smath::floor2(3_cu) == 2_cu, ""); 106 | static_assert(smath::floor2(4_cu) == 4_cu, ""); 107 | static_assert(smath::floor2(5_cu) == 4_cu, ""); 108 | static_assert(smath::floor2(123_cu) == 64_cu, ""); 109 | 110 | static_assert(smath::log2p1(0_cu) == 0_cu, ""); 111 | static_assert(smath::log2p1(1_cu) == 1_cu, ""); 112 | static_assert(smath::log2p1(2_cu) == 2_cu, ""); 113 | static_assert(smath::log2p1(3_cu) == 2_cu, ""); 114 | static_assert(smath::log2p1(4_cu) == 3_cu, ""); 115 | static_assert(smath::log2p1(123_cu) == 7_cu, ""); 116 | #endif 117 | } 118 | -------------------------------------------------------------------------------- /test/rational.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | 26 | using namespace smath; 27 | 28 | 29 | int main() 30 | { 31 | // Constructor tests 32 | constexpr auto ratio = rational(4, 3); 33 | static_assert(ratio.numer == 4, ""); 34 | static_assert(ratio.denom == 3, ""); 35 | 36 | constexpr auto ratio2 = rational(5); 37 | static_assert(ratio2.numer == 5, ""); 38 | static_assert(ratio2.denom == 1, ""); 39 | 40 | constexpr auto r1 = rational(1, 2); 41 | constexpr auto r2 = rational(2, 4); 42 | constexpr auto r3 = rational(1, 3); 43 | constexpr auto r4 = rational(5, 1); 44 | constexpr auto r5 = rational(-1, 2); 45 | constexpr auto r6 = rational(1, -2); 46 | constexpr auto r7 = rational(4, 5); 47 | 48 | // Rational-rational comparison 49 | static_assert(r1 == r2, ""); 50 | static_assert(r1 != r3, ""); 51 | static_assert(r1 > r3, ""); 52 | static_assert(r3 < r2, ""); 53 | static_assert(r1 >= r2, ""); 54 | static_assert(r3 <= r2, ""); 55 | static_assert(r5 == r6, ""); 56 | 57 | // Rational-integral comparison 58 | static_assert(r4 == 5, ""); 59 | static_assert(5 == r4, ""); 60 | static_assert(r1 != 3, ""); 61 | static_assert(8 != r2, ""); 62 | static_assert(0 < r1, ""); 63 | static_assert(r2 < 1, ""); 64 | static_assert(8 > r4, ""); 65 | static_assert(r2 > -1, ""); 66 | static_assert(5 <= r4, ""); 67 | static_assert(r3 <= 1, ""); 68 | static_assert(1 >= r3, ""); 69 | static_assert(r1 >= -8, ""); 70 | static_assert(r5 <= 0, ""); 71 | static_assert(r6 <= 0, ""); 72 | 73 | // Rational-rational arithmetic operations 74 | static_assert(r1 + r2 == 1, ""); 75 | static_assert(r4 - r1 == rational(9, 2), ""); 76 | static_assert(r2 * r3 == rational(1, 6), ""); 77 | static_assert(r1 / r3 == rational(3, 2), ""); 78 | 79 | // Rational-integral arithmetic operations 80 | static_assert(r1 + 1 == rational(3, 2), ""); 81 | static_assert(2 + r2 == rational(5, 2), ""); 82 | static_assert(r3 - 3 == rational(-8, 3), ""); 83 | static_assert(2 - r1 == rational(3, 2), ""); 84 | static_assert(r4 * 2 == 10, ""); 85 | static_assert(6 * r2 == r1 * 6, ""); 86 | static_assert(1 / r2 == 2, ""); 87 | static_assert(r3 / 3 == rational(1, 9), ""); 88 | 89 | // Cast 90 | static_assert(rational(1, 2) == rational(1, 2), ""); 91 | static_assert(rational(3, 2) == rational(3, 2), ""); 92 | static_assert(float(r1) == 0.5f, ""); 93 | static_assert(double(r1) == 0.5, ""); 94 | static_assert((long double)(r1) == 0.5l, ""); 95 | 96 | // User-defined literal 97 | static_assert(2 / 3_r == rational(2, 3), ""); 98 | static_assert(1_r / 8 == rational(1, 8), ""); 99 | static_assert(3 / 5_r == 3_r / 5, ""); 100 | 101 | constexpr auto a0 = rational(0, 1); 102 | constexpr auto a1 = rational(1, 2); 103 | constexpr auto a2 = rational(-3, 8); 104 | constexpr auto a3 = rational(6, -7); 105 | 106 | // Math functions 107 | static_assert(smath::sign(a0) == 0, ""); 108 | static_assert(smath::sign(a1) == 1, ""); 109 | static_assert(smath::sign(a2) == -1, ""); 110 | static_assert(smath::sign(a3) == -1, ""); 111 | 112 | static_assert(smath::abs(a1) == 1 / 2_r, ""); 113 | static_assert(smath::abs(a2) == 3 / 8_r, ""); 114 | static_assert(smath::abs(a3) == 6 / 7_r, ""); 115 | 116 | static_assert(smath::round(a1) == 1.0, ""); 117 | /* No more tests for ceil, floor, trunc 118 | * and round since they are based on 119 | * the floating point functions after 120 | * a simple cast. 121 | */ 122 | 123 | static_assert(smath::reciprocal(a1) == 2, ""); 124 | static_assert(smath::reciprocal(a2) == rational(8, -3), ""); 125 | 126 | static_assert(smath::pow(a1, 2) == 1 / 4_r, ""); 127 | static_assert(smath::pow(a2, 3) == -27 / 512_r, ""); 128 | static_assert(smath::pow(a3, -2) == 49 / 36_r, ""); 129 | static_assert(smath::pow(r1, 0) == 1_r, ""); 130 | static_assert(smath::pow(r2, 1) == r2, ""); 131 | static_assert(smath::pow(r7, 3) == 64 / 125_r, ""); 132 | } 133 | -------------------------------------------------------------------------------- /include/static_math/formula.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_FORMULA_H_ 25 | #define SMATH_FORMULA_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include "detail/core.h" 33 | 34 | namespace smath 35 | { 36 | //////////////////////////////////////////////////////////// 37 | // Basic functions 38 | 39 | /** 40 | * @brief signum function 41 | * @param val Any number 42 | * @return Sign of \a val 43 | */ 44 | template 45 | constexpr auto sign(Number x) 46 | -> int; 47 | 48 | /** 49 | * @brief Approximative comparison. 50 | * 51 | * Compares two floating point numbers by checking whether 52 | * the difference between the two of them is lower than a 53 | * given value. 54 | * 55 | * For other types, it performs a regular comparison. 56 | */ 57 | template 58 | constexpr auto is_close(T a, U b) 59 | -> bool; 60 | 61 | /** 62 | * @brief Sum of a number of variables 63 | */ 64 | template 65 | constexpr auto sum(T first, U second, Rest... rest) 66 | -> decltype(auto); 67 | 68 | /** 69 | * @brief Mean of a number of variables 70 | */ 71 | template 72 | constexpr auto mean(Numbers... args) 73 | -> decltype(sum(args...) / sizeof...(args)); 74 | 75 | /** 76 | * @brief Square function 77 | * @param x Some number 78 | * @return Square of \a x 79 | */ 80 | template 81 | constexpr auto sqr(Number x) 82 | -> decltype(auto); 83 | 84 | /** 85 | * @brief Limits a value to a range 86 | * @param val Number to clamp 87 | * @param min Lower limit 88 | * @param max Higher limit 89 | * @return \a val clamped between \a min and \a max 90 | */ 91 | template 92 | constexpr auto clamp(Number x, Number min, Number max) 93 | -> Number; 94 | 95 | //////////////////////////////////////////////////////////// 96 | // Integer-related functions 97 | 98 | /** 99 | * @brief Tells whether the given number is even 100 | * @param n Integer value 101 | * @return Whether \a n is even or not 102 | */ 103 | template 104 | constexpr auto is_even(Integer n) 105 | -> decltype(auto); 106 | 107 | /** 108 | * @brief Tells whether the given number is odd 109 | * @param n Integer value 110 | * @return Whether \a n is odd or not 111 | */ 112 | template 113 | constexpr auto is_odd(Integer n) 114 | -> decltype(auto); 115 | 116 | /** 117 | * @brief Tells whether the given number is a prime number 118 | * @param n Integer value 119 | * @return True if \a n is a prime number 120 | */ 121 | template 122 | constexpr auto is_prime(Integer n) 123 | -> bool; 124 | 125 | /** 126 | * @brief Fibonacci function 127 | * @param n Some integer 128 | * @return nth Fibonacci number 129 | */ 130 | template 131 | constexpr auto fibonacci(Integer n) 132 | -> Integer; 133 | 134 | /** 135 | * @brief Factorial function 136 | * @param n Some integer 137 | * @return Factorial of n 138 | */ 139 | template 140 | constexpr auto factorial(Integer n) 141 | -> decltype(auto); 142 | 143 | /** 144 | * @brief Greatest common divisor 145 | * @param a Some integer 146 | * @param b Some integer 147 | * @return Greatest common divisor of a and b 148 | */ 149 | template 150 | constexpr auto gcd(T a, U b) 151 | -> std::common_type_t; 152 | 153 | /** 154 | * @brief Least common multiple 155 | * @param a Some integer 156 | * @param b Some integer 157 | * @return Least common multiple of a and b 158 | */ 159 | template 160 | constexpr auto lcm(T a, U b) 161 | -> std::common_type_t; 162 | 163 | //////////////////////////////////////////////////////////// 164 | // Angle conversions 165 | 166 | /** 167 | * @brief Converts an angle in radians into an angle in degrees. 168 | * @param x Angle in radians 169 | * @return The degrees value 170 | */ 171 | template 172 | constexpr auto degrees(Float x) 173 | -> Float; 174 | 175 | /** 176 | * @brief Converts an angle in degrees into an angle in radians. 177 | * @param x Angle in degrees 178 | * @return The radians value 179 | */ 180 | template 181 | constexpr auto radians(Float x) 182 | -> Float; 183 | 184 | #include "detail/formula.inl" 185 | } 186 | 187 | #endif // SMATH_FORMULA_H_ 188 | -------------------------------------------------------------------------------- /test/complex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | 27 | using namespace smath; 28 | 29 | constexpr auto test(complex lhs, complex rhs) 30 | -> complex 31 | { 32 | lhs += rhs; 33 | lhs -= rhs; 34 | lhs.imag += rhs.imag; 35 | lhs.imag -= rhs.imag; 36 | 37 | lhs.imag *= rhs.real; 38 | lhs.imag /= rhs.real; 39 | 40 | return complex(lhs); 41 | } 42 | 43 | int main() 44 | { 45 | // Constructor tests 46 | constexpr imaginary i1; 47 | static_assert(i1.value == 0, ""); 48 | constexpr auto i2 = imaginary(5.8f); 49 | static_assert(smath::is_close(i2.value, 5.8f), ""); 50 | 51 | constexpr complex c1; 52 | static_assert(c1.real == 0, ""); 53 | static_assert(c1.imag.value == 0, ""); 54 | constexpr auto c2 = complex(1.2f, 2.5f); 55 | static_assert(smath::is_close(c2.real, 1.2f), ""); 56 | static_assert(smath::is_close(c2.imag.value, 2.5f), ""); 57 | 58 | constexpr auto imag0 = imaginary(0); 59 | constexpr auto imag1 = imaginary(1); 60 | constexpr auto imag2 = imaginary(-2); 61 | constexpr auto comp0 = complex(5, imag0); 62 | constexpr auto comp1 = complex(imag1); 63 | constexpr auto comp2 = complex(-1, 3); 64 | constexpr auto comp3 = complex(5); 65 | constexpr auto comp4 = complex(-2, 4); 66 | constexpr auto comp5 = 3 - 1_i; 67 | 68 | // Unary + and - 69 | static_assert(-imag1 == imaginary(-1), ""); 70 | static_assert(+imag1 == imaginary(1), ""); 71 | static_assert(+comp0 == complex(5, 0), ""); 72 | static_assert(-comp0 == complex(-5, 0), ""); 73 | 74 | // Comparison tests 75 | static_assert(5 == comp0, ""); 76 | static_assert(comp0 == 5, ""); 77 | static_assert(comp1 == imag1, ""); 78 | static_assert(imag1 == comp1, ""); 79 | static_assert(comp0 == comp3, ""); 80 | static_assert(comp3 == comp0, ""); 81 | static_assert(comp0 != 3, ""); 82 | static_assert(3 != comp0, ""); 83 | static_assert(imag0 != imag1, ""); 84 | static_assert(imag1 != imag0, ""); 85 | static_assert(comp0 != comp1, ""); 86 | static_assert(comp1 != comp0, ""); 87 | 88 | // imaginary-imaginary arithmetic 89 | static_assert(imag1 + imag1 == 2_i, ""); 90 | static_assert(imag1 - imag0 == 1_i, ""); 91 | static_assert(imag1 * imag1 == -1, ""); 92 | static_assert(4_i / 2_i == 2, ""); 93 | 94 | // imaginary-scalar arithmetic 95 | static_assert(imag1 + 2 == complex(2, 1), ""); 96 | static_assert(-3 + imag1 == complex(-3, 1), ""); 97 | static_assert(imag2 - 5 == complex(-5, -2), ""); 98 | static_assert(2 - imag2 == complex(2, 2), ""); 99 | static_assert(imag1 * 3 == imaginary(3), ""); 100 | static_assert(-4 * imag2 == imaginary(8), ""); 101 | static_assert(imag2 / 2 == -1_i, ""); 102 | static_assert(5 / imag1 == 5_i, ""); 103 | 104 | // complex-complex arithmetic 105 | static_assert(comp4 + comp5 == complex(1, 3), ""); 106 | static_assert(comp5 - comp4 == complex(5, -5), ""); 107 | static_assert(comp4 * comp5 == complex(-2, 14), ""); 108 | static_assert(comp4 / comp5 == complex(-1, 1), ""); 109 | 110 | // complex-scalar arithmetic 111 | static_assert(comp4 + 5 == complex(3, 4), ""); 112 | static_assert(-2 + comp5 == complex(1, -1), ""); 113 | static_assert(comp1 - 2 == complex(-2, 1), ""); 114 | static_assert(3 - comp2 == complex(4, -3), ""); 115 | static_assert(comp4 * 5 == complex(-10, 20), ""); 116 | static_assert(-2 * comp5 == complex(-6, 2), ""); 117 | static_assert(comp4 / 2 == complex(-1, 2), ""); 118 | static_assert(4 / complex(2, 2) == complex(1, -1), ""); 119 | 120 | // complex-imaginary arithmetic 121 | static_assert(comp1 + 5_i == complex(0, 6), ""); 122 | static_assert(-2_i + comp0 == complex(5, -2), ""); 123 | static_assert(comp2 - -1_i == complex(-1, 4), ""); 124 | static_assert(8_i - comp3 == complex(-5, 8), ""); 125 | static_assert(comp4 * 2_i == complex(-8, -4), ""); 126 | static_assert(-3_i * comp5 == complex(-3, -9), ""); 127 | static_assert(comp4 / 2_i == complex(2, 1), ""); 128 | static_assert(4_i / complex(2, 2) == complex(1, 1), ""); 129 | 130 | // Augmented assignment operators 131 | constexpr auto comp6 = 5 + 6_i; 132 | constexpr auto comp7 = 8ll + 2_ill; 133 | constexpr auto res = test(comp6, comp7); 134 | static_assert(smath::is_close(res.real, 5.0), ""); 135 | static_assert(smath::is_close(res.imag.value, 6.0), ""); 136 | 137 | // Mathematical functions 138 | constexpr auto c3 = 3.0f + 4.0_if; 139 | static_assert(smath::is_close(smath::norm(c3), 25.0f), ""); 140 | static_assert(smath::is_close(smath::abs(c3), 5.0f), ""); 141 | 142 | static_assert(smath::conj(comp4) == complex(-2, -4), ""); 143 | static_assert(smath::conj(comp5) == complex(3, 1), ""); 144 | } 145 | -------------------------------------------------------------------------------- /include/static_math/detail/formula.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2017 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | //////////////////////////////////////////////////////////// 26 | // Helper functions 27 | 28 | namespace detail 29 | { 30 | template 31 | constexpr auto is_prime_helper(T n, T div) 32 | -> bool 33 | { 34 | return (div*div > n) ? true : 35 | (n % div == 0) ? false : 36 | is_prime_helper(n, div+2); 37 | } 38 | 39 | template 40 | constexpr auto gcd_helper(T b, U r) 41 | -> std::common_type_t 42 | { 43 | return (r == 0) ? b : gcd_helper(r, b % r); 44 | } 45 | } 46 | 47 | //////////////////////////////////////////////////////////// 48 | // Basic functions 49 | 50 | template 51 | constexpr auto sign(Number x) 52 | -> int 53 | { 54 | return (x > 0) ? 1 : (x < 0) ? -1 : 0; 55 | } 56 | 57 | template 58 | constexpr auto is_close(T a, U b) 59 | -> bool 60 | { 61 | return detail::is_close(a, b); 62 | } 63 | 64 | template 65 | constexpr auto sum(T first, U second) 66 | -> decltype(auto) 67 | { 68 | return first + second; 69 | } 70 | 71 | template 72 | constexpr auto sum(T first, U second, Rest... rest) 73 | -> decltype(auto) 74 | { 75 | return first + sum(second, rest...); 76 | } 77 | 78 | template 79 | constexpr auto mean(Numbers... args) 80 | -> decltype(sum(args...) / sizeof...(args)) 81 | { 82 | return sum(args...) / sizeof...(args); 83 | } 84 | 85 | template 86 | constexpr auto sqr(Number x) 87 | -> decltype(auto) 88 | { 89 | return x * x; 90 | } 91 | 92 | template 93 | constexpr auto clamp(Number x, Number min, Number max) 94 | -> Number 95 | { 96 | return (x < min) ? min : (x > max) ? max : x; 97 | } 98 | 99 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 100 | template 101 | constexpr auto clamp(constant, constant, constant) 102 | -> constant 103 | { 104 | return {}; 105 | } 106 | #endif 107 | 108 | //////////////////////////////////////////////////////////// 109 | // Integer-related functions 110 | 111 | template 112 | constexpr auto is_even(Integer n) 113 | -> decltype(auto) 114 | { 115 | return detail::is_even(n); 116 | } 117 | 118 | template 119 | constexpr auto is_odd(Integer n) 120 | -> decltype(auto) 121 | { 122 | return detail::is_odd(n); 123 | } 124 | 125 | template 126 | constexpr auto is_prime(Integer n) 127 | -> bool 128 | { 129 | return (n < 2) ? false : 130 | (n == 2) ? true : 131 | (n % 2 == 0) ? false : 132 | detail::is_prime_helper(n, 3); 133 | } 134 | 135 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 136 | template 137 | constexpr auto is_prime(constant) 138 | -> constant 139 | { 140 | return {}; 141 | } 142 | #endif 143 | 144 | template 145 | constexpr auto fibonacci(Integer n) 146 | -> Integer 147 | { 148 | return (n < 2) ? n : fibonacci(n-2) + fibonacci(n-1); 149 | } 150 | 151 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 152 | template 153 | constexpr auto fibonacci(constant) 154 | -> constant 155 | { 156 | return {}; 157 | } 158 | #endif 159 | 160 | template 161 | constexpr auto factorial(Integer n) 162 | -> decltype(auto) 163 | { 164 | return detail::factorial(n); 165 | } 166 | 167 | template 168 | constexpr auto gcd(T a, U b) 169 | -> std::common_type_t 170 | { 171 | return (a == 0 || b == 0) ? 0 : 172 | (a < 0 || b < 0) ? gcd(detail::abs(a), detail::abs(b)) : 173 | (a >= b) ? detail::gcd_helper(b, a % b) : 174 | detail::gcd_helper(a, b % a); 175 | } 176 | 177 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 178 | template 179 | constexpr auto gcd(constant, constant) 180 | -> constant 181 | { 182 | return {}; 183 | } 184 | #endif 185 | 186 | template 187 | constexpr auto lcm(T a, U b) 188 | -> std::common_type_t 189 | { 190 | return (a == 0 || b == 0) ? 1 : 191 | a * b / gcd(a, b); 192 | } 193 | 194 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 195 | template 196 | constexpr auto lcm(constant, constant) 197 | -> constant 198 | { 199 | return {}; 200 | } 201 | #endif 202 | 203 | //////////////////////////////////////////////////////////// 204 | // Angle conversions 205 | 206 | template 207 | constexpr auto degrees(Float x) 208 | -> Float 209 | { 210 | return x * 180.0L / constants::pi; 211 | } 212 | 213 | template 214 | constexpr auto radians(Float x) 215 | -> Float 216 | { 217 | return x * constants::pi / 180.0L; 218 | } 219 | -------------------------------------------------------------------------------- /test/constant.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | 27 | int main() 28 | { 29 | using namespace smath::constant_literals; 30 | 31 | // Constant literals 32 | { 33 | static_assert(0_c == 0, ""); 34 | static_assert(1_c == 1, ""); 35 | static_assert(-1_c == -1, ""); 36 | static_assert(45_cl == 45l, ""); 37 | static_assert(52_cll == 52ll, ""); 38 | static_assert(decltype(45_cu)::value == 45u, ""); 39 | static_assert(91_cul == 91ul, ""); 40 | static_assert(23_cull == (long long unsigned)23, ""); 41 | 42 | static_assert( 43 | std::is_same< 44 | decltype(58_c), 45 | smath::constant 46 | >::value, ""); 47 | 48 | // Should be too big for an int but will either fit 49 | // a long or a long long depending on the platform 50 | // (assume well-known reasonable platforms) 51 | using big_type = decltype(1844674407370955161_c); 52 | static_assert( 53 | std::is_same::value || 54 | std::is_same::value, 55 | ""); 56 | 57 | constexpr auto a = 42_c; 58 | constexpr auto b = +a; 59 | static_assert(b == 42, ""); 60 | static_assert(b == +42_c, ""); 61 | static_assert(b == 42_c, ""); 62 | 63 | static_assert( 64 | std::is_same< 65 | decltype(+58_c), 66 | smath::constant 67 | >::value, ""); 68 | } 69 | 70 | // Constant unary operators 71 | { 72 | constexpr auto a = 42_c; 73 | constexpr auto b = -a; 74 | static_assert(b == -42, ""); 75 | static_assert(b == -42_c, ""); 76 | 77 | static_assert( 78 | std::is_same< 79 | decltype(-58_c), 80 | smath::constant 81 | >::value, ""); 82 | 83 | static_assert(smath::true_type{}, ""); 84 | static_assert(!smath::false_type{}, ""); 85 | static_assert(!!smath::true_type{}, ""); 86 | 87 | static_assert( 88 | std::is_same< 89 | decltype(!smath::false_type{}), 90 | smath::true_type 91 | >::value, ""); 92 | 93 | static_assert( 94 | std::is_same< 95 | decltype(!!smath::false_type{}), 96 | smath::false_type 97 | >::value, ""); 98 | } 99 | 100 | // Constant binary arithmetic operators 101 | { 102 | static_assert(0_c + 0_c == 0_c, ""); 103 | static_assert(1_c + 0_c == 1_c, ""); 104 | static_assert(0_c + 1_c == 1_c, ""); 105 | static_assert(88_c + 22_c == 110_c, ""); 106 | 107 | static_assert(0_c - 0_c == 0_c, ""); 108 | static_assert(1_c - 0_c == 1_c, ""); 109 | static_assert(0_c - 1_c == -1_c, ""); 110 | static_assert(88_c - 22_c == 66_c, ""); 111 | 112 | static_assert(0_c * 0_c == 0_c, ""); 113 | static_assert(1_c * 0_c == 0_c, ""); 114 | static_assert(0_c * 1_c == 0_c, ""); 115 | static_assert(88_c * 22_c == 1936_c, ""); 116 | 117 | static_assert(0_c / 1_c == 0_c, ""); 118 | static_assert(88_c / 22_c == 4_c, ""); 119 | 120 | static_assert(0_c + 0_c == 0_c, ""); 121 | static_assert(1_c + 0_c == 1_c, ""); 122 | static_assert(0_c + 1_c == 1_c, ""); 123 | static_assert(88_c + 22_c == 110_c, ""); 124 | 125 | static_assert(27_c % 16_c == 11_c, ""); 126 | static_assert(30_c % 3_c == 0_c, ""); 127 | static_assert(35_c % 3_c == 2_c, ""); 128 | static_assert(16_c % 6_c == 4_c, ""); 129 | static_assert(15_c % 12_c == 3_c, ""); 130 | } 131 | 132 | // Constant comparison operators 133 | { 134 | static_assert(52_c == 52_c, ""); 135 | static_assert(0_c != 1_c, ""); 136 | 137 | static_assert( 138 | std::is_same< 139 | decltype(45_c == 23_c), 140 | smath::false_type 141 | >::value, ""); 142 | 143 | static_assert( 144 | std::is_same< 145 | decltype(45_c != 23_c), 146 | smath::true_type 147 | >::value, ""); 148 | } 149 | 150 | // Constant relational operators 151 | { 152 | static_assert(51_c < 52_c, ""); 153 | static_assert(23_c <= 42_c, ""); 154 | static_assert(23_c <= 23_c, ""); 155 | static_assert(29_c > 17_c, ""); 156 | static_assert(85_c >= 53_c, ""); 157 | static_assert(87_c >= 87_c, ""); 158 | 159 | static_assert( 160 | std::is_same< 161 | decltype(45_c < 23_c), 162 | smath::false_type 163 | >::value, ""); 164 | 165 | static_assert( 166 | std::is_same< 167 | decltype(45_c <= 23_c), 168 | smath::false_type 169 | >::value, ""); 170 | 171 | static_assert( 172 | std::is_same< 173 | decltype(45_c > 23_c), 174 | smath::true_type 175 | >::value, ""); 176 | 177 | static_assert( 178 | std::is_same< 179 | decltype(45_c >= 23_c), 180 | smath::true_type 181 | >::value, ""); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /docs/Common-mathematical-functions.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | All the functions in this header more or less correspond to their equivalents in the standard library header ``, reworked as `constexpr` functions. Some of the functions are less powerful than the standard library ones (`smath::pow` only works with integral exponents) while other functions are more powerful (most functions are templated, `hypot` is variadic...). 6 | 7 | ### Basic functions 8 | 9 | ```cpp 10 | template 11 | constexpr auto abs(Number x) 12 | -> Number; 13 | ``` 14 | 15 | Computes the [absolute value](https://en.wikipedia.org/wiki/Absolute_value) of a given number. Unlike the corresponding standard library function, this function also accepts unsigned integer values and returns them unchanged. 16 | 17 | *This function is overloaded so that it can handle [[integral constants]].* 18 | 19 | ```cpp 20 | template 21 | constexpr auto div(Number x, Number y) 22 | -> smath::div_t; 23 | ``` 24 | 25 | Computes both the quotient and the remainder of the division of the numerator `x` by the denominator `y`. The return type `smath::div_t` contains two members variables `quot` and `rem` which denote the quotient and the remainder. If `Number` is either `int`, `long int` or `long long int`, the corresponding `smath::div_t` wil respectively inherit from `std::div_t`, `std::ldiv_t` or `std::lldiv_t` to make conversion from existing code easier. If `std::intmax_t` is different from `long long int`, then `smath::div_t` will inherit from `std::imaxdiv_t`. 26 | 27 | ```cpp 28 | template 29 | constexpr auto min(T first, U second, Rest... rest) 30 | -> std::common_type_t; 31 | ``` 32 | 33 | Returns the smallest value among a given number of values. 34 | 35 | *This function is overloaded so that it can handle [[integral constants]].* 36 | 37 | ```cpp 38 | template 39 | constexpr auto max(T first, U second, Rest... rest) 40 | -> std::common_type_t; 41 | ``` 42 | 43 | Returns the greatest value among a given number of values. 44 | 45 | *This function is overloaded so that it can handle [[integral constants]].* 46 | 47 | ### Number-theoretic and representation functions 48 | 49 | ```cpp 50 | template 51 | constexpr auto floor(Float x) 52 | -> decltype(std::floor(x)); 53 | ``` 54 | 55 | Computes the largest integer value not greater than `x`. 56 | 57 | ```cpp 58 | template 59 | constexpr auto ceil(Float x) 60 | -> decltype(std::ceil(x)); 61 | ``` 62 | 63 | Computes the smallest integer value not less than `x`. 64 | 65 | ```cpp 66 | template 67 | constexpr auto round(Float x) 68 | -> decltype(std::round(x)); 69 | ``` 70 | 71 | Computes the nearest integer value to `x` (in floating-point format), rounding halfway cases away from zero, regardless of the current rounding mode. 72 | 73 | For usability reasons, the functions `lround` and `llround` are also available, providing the same type conversions than their standard library equivalents. 74 | 75 | ```cpp 76 | template 77 | constexpr auto trunc(Float x) 78 | -> decltype(std::trunc(x)); 79 | ``` 80 | 81 | Computes the nearest integer not greater in magnitude than `x`. 82 | 83 | ### Power and logarithmic functions 84 | 85 | ```cpp 86 | template 87 | constexpr auto exp(Float x) 88 | -> decltype(std::exp(x)); 89 | ``` 90 | 91 | Computes the [exponential](https://en.wikipedia.org/wiki/Exponential_function) of `x`. 92 | 93 | ```cpp 94 | template 95 | constexpr auto pow(Number x, Integer exponent) 96 | -> std::common_type_t; 97 | ``` 98 | 99 | Computes the value of `x` raised to the power `exponent`. Note however that this function only accepts integer exponents. 100 | 101 | *This function is overloaded so that it can handle [[integral constants]].* 102 | 103 | ```cpp 104 | template 105 | constexpr auto log(Float x) 106 | -> decltype(std::log(x)); 107 | ``` 108 | 109 | Computes the the [natural logarithm](https://en.wikipedia.org/wiki/Natural_logarithm) (base *e*) of `x`. 110 | 111 | ```cpp 112 | template 113 | constexpr auto log2(Float x) 114 | -> decltype(std::log2(x)); 115 | ``` 116 | 117 | Computes the the [binary logarithm](https://en.wikipedia.org/wiki/Binary_logarithm) (base 2) of `x`. 118 | 119 | ```cpp 120 | template 121 | constexpr auto log10(Float x) 122 | -> decltype(std::log10(x)); 123 | ``` 124 | 125 | Computes the the [common logarithm](https://en.wikipedia.org/wiki/Common_logarithm) (base 10) of `x`. 126 | 127 | ```cpp 128 | template 129 | constexpr auto sqrt(Float x) 130 | -> decltype(std::sqrt(x)); 131 | ``` 132 | 133 | Computes the [square root](https://en.wikipedia.org/wiki/Square_root) of `x`, using the [Babylonian method](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method). This function recurses until the best possible precision for a given floating point type is found. 134 | 135 | ```cpp 136 | template 137 | constexpr auto hypot(Args... args) 138 | -> decltype(auto); 139 | ``` 140 | 141 | Computes the square root of the sum of the squares of `args...`, without undue overflow or underflow at intermediate stages of the computation. The passed parameters are converted to the appropriate floating point type prior to the computation; the return type is the type common to these converted types. 142 | 143 | ### Trigonometric functions 144 | 145 | ```cpp 146 | template 147 | constexpr auto sin(Float x) 148 | -> Float; 149 | ``` 150 | 151 | Computes the sine of `x` (measured in radians). 152 | 153 | ```cpp 154 | template 155 | constexpr auto cos(Float x) 156 | -> Float; 157 | ``` 158 | 159 | Computes the cosine of `x` (measured in radians). 160 | 161 | ```cpp 162 | template 163 | constexpr auto tan(Float x) 164 | -> Float; 165 | ``` 166 | 167 | Computes the tangent of `x` (measured in radians). 168 | 169 | ### Hyperbolic functions 170 | 171 | ```cpp 172 | template 173 | constexpr auto sinh(Float x) 174 | -> Float; 175 | ``` 176 | 177 | Computes hyperbolic the sine of `x` (measured in radians). 178 | 179 | ```cpp 180 | template 181 | constexpr auto cosh(Float x) 182 | -> Float; 183 | ``` 184 | 185 | Computes the hyperbolic cosine of `x` (measured in radians). 186 | 187 | ```cpp 188 | template 189 | constexpr auto tanh(Float x) 190 | -> Float; 191 | ``` 192 | 193 | Computes the hyperbolic tangent of `x` (measured in radians). 194 | -------------------------------------------------------------------------------- /include/static_math/detail/constant.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | //////////////////////////////////////////////////////////// 26 | // Check whether a type is an integral constant 27 | 28 | namespace detail 29 | { 30 | template 31 | struct is_integral_constant: 32 | std::false_type 33 | {}; 34 | 35 | template 36 | struct is_integral_constant>: 37 | std::true_type 38 | {}; 39 | } 40 | 41 | //////////////////////////////////////////////////////////// 42 | // Unary arithmetic operators 43 | 44 | template 45 | constexpr auto operator+(constant) 46 | -> constant 47 | { 48 | return {}; 49 | } 50 | 51 | template 52 | constexpr auto operator-(constant) 53 | -> constant 54 | { 55 | return {}; 56 | } 57 | 58 | //////////////////////////////////////////////////////////// 59 | // Binary arithmetic operators 60 | 61 | template 62 | constexpr auto operator+(constant, constant) 63 | -> constant 64 | { 65 | return {}; 66 | } 67 | 68 | template 69 | constexpr auto operator-(constant, constant) 70 | -> constant 71 | { 72 | return {}; 73 | } 74 | 75 | template 76 | constexpr auto operator*(constant, constant) 77 | -> constant 78 | { 79 | return {}; 80 | } 81 | 82 | template 83 | constexpr auto operator/(constant, constant) 84 | -> constant 85 | { 86 | return {}; 87 | } 88 | 89 | template 90 | constexpr auto operator%(constant, constant) 91 | -> constant 92 | { 93 | return {}; 94 | } 95 | 96 | //////////////////////////////////////////////////////////// 97 | // Equality operators 98 | 99 | template 100 | constexpr auto operator==(constant, constant) 101 | -> constant 102 | { 103 | return {}; 104 | } 105 | 106 | template 107 | constexpr auto operator!=(constant, constant) 108 | -> constant 109 | { 110 | return {}; 111 | } 112 | 113 | //////////////////////////////////////////////////////////// 114 | // Relational operators 115 | 116 | template 117 | constexpr auto operator<(constant, constant) 118 | -> constant 119 | { 120 | return {}; 121 | } 122 | 123 | template 124 | constexpr auto operator<=(constant, constant) 125 | -> constant 126 | { 127 | return {}; 128 | } 129 | 130 | template 131 | constexpr auto operator>(constant, constant) 132 | -> constant M)> 133 | { 134 | return {}; 135 | } 136 | 137 | template 138 | constexpr auto operator>=(constant, constant) 139 | -> constant= M)> 140 | { 141 | return {}; 142 | } 143 | 144 | //////////////////////////////////////////////////////////// 145 | // Logical operators 146 | 147 | template 148 | constexpr auto operator&&(constant, constant) 149 | -> constant 150 | { 151 | return {}; 152 | } 153 | 154 | template 155 | constexpr auto operator||(constant, constant) 156 | -> constant 157 | { 158 | return {}; 159 | } 160 | 161 | template 162 | constexpr auto operator!(constant) 163 | -> constant 164 | { 165 | return {}; 166 | } 167 | 168 | //////////////////////////////////////////////////////////// 169 | // User-defined literals 170 | 171 | inline namespace literals 172 | { 173 | inline namespace constant_literals 174 | { 175 | template 176 | constexpr auto operator"" _c() 177 | -> constant< 178 | detail::parse_t, 179 | detail::parse::value 180 | > 181 | { 182 | return {}; 183 | } 184 | 185 | template 186 | constexpr auto operator"" _cl() 187 | -> constant< 188 | detail::parse_t, 189 | detail::parse::value 190 | > 191 | { 192 | return {}; 193 | } 194 | 195 | template 196 | constexpr auto operator"" _cll() 197 | -> constant< 198 | detail::parse_t, 199 | detail::parse::value 200 | > 201 | { 202 | return {}; 203 | } 204 | 205 | template 206 | constexpr auto operator"" _cu() 207 | -> constant< 208 | detail::parse_t, 209 | detail::parse::value 210 | > 211 | { 212 | return {}; 213 | } 214 | 215 | template 216 | constexpr auto operator"" _cul() 217 | -> constant< 218 | detail::parse_t, 219 | detail::parse::value 220 | > 221 | { 222 | return {}; 223 | } 224 | 225 | template 226 | constexpr auto operator"" _cull() 227 | -> constant< 228 | detail::parse_t, 229 | detail::parse::value 230 | > 231 | { 232 | return {}; 233 | } 234 | }} 235 | -------------------------------------------------------------------------------- /include/static_math/cmath.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2018 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_CMATH_H_ 25 | #define SMATH_CMATH_H_ 26 | 27 | /** 28 | * @file static_math/cmath.h 29 | * @brief compile-time clone of the standard header . 30 | * 31 | * This header provides functions aimed to have at least the 32 | * same features as the ones in the standard header . 33 | * The names can be changed (for example fabs, fmin and fmax 34 | * do not exist here) and some additional features can be 35 | * added to some of the functions, such as a variadic number 36 | * of arguments or a support for more different types. 37 | */ 38 | 39 | //////////////////////////////////////////////////////////// 40 | // Headers 41 | //////////////////////////////////////////////////////////// 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include "detail/core.h" 52 | 53 | namespace smath 54 | { 55 | //////////////////////////////////////////////////////////// 56 | // Basic functions 57 | 58 | /** 59 | * @brief Absolute value of a number 60 | */ 61 | template 62 | constexpr auto abs(Number x) 63 | -> decltype(auto); 64 | 65 | // Return type of div 66 | template 67 | struct div_t; 68 | 69 | /** 70 | * @brief Computes both quotient and remainder at once 71 | */ 72 | template 73 | constexpr auto div(Number x, Number y) 74 | -> div_t; 75 | 76 | /** 77 | * @brief Min of a number of variables 78 | */ 79 | template 80 | constexpr auto min(Args... args) 81 | -> decltype(auto); 82 | 83 | /** 84 | * @brief Max of a number of variables 85 | */ 86 | template 87 | constexpr auto max(Args... args) 88 | -> decltype(auto); 89 | 90 | //////////////////////////////////////////////////////////// 91 | // Number-theoretic and representation functions 92 | 93 | template 94 | constexpr auto floor(Float x) 95 | -> decltype(std::floor(x)); 96 | 97 | template 98 | constexpr auto ceil(Float x) 99 | -> decltype(std::ceil(x)); 100 | 101 | template 102 | constexpr auto round(Float x) 103 | -> decltype(std::round(x)); 104 | 105 | template 106 | constexpr auto lround(Float x) 107 | -> decltype(std::lround(x)); 108 | 109 | template 110 | constexpr auto llround(Float x) 111 | -> decltype(std::llround(x)); 112 | 113 | template 114 | constexpr auto trunc(Float x) 115 | -> decltype(std::trunc(x)); 116 | 117 | //////////////////////////////////////////////////////////// 118 | // Power and logarithmic functions 119 | 120 | /** 121 | * @brief Exponential function. 122 | */ 123 | template 124 | constexpr auto exp(Float x) 125 | -> decltype(std::exp(x)); 126 | 127 | /** 128 | * @brief Power function 129 | * 130 | * @warning This functions is only available for the integer 131 | * @warning exponent right now. 132 | */ 133 | template 134 | constexpr auto pow(Number x, Integer exponent) 135 | -> std::common_type_t; 136 | 137 | /** 138 | * @brief Natural Log function 139 | */ 140 | template 141 | constexpr auto log(Float x) 142 | -> decltype(std::log(x)); 143 | 144 | /** 145 | * @brief Log base 2 function 146 | */ 147 | template 148 | constexpr auto log2(Float x) 149 | -> decltype(std::log2(x)); 150 | 151 | /** 152 | * @brief Log base 10 function 153 | */ 154 | template 155 | constexpr auto log10(Float x) 156 | -> decltype(std::log10(x)); 157 | 158 | /** 159 | * @brief Square root function 160 | * 161 | * Square root computation with the Babylonian method until 162 | * the best possible precision for the given floating point 163 | * type. 164 | */ 165 | template 166 | constexpr auto sqrt(Float x) 167 | -> decltype(std::sqrt(x)); 168 | 169 | /** 170 | * @brief Hypotenuse function 171 | * 172 | * Computes the square root of the sum of the squares of \a x 173 | * and \a y, without undue overflow or underflow during the 174 | * intermediate stages of the computation. 175 | */ 176 | template 177 | constexpr auto hypot(Args... args) 178 | -> decltype(auto); 179 | 180 | //////////////////////////////////////////////////////////// 181 | // Trigonometric functions 182 | 183 | /** 184 | * @brief Sine function. 185 | * @param x Angle in radians 186 | */ 187 | template 188 | constexpr auto sin(Float x) 189 | -> Float; 190 | 191 | /** 192 | * @brief Cosine function. 193 | * @param x Angle in radians 194 | */ 195 | template 196 | constexpr auto cos(Float x) 197 | -> Float; 198 | 199 | /** 200 | * @brief Tangent function. 201 | * @param x Angle in radians 202 | */ 203 | template 204 | constexpr auto tan(Float x) 205 | -> Float; 206 | 207 | //////////////////////////////////////////////////////////// 208 | // Hyperbolic functions 209 | 210 | /** 211 | * @brief Hyperbolic sine function. 212 | * @param x Hyperbolic angle in radians 213 | */ 214 | template 215 | constexpr auto sinh(Float x) 216 | -> Float; 217 | 218 | /** 219 | * @brief Hyperbolic cosine function. 220 | * @param x Hyperbolic angle in radians 221 | */ 222 | template 223 | constexpr auto cosh(Float x) 224 | -> Float; 225 | 226 | /** 227 | * @brief Hyperbolic tangent function. 228 | * @param x Hyperbolic angle in radians 229 | */ 230 | template 231 | constexpr auto tanh(Float x) 232 | -> Float; 233 | 234 | #include "detail/cmath.inl" 235 | } 236 | 237 | #endif // SMATH_CMATH_H_ 238 | -------------------------------------------------------------------------------- /test/formula.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | 27 | int main() 28 | { 29 | //////////////////////////////////////////////////////////// 30 | // Regular functions 31 | 32 | static_assert(smath::sign(5) == 1, ""); 33 | static_assert(smath::sign(-3) == -1, ""); 34 | static_assert(smath::sign(2.0) == 1, ""); 35 | static_assert(smath::sign(-5.8) == -1, ""); 36 | static_assert(smath::sign(0) == 0, ""); 37 | static_assert(smath::sign(0.0) == 0, ""); 38 | 39 | static_assert(smath::is_even(5) == false, ""); 40 | static_assert(smath::is_even(-4) == true, ""); 41 | static_assert(smath::is_even(0) == true, ""); 42 | 43 | static_assert(smath::is_odd(8) == false, ""); 44 | static_assert(smath::is_odd(0) == false, ""); 45 | static_assert(smath::is_odd(-5) == true, ""); 46 | 47 | static_assert(smath::is_prime(0) == false, ""); 48 | static_assert(smath::is_prime(1) == false, ""); 49 | static_assert(smath::is_prime(2) == true, ""); 50 | static_assert(smath::is_prime(3) == true, ""); 51 | static_assert(smath::is_prime(4) == false, ""); 52 | static_assert(smath::is_prime(5) == true, ""); 53 | static_assert(smath::is_prime(7) == true, ""); 54 | static_assert(smath::is_prime(8) == false, ""); 55 | static_assert(smath::is_prime(9) == false, ""); 56 | static_assert(smath::is_prime(128) == false, ""); 57 | 58 | static_assert(smath::fibonacci(0) == 0, ""); 59 | static_assert(smath::fibonacci(1) == 1, ""); 60 | static_assert(smath::fibonacci(2) == 1, ""); 61 | static_assert(smath::fibonacci(3) == 2, ""); 62 | static_assert(smath::fibonacci(4) == 3, ""); 63 | static_assert(smath::fibonacci(5) == 5, ""); 64 | static_assert(smath::fibonacci(6) == 8, ""); 65 | static_assert(smath::fibonacci(7) == 13, ""); 66 | static_assert(smath::fibonacci(8) == 21, ""); 67 | 68 | static_assert(smath::factorial(0) == 1, ""); 69 | static_assert(smath::factorial(1) == 1, ""); 70 | static_assert(smath::factorial(2) == 2, ""); 71 | static_assert(smath::factorial(3) == 6, ""); 72 | static_assert(smath::factorial(4) == 24, ""); 73 | static_assert(smath::factorial(5) == 120, ""); 74 | static_assert(smath::factorial(6) == 720, ""); 75 | static_assert(smath::factorial(7) == 5040, ""); 76 | 77 | static_assert( 78 | smath::sum(1, 2, 3, 4, 5) == 15, 79 | ""); 80 | 81 | static_assert(smath::gcd(1071, 1029) == 21, ""); 82 | static_assert(smath::gcd(1029, 1071) == 21, ""); 83 | static_assert(smath::gcd(270, 84) == 6, ""); 84 | static_assert(smath::gcd(84, 270) == 6, ""); 85 | 86 | static_assert(smath::gcd(3, 6) == 3, ""); 87 | static_assert(smath::gcd(-3, 6) == 3, ""); 88 | static_assert(smath::gcd(3, -6) == 3, ""); 89 | static_assert(smath::gcd(-3, -6) == 3, ""); 90 | 91 | static_assert(smath::lcm(60, 168) == 840, ""); 92 | static_assert(smath::lcm(168, 60) == 840, ""); 93 | 94 | static_assert(smath::clamp(3, 2, 4) == 3, ""); 95 | static_assert(smath::clamp(1, 2, 4) == 2, ""); 96 | static_assert(smath::clamp(5, 2, 4) == 4, ""); 97 | 98 | //////////////////////////////////////////////////////////// 99 | // smath::constant overloads 100 | 101 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 102 | using namespace smath::constant_literals; 103 | 104 | static_assert( 105 | std::is_same< 106 | decltype(smath::sqr(5_c)), 107 | smath::constant 108 | >::value, ""); 109 | 110 | static_assert(not smath::is_even(5_c), ""); 111 | static_assert( smath::is_even(-4_c), ""); 112 | static_assert( smath::is_even(0_c), ""); 113 | 114 | static_assert(not smath::is_odd(8_c), ""); 115 | static_assert(not smath::is_odd(0_c), ""); 116 | static_assert( smath::is_odd(-5_c), ""); 117 | 118 | static_assert(not smath::is_prime(0_c), ""); 119 | static_assert(not smath::is_prime(1_c), ""); 120 | static_assert( smath::is_prime(2_c), ""); 121 | static_assert( smath::is_prime(3_c), ""); 122 | static_assert(not smath::is_prime(4_c), ""); 123 | static_assert( smath::is_prime(5_c), ""); 124 | static_assert( smath::is_prime(7_c), ""); 125 | static_assert(not smath::is_prime(8_c), ""); 126 | static_assert(not smath::is_prime(9_c), ""); 127 | static_assert(not smath::is_prime(128_c), ""); 128 | 129 | static_assert(smath::fibonacci(0_c) == 0_c, ""); 130 | static_assert(smath::fibonacci(1_c) == 1_c, ""); 131 | static_assert(smath::fibonacci(2_c) == 1_c, ""); 132 | static_assert(smath::fibonacci(3_c) == 2_c, ""); 133 | static_assert(smath::fibonacci(4_c) == 3_c, ""); 134 | static_assert(smath::fibonacci(5_c) == 5_c, ""); 135 | static_assert(smath::fibonacci(6_c) == 8_c, ""); 136 | static_assert(smath::fibonacci(7_c) == 13_c, ""); 137 | static_assert(smath::fibonacci(8_c) == 21_c, ""); 138 | 139 | static_assert(smath::factorial(0_c) == 1_c, ""); 140 | static_assert(smath::factorial(1_c) == 1_c, ""); 141 | static_assert(smath::factorial(2_c) == 2_c, ""); 142 | static_assert(smath::factorial(3_c) == 6_c, ""); 143 | static_assert(smath::factorial(4_c) == 24_c, ""); 144 | static_assert(smath::factorial(5_c) == 120_c, ""); 145 | static_assert(smath::factorial(6_c) == 720_c, ""); 146 | static_assert(smath::factorial(7_c) == 5040_c, ""); 147 | 148 | static_assert( 149 | smath::sum(1_c, 2_c, 3_c, 4_c, 5_c) == 15_c, 150 | ""); 151 | 152 | static_assert( 153 | std::is_same< 154 | decltype(smath::sum(1_c, 2_c, 3_c, 4_c, 5_c)), 155 | smath::constant 156 | >::value, ""); 157 | 158 | static_assert(smath::gcd(1071_c, 1029_c) == 21_c, ""); 159 | static_assert(smath::gcd(1029_c, 1071_c) == 21_c, ""); 160 | static_assert(smath::gcd(270_c, 84_c) == 6_c, ""); 161 | static_assert(smath::gcd(84_c, 270_c) == 6_c, ""); 162 | 163 | static_assert(smath::gcd(3_c, 6_c) == 3_c, ""); 164 | static_assert(smath::gcd(-3_c, 6_c) == 3_c, ""); 165 | static_assert(smath::gcd(3_c, -6_c) == 3_c, ""); 166 | static_assert(smath::gcd(-3_c, -6_c) == 3_c, ""); 167 | 168 | static_assert(smath::lcm(60_c, 168_c) == 840_c, ""); 169 | static_assert(smath::lcm(168_c, 60_c) == 840_c, ""); 170 | 171 | static_assert(smath::clamp(3_c, 2_c, 4_c) == 3_c, ""); 172 | static_assert(smath::clamp(1_c, 2_c, 4_c) == 2_c, ""); 173 | static_assert(smath::clamp(5_c, 2_c, 4_c) == 4_c, ""); 174 | 175 | static_assert( 176 | std::is_same< 177 | decltype(smath::clamp(5_c, 2_c, 4_c)), 178 | smath::constant 179 | >::value, ""); 180 | #endif 181 | } 182 | -------------------------------------------------------------------------------- /include/static_math/detail/core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2019 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_DETAIL_CORE_H_ 25 | #define SMATH_DETAIL_CORE_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | #include "logical_traits.h" 34 | 35 | // This header contains very basic functions that are 36 | // often used by many headers but may introduce some 37 | // annoying circular dependencies if not isolated 38 | 39 | namespace smath 40 | { 41 | namespace detail 42 | { 43 | //////////////////////////////////////////////////////////// 44 | // Trait to delay instantiation of value_type 45 | 46 | template 47 | struct is_same_value_type: 48 | std::is_same< 49 | typename T::value_type, 50 | typename U::value_type 51 | > 52 | {}; 53 | 54 | //////////////////////////////////////////////////////////// 55 | // Absolute value 56 | 57 | template 58 | constexpr auto abs(Number x) 59 | -> std::enable_if_t< 60 | std::is_unsigned::value, 61 | Number 62 | > 63 | { 64 | return x; 65 | } 66 | 67 | template 68 | constexpr auto abs(Number x) 69 | -> std::enable_if_t< 70 | !std::is_unsigned::value, 71 | Number 72 | > 73 | { 74 | return (x >= 0) ? x : -x; 75 | } 76 | 77 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 78 | template 79 | constexpr auto abs(constant) 80 | -> constant 81 | { 82 | return {}; 83 | } 84 | #endif 85 | 86 | //////////////////////////////////////////////////////////// 87 | // Minimal and maximal values 88 | 89 | template< 90 | typename T, typename U, 91 | typename = std::enable_if_t, 93 | is_integral_constant, 94 | is_same_value_type 95 | >>::value> 96 | > 97 | constexpr auto min(T first, U second) 98 | -> std::common_type_t 99 | { 100 | return (first < second) ? first : second; 101 | } 102 | 103 | template< 104 | typename T, typename U, typename... Rest, 105 | typename = std::enable_if_t, 107 | is_integral_constant, 108 | is_same_value_type 109 | >>::value> 110 | > 111 | constexpr auto min(T first, U second, Rest... rest) 112 | -> std::common_type_t 113 | { 114 | return (first < second) ? 115 | detail::min(first, rest...) : 116 | detail::min(second, rest...); 117 | } 118 | 119 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 120 | template 121 | constexpr auto min(constant...) 122 | -> constant 123 | { 124 | return {}; 125 | } 126 | #endif 127 | 128 | template< 129 | typename T, typename U, 130 | typename = std::enable_if_t, 132 | is_integral_constant, 133 | is_same_value_type 134 | >>::value> 135 | > 136 | constexpr auto max(T first, U second) 137 | -> std::common_type_t 138 | { 139 | return (first > second) ? first : second; 140 | } 141 | 142 | template< 143 | typename T, typename U, typename... Rest, 144 | typename = std::enable_if_t, 146 | is_integral_constant, 147 | is_same_value_type 148 | >>::value> 149 | > 150 | constexpr auto max(T first, U second, Rest... rest) 151 | -> std::common_type_t 152 | { 153 | return (first > second) ? 154 | detail::max(first, rest...) : 155 | detail::max(second, rest...); 156 | } 157 | 158 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 159 | template 160 | constexpr auto max(constant...) 161 | -> constant 162 | { 163 | return {}; 164 | } 165 | #endif 166 | 167 | //////////////////////////////////////////////////////////// 168 | // Whether two values are close 169 | 170 | template 171 | using lesser_of = std::conditional_t< 172 | sizeof(T) <= sizeof(U), 173 | T, 174 | U 175 | >; 176 | 177 | template 178 | constexpr auto is_close(T a, U b) 179 | -> std::enable_if_t< 180 | std::is_floating_point::value && std::is_floating_point::value, 181 | bool 182 | > 183 | { 184 | // https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon 185 | return smath::detail::abs(a - b) <= 186 | std::numeric_limits>::epsilon() * smath::detail::abs(a + b) 187 | || smath::detail::abs(a - b) < std::numeric_limits>::min(); 188 | } 189 | 190 | template 191 | constexpr auto is_close(T a, U b) 192 | -> std::enable_if_t< 193 | !std::is_floating_point::value || !std::is_floating_point::value, 194 | bool 195 | > 196 | { 197 | return a == b; 198 | } 199 | 200 | //////////////////////////////////////////////////////////// 201 | // Odd & even checks 202 | 203 | template 204 | constexpr auto is_even(Integer n) 205 | -> decltype(auto) 206 | { 207 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 208 | using namespace constant_literals; 209 | return !(n % 2_c); 210 | #else 211 | return !(n % 2); 212 | #endif 213 | } 214 | 215 | template 216 | constexpr auto is_odd(Integer n) 217 | -> decltype(auto) 218 | { 219 | return !detail::is_even(n); 220 | } 221 | 222 | //////////////////////////////////////////////////////////// 223 | // Factorial function 224 | 225 | template 226 | constexpr auto factorial(Integer n) 227 | -> Integer 228 | { 229 | Integer res = 1; 230 | for (Integer i = 2 ; i <= n ; ++i) 231 | { 232 | res *= i; 233 | } 234 | return res; 235 | } 236 | 237 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 238 | template 239 | constexpr auto factorial(constant) 240 | -> constant 241 | { 242 | return {}; 243 | } 244 | #endif 245 | }} 246 | 247 | #endif // SMATH_DETAIL_CORE_H_ 248 | -------------------------------------------------------------------------------- /include/static_math/constant.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015-2018 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_CONSTANT_H_ 25 | #define SMATH_CONSTANT_H_ 26 | 27 | // Integral constants were broken with old MSVC++ versions 28 | 29 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 30 | # if defined(_MSC_VER) && _MSC_VER < 1912 31 | # define STATIC_MATH_NO_INTEGRAL_CONSTANT 32 | # endif 33 | #endif 34 | 35 | #ifdef STATIC_MATH_NO_INTEGRAL_CONSTANT 36 | 37 | #include 38 | 39 | namespace smath 40 | { 41 | namespace detail 42 | { 43 | // Required even when smath::constant does not exist, 44 | // normal definition is in constant.inl 45 | template 46 | struct is_integral_constant: 47 | std::false_type 48 | {}; 49 | }} 50 | 51 | #else 52 | 53 | //////////////////////////////////////////////////////////// 54 | // Headers 55 | //////////////////////////////////////////////////////////// 56 | #include 57 | #include 58 | #include "detail/parse.h" 59 | 60 | namespace smath 61 | { 62 | template 63 | struct constant: 64 | std::integral_constant 65 | {}; 66 | 67 | template 68 | using bool_constant = constant; 69 | 70 | using true_type = bool_constant; 71 | using false_type = bool_constant; 72 | 73 | //////////////////////////////////////////////////////////// 74 | // Unary arithmetic operators 75 | 76 | template 77 | constexpr auto operator+(constant con) 78 | -> constant; 79 | 80 | template 81 | constexpr auto operator-(constant con) 82 | -> constant; 83 | 84 | //////////////////////////////////////////////////////////// 85 | // Binary arithmetic operators 86 | 87 | template 88 | constexpr auto operator+(constant lhs, constant rhs) 89 | -> constant; 90 | 91 | template 92 | constexpr auto operator-(constant lhs, constant rhs) 93 | -> constant; 94 | 95 | template 96 | constexpr auto operator*(constant lhs, constant rhs) 97 | -> constant; 98 | 99 | template 100 | constexpr auto operator/(constant lhs, constant rhs) 101 | -> constant; 102 | 103 | template 104 | constexpr auto operator%(constant lhs, constant rhs) 105 | -> constant; 106 | 107 | //////////////////////////////////////////////////////////// 108 | // Equality operators 109 | 110 | template 111 | constexpr auto operator==(constant lhs, constant rhs) 112 | -> constant; 113 | 114 | template 115 | constexpr auto operator!=(constant lhs, constant rhs) 116 | -> constant; 117 | 118 | //////////////////////////////////////////////////////////// 119 | // Relational operators 120 | 121 | template 122 | constexpr auto operator<(constant lhs, constant rhs) 123 | -> constant; 124 | 125 | template 126 | constexpr auto operator<=(constant lhs, constant rhs) 127 | -> constant; 128 | 129 | template 130 | constexpr auto operator>(constant lhs, constant rhs) 131 | -> constant M)>; 132 | 133 | template 134 | constexpr auto operator>=(constant lhs, constant rhs) 135 | -> constant= M)>; 136 | 137 | //////////////////////////////////////////////////////////// 138 | // Logical operators 139 | 140 | template 141 | constexpr auto operator&&(constant lhs, constant rhs) 142 | -> constant; 143 | 144 | template 145 | constexpr auto operator||(constant lhs, constant rhs) 146 | -> constant; 147 | 148 | template 149 | constexpr auto operator!(constant con) 150 | -> constant; 151 | 152 | //////////////////////////////////////////////////////////// 153 | // User-defined literals 154 | 155 | inline namespace literals 156 | { 157 | inline namespace constant_literals 158 | { 159 | template 160 | constexpr auto operator"" _c() 161 | -> constant< 162 | detail::parse_t, 163 | detail::parse::value 164 | >; 165 | 166 | template 167 | constexpr auto operator"" _cl() 168 | -> constant< 169 | detail::parse_t, 170 | detail::parse::value 171 | >; 172 | 173 | template 174 | constexpr auto operator"" _cll() 175 | -> constant< 176 | detail::parse_t, 177 | detail::parse::value 178 | >; 179 | 180 | template 181 | constexpr auto operator"" _cu() 182 | -> constant< 183 | detail::parse_t, 184 | detail::parse::value 185 | >; 186 | 187 | template 188 | constexpr auto operator"" _cul() 189 | -> constant< 190 | detail::parse_t, 191 | detail::parse::value 192 | >; 193 | 194 | template 195 | constexpr auto operator"" _cull() 196 | -> constant< 197 | detail::parse_t, 198 | detail::parse::value 199 | >; 200 | }} 201 | 202 | #include "detail/constant.inl" 203 | } 204 | 205 | namespace std 206 | { 207 | //////////////////////////////////////////////////////////// 208 | // Numeric limits 209 | 210 | template 211 | class numeric_limits>: 212 | public std::numeric_limits 213 | {}; 214 | } 215 | 216 | #endif // STATIC_MATH_NO_INTEGRAL_CONSTANT 217 | 218 | #endif // SMATH_CONSTANT_H_ 219 | -------------------------------------------------------------------------------- /docs/Rational-numbers.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | This header implements [rational numbers](https://en.wikipedia.org/wiki/Rational_number) through the `rational` class template. It supports basic rational-rational and rational-integer arithmetics and common rational functions. A rational instance has two public member data: `numer` and `denom`, corresponding to the numerator and the denominator; `numer` holds the sign information. A rational number is always automatically simplified after an operation has been performed. 6 | 7 | ```cpp 8 | template 9 | struct rational; 10 | ``` 11 | 12 | ### Construction functions 13 | 14 | ```cpp 15 | constexpr rational(value_type numerator); 16 | ``` 17 | 18 | Constructs a rational number with `numerator` and 1 as the denominator. 19 | 20 | ```cpp 21 | constexpr rational(value_type numerator, value_type denominator); 22 | ``` 23 | 24 | Constructs a rational number with `numerator` and `denominator` and 1 as the denominator. 25 | 26 | ### Conversion functions 27 | 28 | ```cpp 29 | constexpr explicit operator float() const; 30 | constexpr explicit operator double() const; 31 | constexpr explicit operator long double() const; 32 | ``` 33 | 34 | Converts the rational number to a floating point number `numerator / denominator`. 35 | 36 | ```cpp 37 | constexpr explicit operator bool() const; 38 | ``` 39 | 40 | Returns `false` when `numerator == 0` and `true` otherwise. 41 | 42 | ### Arithmetic operations 43 | 44 | ```cpp 45 | template 46 | constexpr auto operator+(rational lhs) 47 | -> rational; 48 | template 49 | constexpr auto operator-(rational lhs) 50 | -> rational; 51 | 52 | template 53 | constexpr auto operator+(rational lhs, rational rhs) 54 | -> rational>; 55 | template 56 | constexpr auto operator-(rational lhs, rational rhs) 57 | -> rational>; 58 | template 59 | constexpr auto operator*(rational lhs, rational rhs) 60 | -> rational>; 61 | template 62 | constexpr auto operator/(rational lhs, rational rhs) 63 | -> rational>; 64 | 65 | template 66 | constexpr auto operator+(rational lhs, Integer rhs) 67 | -> rational>; 68 | template 69 | constexpr auto operator-(rational lhs, Integer rhs) 70 | -> rational>; 71 | template 72 | constexpr auto operator*(rational lhs, Integer rhs) 73 | -> rational>; 74 | template 75 | constexpr auto operator/(rational lhs, Integer rhs) 76 | -> rational>; 77 | 78 | template 79 | constexpr auto operator+(Integer lhs, rational rhs) 80 | -> rational>; 81 | template 82 | constexpr auto operator-(Integer lhs, rational rhs) 83 | -> rational>; 84 | template 85 | constexpr auto operator*(Integer lhs, rational rhs) 86 | -> rational>; 87 | template 88 | constexpr auto operator/(Integer lhs, rational rhs) 89 | -> rational>; 90 | ``` 91 | 92 | ### Relational operations 93 | 94 | ```cpp 95 | template 96 | constexpr auto operator==(rational lhs, rational rhs) 97 | -> bool; 98 | template 99 | constexpr auto operator!=(rational lhs, rational rhs) 100 | -> bool; 101 | template 102 | constexpr auto operator<(rational lhs, rational rhs) 103 | -> bool; 104 | template 105 | constexpr auto operator>(rational lhs, rational rhs) 106 | -> bool; 107 | template 108 | constexpr auto operator<=(rational lhs, rational rhs) 109 | -> bool; 110 | template 111 | constexpr auto operator>=(rational lhs, rational rhs) 112 | -> bool; 113 | 114 | template 115 | constexpr auto operator==(rational lhs, Integer rhs) 116 | -> bool; 117 | template 118 | constexpr auto operator!=(rational lhs, Integer rhs) 119 | -> bool; 120 | template 121 | constexpr auto operator<(rational lhs, Integer rhs) 122 | -> bool; 123 | template 124 | constexpr auto operator>(rational lhs, Integer rhs) 125 | -> bool; 126 | template 127 | constexpr auto operator<=(rational lhs, Integer rhs) 128 | -> bool; 129 | template 130 | constexpr auto operator>=(rational lhs, Integer rhs) 131 | -> bool; 132 | 133 | template 134 | constexpr auto operator==(Integer lhs, rational rhs) 135 | -> bool; 136 | template 137 | constexpr auto operator!=(Integer lhs, rational rhs) 138 | -> bool; 139 | template 140 | constexpr auto operator<(Integer lhs, rational rhs) 141 | -> bool; 142 | template 143 | constexpr auto operator>(Integer lhs, rational rhs) 144 | -> bool; 145 | template 146 | constexpr auto operator<=(Integer lhs, rational rhs) 147 | -> bool; 148 | template 149 | constexpr auto operator>=(Integer lhs, rational rhs) 150 | -> bool; 151 | ``` 152 | 153 | ### Mathematical functions 154 | 155 | ```cpp 156 | template 157 | constexpr auto sign(rational ratio) 158 | -> int; 159 | ``` 160 | 161 | Computes the sign of `ratio`. 162 | 163 | ```cpp 164 | template 165 | constexpr auto abs(rational ratio) 166 | -> rational; 167 | ``` 168 | 169 | Computes the absolute value of `ratio`. 170 | 171 | ```cpp 172 | template 173 | constexpr auto floor(rational ratio) 174 | -> decltype(std::floor(T{})); 175 | ``` 176 | 177 | Computes the largest integer value not greater than `ratio`. 178 | 179 | ```cpp 180 | template 181 | constexpr auto ceil(rational ratio) 182 | -> decltype(std::ceil(T{})); 183 | ``` 184 | 185 | Computes the smallest integer value not greater than `ratio`. 186 | 187 | ```cpp 188 | template 189 | constexpr auto round(rational ratio) 190 | -> decltype(std::round(T{})); 191 | ``` 192 | 193 | Computes the nearest integer value to `ratio` (converted to floating-point format), rounding halfway cases away from zero, regardless of the current rounding mode. 194 | 195 | ```cpp 196 | template 197 | constexpr auto trunc(rational ratio) 198 | -> decltype(std::trunc(T{})); 199 | ``` 200 | 201 | Computes the nearest integer not greater in magnitude than `ratio`. 202 | 203 | ```cpp 204 | template 205 | constexpr auto reciprocal(rational ratio) 206 | -> rational; 207 | ``` 208 | 209 | Computes the [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) of `ratio`. 210 | 211 | ```cpp 212 | template 213 | constexpr auto pow(rational ratio, Integer exponent) 214 | -> rational; 215 | ``` 216 | 217 | Computes `ratio` to the power `exponent` where `exponent` is an integral type. 218 | 219 | ### User-defined literals 220 | 221 | `static_math` provides user-defined literals for the class template `rational` when templated over standard integral types. To make them as usable as possible, they are defined in the inline namespace `rational_literals` in the inline namespace `smath::literals`. 222 | 223 | ```cpp 224 | constexpr auto operator "" _r(unsigned long long n) 225 | -> rational; 226 | 227 | constexpr auto operator "" _rl(unsigned long long n) 228 | -> rational; 229 | 230 | constexpr auto operator "" _rll(unsigned long long n) 231 | -> rational; 232 | 233 | constexpr auto operator "" _ru(unsigned long long n) 234 | -> rational; 235 | 236 | constexpr auto operator "" _rul(unsigned long long n) 237 | -> rational; 238 | 239 | constexpr auto operator "" _rull(unsigned long long n) 240 | -> rational; 241 | ``` -------------------------------------------------------------------------------- /test/cmath.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2018 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | int main() 30 | { 31 | //////////////////////////////////////////////////////////// 32 | // Regular functions 33 | 34 | static_assert(smath::abs(-5) == 5, ""); 35 | static_assert(smath::abs(8) == 8, ""); 36 | static_assert(smath::abs(-82L) == 82, ""); 37 | 38 | static_assert(smath::div(9, 5).quot == 1 && smath::div(9, 5).rem == 4, ""); 39 | static_assert(smath::div(5, 9).quot == 0 && smath::div(5, 9).rem == 5, ""); 40 | static_assert(smath::div(9L, 5L).quot == 1L && smath::div(9L, 5L).rem == 4L, ""); 41 | 42 | // Check that it correctly converts to std::div and friends 43 | constexpr std::div_t d1 = smath::div(9, 2); 44 | constexpr std::ldiv_t d2 = smath::div(7L, 1L); 45 | constexpr std::lldiv_t d3 = smath::div(15LL, 5LL); 46 | static_assert(d1.quot == 4 && d1.rem == 1, ""); 47 | static_assert(d2.quot == 7L && d2.rem == 0L, ""); 48 | static_assert(d3.quot == 3LL && d3.rem == 0L, ""); 49 | 50 | static_assert(smath::min(1, 2) == 1, ""); 51 | static_assert(smath::min(0, 0) == 0, ""); 52 | static_assert(smath::min(-2, -1, 0, 1, 2) == -2, ""); 53 | static_assert(smath::min(2, 1, 0, -1, -2) == -2, ""); 54 | 55 | static_assert(smath::max(3, 8) == 8, ""); 56 | static_assert(smath::max(-8, -8) == -8, ""); 57 | static_assert(smath::max(8, -1, 6, 3, 5, 2, -8) == 8, ""); 58 | static_assert(smath::max(-1, 0, 1, 2, 3, 2, 1, 0, -1) == 3, ""); 59 | 60 | static_assert(smath::floor(2.5) == 2.0, ""); 61 | static_assert(smath::floor(2.01) == 2.0, ""); 62 | static_assert(smath::floor(2.8) == 2.0, ""); 63 | static_assert(smath::floor(-2.5) == -3.0, ""); 64 | 65 | static_assert(smath::ceil(0) == 0.0, ""); 66 | static_assert(smath::ceil(2.5) == 3.0, ""); 67 | static_assert(smath::ceil(2.01) == 3.0, ""); 68 | static_assert(smath::ceil(2.8) == 3.0, ""); 69 | static_assert(smath::ceil(-2.5) == -2.0, ""); 70 | 71 | static_assert(smath::round(2.5) == 3.0, ""); 72 | static_assert(smath::round(2.01) == 2.0, ""); 73 | static_assert(smath::round(2.8) == 3.0, ""); 74 | static_assert(smath::round(-2.1) == -2.0, ""); 75 | 76 | static_assert(smath::lround(6000000000.5)== 6000000001, ""); 77 | static_assert(smath::lround(2.5) == 3.0, ""); 78 | static_assert(smath::lround(2.01) == 2.0, ""); 79 | static_assert(smath::lround(2.8) == 3.0, ""); 80 | static_assert(smath::lround(-2.1) == -2.0, ""); 81 | static_assert(smath::lround(-6000000000.5) == -6000000001, ""); 82 | 83 | static_assert(smath::llround(6000000000.5)== 6000000001, ""); 84 | static_assert(smath::llround(2.5) == 3.0, ""); 85 | static_assert(smath::llround(2.01) == 2.0, ""); 86 | static_assert(smath::llround(2.8) == 3.0, ""); 87 | static_assert(smath::llround(-2.1) == -2.0, ""); 88 | static_assert(smath::llround(-6000000000.5) == -6000000001, ""); 89 | 90 | static_assert(smath::trunc(2.5) == 2.0, ""); 91 | static_assert(smath::trunc(2.01) == 2.0, ""); 92 | static_assert(smath::trunc(2.8) == 2.0, ""); 93 | static_assert(smath::trunc(-2.1) == -2.0, ""); 94 | 95 | static_assert(smath::is_close(smath::exp(0.0), 1.0), ""); 96 | static_assert(smath::is_close(smath::exp(1.0), smath::constants::e<>), ""); 97 | 98 | static_assert(smath::pow(2, -1) == 0, ""); 99 | static_assert(smath::pow(2, 0) == 1, ""); 100 | static_assert(smath::pow(2, 1) == 2, ""); 101 | static_assert(smath::pow(2, 2) == 4, ""); 102 | 103 | static_assert(smath::pow(5.8, 0) == 1.0, ""); 104 | static_assert(smath::is_close(smath::pow(5.8, 2), 33.64), ""); 105 | static_assert(smath::is_close(smath::pow(2.0, -1), 0.5), ""); 106 | static_assert(smath::is_close(smath::pow(2.0, -2), 0.25), ""); 107 | 108 | static_assert(smath::is_close(smath::sqrt(4.0), 2.0), ""); 109 | static_assert(smath::is_close(smath::sqrt(2.0), 1.414213562373095), ""); 110 | static_assert(smath::is_close(smath::sqrt(3.0), 1.732050807568877), ""); 111 | 112 | // From GitHub issue #25 113 | static_assert(smath::is_close(smath::sqrt(4.916330874e-01f), 0.701165520686806f), ""); 114 | static_assert(smath::is_close(smath::sqrt(3.804553151e-01f), 0.616810599049660f), ""); 115 | static_assert(smath::is_close(smath::sqrt(4.505589902e-01f), 0.671236910635880f), ""); 116 | static_assert(smath::is_close(smath::sqrt(3.162864149e-01f), 0.562393469823397f), ""); 117 | static_assert(smath::is_close(smath::sqrt(4.889709353e-01f), 0.699264567456410f), ""); 118 | 119 | static_assert(smath::is_close(smath::hypot(3.0f, 4), 5.0), ""); 120 | 121 | static_assert(smath::is_close(smath::exp(-2.0), 0.1353352832366127), ""); 122 | static_assert(smath::is_close(smath::exp(-1.0), 0.36787944117144233), ""); 123 | static_assert(smath::is_close(smath::exp(0.0), 1.0), ""); 124 | static_assert(smath::is_close(smath::exp(1.0), 2.718281828459045), ""); 125 | static_assert(smath::is_close(smath::exp(2.0), 7.38905609893065), ""); 126 | static_assert(smath::is_close(smath::exp(5.0), 148.4131591025766), ""); 127 | 128 | static_assert(smath::log2(256) == 8, ""); 129 | static_assert(smath::log10(100) == 2, ""); 130 | static_assert(smath::is_close(smath::log(1.0), 0.0), ""); 131 | static_assert(smath::is_close(smath::log(2.0), 0.693147180559945286226763982995180413126945496), ""); 132 | static_assert(smath::is_close(smath::log(0.5), -0.693147180559945286226763982995180413126945496), ""); 133 | static_assert(smath::is_close(smath::log(0.1), -2.302585084356761679913461193791590631008148193), ""); 134 | static_assert(smath::is_close(smath::log(256.0), 5.545177444479563177992531564086675643920898438), ""); 135 | 136 | //////////////////////////////////////////////////////////// 137 | // smath::constant overloads 138 | 139 | #ifndef STATIC_MATH_NO_INTEGRAL_CONSTANT 140 | using namespace smath::constant_literals; 141 | 142 | static_assert(smath::abs(-5_c) == 5_c, ""); 143 | static_assert(smath::abs(8_c) == 8_c, ""); 144 | static_assert(smath::abs(-82_cl) == 82_cl, ""); 145 | 146 | static_assert( 147 | std::is_same< 148 | decltype(smath::abs(-5_c)), 149 | smath::constant 150 | >::value, ""); 151 | 152 | static_assert( 153 | smath::min(1_c, 2_c) == 1_c, ""); 154 | static_assert( 155 | smath::min(0_c, 0_c) == 0_c, ""); 156 | static_assert( 157 | smath::min(-2_c, -1_c, 0_c, 1_c, 2_c) == -2_c, ""); 158 | static_assert( 159 | smath::min(2_c, 1_c, 0_c, -1_c, -2_c) == -2_c, ""); 160 | 161 | static_assert( 162 | smath::max(3_c, 8_c) == 8_c, ""); 163 | static_assert( 164 | smath::max(-8_c, -8_c) == -8_c, ""); 165 | static_assert( 166 | smath::max(8_c, -1_c, 6_c, 3_c, 5_c, 2_c, -8_c) == 8_c, ""); 167 | static_assert( 168 | smath::max(-1_c, 0_c, 1_c, 2_c, 3_c, 2_c, 1_c, 0_c, -1_c) == 3_c, ""); 169 | 170 | static_assert(smath::pow(2_c, 0_c) == 1_c, ""); 171 | static_assert(smath::pow(2_c, 1_c) == 2_c, ""); 172 | static_assert(smath::pow(5_c, 1_c) == 5_c, ""); 173 | static_assert(smath::pow(5_c, 0_c) == 1_c, ""); 174 | static_assert(smath::pow(2_c, 1_c) == 2_c, ""); 175 | static_assert(smath::pow(2_c, 2_c) == 4_c, ""); 176 | 177 | static_assert( 178 | std::is_same< 179 | decltype(smath::pow(5_c, 2_c)), 180 | smath::constant 181 | >::value, ""); 182 | #endif 183 | } 184 | -------------------------------------------------------------------------------- /include/static_math/rational.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_RATIONAL_H_ 25 | #define SMATH_RATIONAL_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace smath 36 | { 37 | /** 38 | * @brief Rational numbers 39 | */ 40 | template 41 | struct rational 42 | { 43 | static_assert(std::is_integral::value, 44 | "a rational can only contain integral values"); 45 | 46 | //////////////////////////////////////////////////////////// 47 | // Types 48 | 49 | using value_type = T; 50 | 51 | //////////////////////////////////////////////////////////// 52 | // Constructors 53 | 54 | constexpr rational(value_type numerator); 55 | constexpr rational(value_type numerator, value_type denominator); 56 | 57 | //////////////////////////////////////////////////////////// 58 | // Cast 59 | 60 | constexpr explicit operator float() const; 61 | constexpr explicit operator double() const; 62 | constexpr explicit operator long double() const; 63 | 64 | constexpr explicit operator bool() const; 65 | 66 | //////////////////////////////////////////////////////////// 67 | // Member data 68 | 69 | const value_type numer; 70 | const value_type denom; 71 | }; 72 | 73 | //////////////////////////////////////////////////////////// 74 | // Unary arithmetic operators 75 | 76 | template 77 | constexpr auto operator+(rational lhs) 78 | -> rational; 79 | template 80 | constexpr auto operator-(rational lhs) 81 | -> rational; 82 | 83 | //////////////////////////////////////////////////////////// 84 | // Binary arithmetic operators 85 | 86 | template 87 | constexpr auto operator+(rational lhs, rational rhs) 88 | -> rational>; 89 | template 90 | constexpr auto operator-(rational lhs, rational rhs) 91 | -> rational>; 92 | template 93 | constexpr auto operator*(rational lhs, rational rhs) 94 | -> rational>; 95 | template 96 | constexpr auto operator/(rational lhs, rational rhs) 97 | -> rational>; 98 | 99 | template 100 | constexpr auto operator+(rational lhs, Integer rhs) 101 | -> rational>; 102 | template 103 | constexpr auto operator-(rational lhs, Integer rhs) 104 | -> rational>; 105 | template 106 | constexpr auto operator*(rational lhs, Integer rhs) 107 | -> rational>; 108 | template 109 | constexpr auto operator/(rational lhs, Integer rhs) 110 | -> rational>; 111 | 112 | template 113 | constexpr auto operator+(Integer lhs, rational rhs) 114 | -> rational>; 115 | template 116 | constexpr auto operator-(Integer lhs, rational rhs) 117 | -> rational>; 118 | template 119 | constexpr auto operator*(Integer lhs, rational rhs) 120 | -> rational>; 121 | template 122 | constexpr auto operator/(Integer lhs, rational rhs) 123 | -> rational>; 124 | 125 | //////////////////////////////////////////////////////////// 126 | // Relational operators 127 | 128 | template 129 | constexpr auto operator==(rational lhs, rational rhs) 130 | -> bool; 131 | template 132 | constexpr auto operator!=(rational lhs, rational rhs) 133 | -> bool; 134 | template 135 | constexpr auto operator<(rational lhs, rational rhs) 136 | -> bool; 137 | template 138 | constexpr auto operator>(rational lhs, rational rhs) 139 | -> bool; 140 | template 141 | constexpr auto operator<=(rational lhs, rational rhs) 142 | -> bool; 143 | template 144 | constexpr auto operator>=(rational lhs, rational rhs) 145 | -> bool; 146 | 147 | template 148 | constexpr auto operator==(rational lhs, Integer rhs) 149 | -> bool; 150 | template 151 | constexpr auto operator!=(rational lhs, Integer rhs) 152 | -> bool; 153 | template 154 | constexpr auto operator<(rational lhs, Integer rhs) 155 | -> bool; 156 | template 157 | constexpr auto operator>(rational lhs, Integer rhs) 158 | -> bool; 159 | template 160 | constexpr auto operator<=(rational lhs, Integer rhs) 161 | -> bool; 162 | template 163 | constexpr auto operator>=(rational lhs, Integer rhs) 164 | -> bool; 165 | 166 | template 167 | constexpr auto operator==(Integer lhs, rational rhs) 168 | -> bool; 169 | template 170 | constexpr auto operator!=(Integer lhs, rational rhs) 171 | -> bool; 172 | template 173 | constexpr auto operator<(Integer lhs, rational rhs) 174 | -> bool; 175 | template 176 | constexpr auto operator>(Integer lhs, rational rhs) 177 | -> bool; 178 | template 179 | constexpr auto operator<=(Integer lhs, rational rhs) 180 | -> bool; 181 | template 182 | constexpr auto operator>=(Integer lhs, rational rhs) 183 | -> bool; 184 | 185 | //////////////////////////////////////////////////////////// 186 | // Mathematical functions 187 | 188 | template 189 | constexpr auto sign(rational ratio) 190 | -> int; 191 | 192 | template 193 | constexpr auto abs(rational ratio) 194 | -> rational; 195 | 196 | template 197 | constexpr auto floor(rational ratio) 198 | -> decltype(std::floor(T{})); 199 | 200 | template 201 | constexpr auto ceil(rational ratio) 202 | -> decltype(std::ceil(T{})); 203 | 204 | template 205 | constexpr auto round(rational ratio) 206 | -> decltype(std::round(T{})); 207 | 208 | template 209 | constexpr auto trunc(rational ratio) 210 | -> decltype(std::trunc(T{})); 211 | 212 | template 213 | constexpr auto reciprocal(rational ratio) 214 | -> rational; 215 | 216 | template 217 | constexpr auto pow(rational ratio, Integer exp) 218 | -> rational; 219 | 220 | inline namespace literals 221 | { 222 | inline namespace rational_literals 223 | { 224 | //////////////////////////////////////////////////////////// 225 | // User-defined literals 226 | 227 | constexpr auto operator "" _r(unsigned long long n) 228 | -> rational; 229 | 230 | constexpr auto operator "" _rl(unsigned long long n) 231 | -> rational; 232 | 233 | constexpr auto operator "" _rll(unsigned long long n) 234 | -> rational; 235 | 236 | constexpr auto operator "" _ru(unsigned long long n) 237 | -> rational; 238 | 239 | constexpr auto operator "" _rul(unsigned long long n) 240 | -> rational; 241 | 242 | constexpr auto operator "" _rull(unsigned long long n) 243 | -> rational; 244 | }} 245 | 246 | #include "detail/rational.inl" 247 | } 248 | 249 | #endif // SMATH_RATIONAL_H_ 250 | -------------------------------------------------------------------------------- /docs/Complex-numbers.md: -------------------------------------------------------------------------------- 1 | ```cpp 2 | #include 3 | ``` 4 | 5 | This header implements [complex numbers](https://en.wikipedia.org/wiki/Complex_number) through the class templates `complex` and `imaginary`. `imaginary` is a mere wrapper around a value of another arithmetic type (public member data `value`) while `complex` is a simple structure wrapping a value of an arithmetic type and a value of the equivalent `imaginary` type (public member data `real` and `imag` to match the standard library names). It should offer a bit stronger typing than `std::complex`. 6 | 7 | ```cpp 8 | template 9 | struct imaginary 10 | { 11 | using value_type = T; 12 | 13 | // Constructors 14 | constexpr imaginary() = default; 15 | constexpr imaginary(const imaginary& other) = default; 16 | 17 | constexpr explicit imaginary(value_type real); 18 | template 19 | constexpr explicit imaginary(imaginary other); 20 | 21 | // Operators 22 | template 23 | constexpr auto operator+=(imaginary other) 24 | -> imaginary&; 25 | template 26 | constexpr auto operator-=(imaginary other) 27 | -> imaginary&; 28 | constexpr auto operator*=(T real) 29 | -> imaginary&; 30 | constexpr auto operator/=(T real) 31 | -> imaginary&; 32 | 33 | // Member data 34 | value_type value = T{}; 35 | }; 36 | 37 | 38 | template 39 | struct complex 40 | { 41 | using value_type = T; 42 | 43 | // Constructors 44 | constexpr complex() = default; 45 | constexpr complex(const complex& other) = default; 46 | constexpr complex(value_type real, value_type imag); 47 | constexpr complex(value_type real, imaginary imag); 48 | constexpr complex(value_type real); 49 | constexpr complex(imaginary imag); 50 | template 51 | constexpr explicit complex(complex other); 52 | 53 | // Augmented assignment operators 54 | constexpr auto operator+=(T other) 55 | -> complex&; 56 | constexpr auto operator-=(T other) 57 | -> complex&; 58 | constexpr auto operator*=(T other) 59 | -> complex&; 60 | constexpr auto operator/=(T other) 61 | -> complex&; 62 | 63 | constexpr auto operator+=(imaginary other) 64 | -> complex&; 65 | constexpr auto operator-=(imaginary other) 66 | -> complex&; 67 | constexpr auto operator*=(imaginary other) 68 | -> complex&; 69 | constexpr auto operator/=(imaginary other) 70 | -> complex&; 71 | 72 | template 73 | constexpr auto operator+=(complex other) 74 | -> complex&; 75 | template 76 | constexpr auto operator-=(complex other) 77 | -> complex&; 78 | template 79 | constexpr auto operator*=(complex other) 80 | -> complex&; 81 | template 82 | constexpr auto operator/=(complex other) 83 | -> complex&; 84 | 85 | // Member data 86 | value_type real = T{}; 87 | imaginary imag = imaginary{}; 88 | }; 89 | 90 | ``` 91 | 92 | ### Arithmetic operators 93 | 94 | ```cpp 95 | template 96 | constexpr auto operator+(imaginary imag) 97 | -> imaginary; 98 | template 99 | constexpr auto operator-(imaginary imag) 100 | -> imaginary; 101 | 102 | template 103 | constexpr auto operator+(complex ratio) 104 | -> complex; 105 | template 106 | constexpr auto operator-(complex ratio) 107 | -> complex; 108 | 109 | template 110 | constexpr auto operator+(imaginary lhs, imaginary rhs) 111 | -> imaginary>; 112 | template 113 | constexpr auto operator-(imaginary lhs, imaginary rhs) 114 | -> imaginary>; 115 | template 116 | constexpr auto operator*(imaginary lhs, imaginary rhs) 117 | -> std::common_type_t; 118 | template 119 | constexpr auto operator/(imaginary lhs, imaginary rhs) 120 | -> std::common_type_t; 121 | 122 | template 123 | constexpr auto operator+(imaginary lhs, Number rhs) 124 | -> complex>; 125 | template 126 | constexpr auto operator-(imaginary lhs, Number rhs) 127 | -> complex>; 128 | template 129 | constexpr auto operator*(imaginary lhs, Number rhs) 130 | -> imaginary>; 131 | template 132 | constexpr auto operator/(imaginary lhs, Number rhs) 133 | -> imaginary>; 134 | 135 | template 136 | constexpr auto operator+(Number lhs, imaginary rhs) 137 | -> complex>; 138 | template 139 | constexpr auto operator-(Number lhs, imaginary rhs) 140 | -> complex>; 141 | template 142 | constexpr auto operator*(Number lhs, imaginary rhs) 143 | -> imaginary>; 144 | template 145 | constexpr auto operator/(Number lhs, imaginary rhs) 146 | -> imaginary>; 147 | 148 | template 149 | constexpr auto operator+(complex lhs, complex rhs) 150 | -> complex>; 151 | template 152 | constexpr auto operator-(complex lhs, complex rhs) 153 | -> complex>; 154 | template 155 | constexpr auto operator*(complex lhs, complex rhs) 156 | -> complex>; 157 | template 158 | constexpr auto operator/(complex lhs, complex rhs) 159 | -> complex>; 160 | 161 | template 162 | constexpr auto operator+(complex lhs, Number rhs) 163 | -> complex>; 164 | template 165 | constexpr auto operator-(complex lhs, Number rhs) 166 | -> complex>; 167 | template 168 | constexpr auto operator*(complex lhs, Number rhs) 169 | -> complex>; 170 | template 171 | constexpr auto operator/(complex lhs, Number rhs) 172 | -> complex>; 173 | 174 | template 175 | constexpr auto operator+(Number lhs, complex rhs) 176 | -> complex>; 177 | template 178 | constexpr auto operator-(Number lhs, complex rhs) 179 | -> complex>; 180 | template 181 | constexpr auto operator*(Number lhs, complex rhs) 182 | -> complex>; 183 | template 184 | constexpr auto operator/(Number lhs, complex rhs) 185 | -> complex>; 186 | 187 | template 188 | constexpr auto operator+(complex lhs, imaginary rhs) 189 | -> complex>; 190 | template 191 | constexpr auto operator-(complex lhs, imaginary rhs) 192 | -> complex>; 193 | template 194 | constexpr auto operator*(complex lhs, imaginary rhs) 195 | -> complex>; 196 | template 197 | constexpr auto operator/(complex lhs, imaginary rhs) 198 | -> complex>; 199 | 200 | template 201 | constexpr auto operator+(imaginary lhs, complex rhs) 202 | -> complex>; 203 | template 204 | constexpr auto operator-(imaginary lhs, complex rhs) 205 | -> complex>; 206 | template 207 | constexpr auto operator*(imaginary lhs, complex rhs) 208 | -> complex>; 209 | template 210 | constexpr auto operator/(imaginary lhs, complex rhs) 211 | -> complex>; 212 | ``` 213 | 214 | ### Comparison operators 215 | 216 | ```cpp 217 | template 218 | constexpr auto operator==(imaginary lhs, imaginary rhs) 219 | -> bool; 220 | template 221 | constexpr auto operator!=(imaginary lhs, imaginary rhs) 222 | -> bool; 223 | 224 | template 225 | constexpr auto operator==(complex lhs, complex rhs) 226 | -> bool; 227 | template 228 | constexpr auto operator!=(complex lhs, complex rhs) 229 | -> bool; 230 | 231 | template 232 | constexpr auto operator==(complex lhs, Number rhs) 233 | -> bool; 234 | template 235 | constexpr auto operator!=(complex lhs, Number rhs) 236 | -> bool; 237 | 238 | template 239 | constexpr auto operator==(Number lhs, complex rhs) 240 | -> bool; 241 | template 242 | constexpr auto operator!=(Number lhs, complex rhs) 243 | -> bool; 244 | 245 | template 246 | constexpr auto operator==(complex lhs, imaginary rhs) 247 | -> bool; 248 | template 249 | constexpr auto operator!=(complex lhs, imaginary rhs) 250 | -> bool; 251 | 252 | template 253 | constexpr auto operator==(imaginary lhs, complex rhs) 254 | -> bool; 255 | template 256 | constexpr auto operator!=(imaginary lhs, complex rhs) 257 | -> bool; 258 | ``` 259 | 260 | ### Mathematical functions 261 | 262 | ```cpp 263 | template 264 | constexpr auto abs(complex z) 265 | -> T; 266 | ``` 267 | 268 | Computes the magnitude of a complex number `z`. 269 | 270 | 271 | ```cpp 272 | template 273 | constexpr auto norm(complex z) 274 | -> T; 275 | 276 | template 277 | constexpr auto norm(T value) 278 | -> T; 279 | ``` 280 | 281 | Computes the squared magnitude of a complex number `z`. If a built-in arithmetic type or an imaginary type is passed, it is converted to a `complex` prior to the operation. 282 | 283 | ```cpp 284 | template 285 | constexpr auto conj(complex z) 286 | -> complex; 287 | 288 | template 289 | constexpr auto conj(T value) 290 | -> complex; 291 | ``` 292 | 293 | Computes the [complex conjugate](https://en.wikipedia.org/wiki/Complex_conjugate) of `z` by reversing the sign of the imaginary part. If a built-in arithmetic type or an imaginary type is passed, it is converted to a `complex` prior to the operation. 294 | 295 | ``` 296 | template 297 | constexpr auto polar(T rho, T theta) 298 | -> complex; 299 | ``` 300 | 301 | Returns a complex number with a magnitude `rho` and a phase angle `theta`. 302 | 303 | ### User-defined literals 304 | 305 | `static_math` provides user-defined literals for the types `imaginary` and `complex` when they are templated over standard integral or floating point types. To make them as usable as possible, they are defined in the inline namespace `complex_literals` in the inline namespace `smath::literals`. 306 | 307 | ```cpp 308 | constexpr auto operator"" _if(long double n) 309 | -> imaginary; 310 | 311 | constexpr auto operator"" _i(long double n) 312 | -> imaginary; 313 | 314 | constexpr auto operator"" _il(long double n) 315 | -> imaginary; 316 | 317 | constexpr auto operator"" _i(unsigned long long n) 318 | -> imaginary; 319 | 320 | constexpr auto operator"" _il(unsigned long long n) 321 | -> imaginary; 322 | 323 | constexpr auto operator"" _ill(unsigned long long n) 324 | -> imaginary; 325 | 326 | constexpr auto operator"" _ui(unsigned long long n) 327 | -> imaginary; 328 | 329 | constexpr auto operator"" _uil(unsigned long long n) 330 | -> imaginary; 331 | 332 | constexpr auto operator"" _uill(unsigned long long n) 333 | -> imaginary; 334 | ``` -------------------------------------------------------------------------------- /include/static_math/detail/rational.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2015 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | //////////////////////////////////////////////////////////// 26 | // Construction 27 | 28 | template 29 | constexpr rational::rational(value_type numerator): 30 | numer(numerator), 31 | denom(1) 32 | {} 33 | 34 | template 35 | constexpr rational::rational(value_type numerator, value_type denominator): 36 | numer( 37 | numerator != 0 ? 38 | numerator * sign(denominator) 39 | / gcd(abs(numerator), abs(denominator)) 40 | : 0 41 | ), 42 | denom( 43 | numerator != 0 ? 44 | abs(denominator) 45 | / gcd(abs(numerator), abs(denominator)) 46 | : 1 47 | ) 48 | {} 49 | 50 | //////////////////////////////////////////////////////////// 51 | // Casts 52 | 53 | template 54 | constexpr rational::operator float() const 55 | { 56 | return static_cast(numer) / 57 | static_cast(denom); 58 | } 59 | 60 | template 61 | constexpr rational::operator double() const 62 | { 63 | return static_cast(numer) / 64 | static_cast(denom); 65 | } 66 | 67 | template 68 | constexpr rational::operator long double() const 69 | { 70 | return static_cast(numer) / 71 | static_cast(denom); 72 | } 73 | 74 | template 75 | constexpr rational::operator bool() const 76 | { 77 | return numer == 0; 78 | } 79 | 80 | //////////////////////////////////////////////////////////// 81 | // Unary arithmetic operators 82 | 83 | template 84 | constexpr auto operator+(rational lhs) 85 | -> rational 86 | { 87 | return lhs; 88 | } 89 | 90 | template 91 | constexpr auto operator-(rational lhs) 92 | -> rational 93 | { 94 | return { 95 | -lhs.numer, 96 | lhs.denom 97 | }; 98 | } 99 | 100 | //////////////////////////////////////////////////////////// 101 | // Binary arithmetic operators 102 | 103 | template 104 | constexpr auto operator+(rational lhs, rational rhs) 105 | -> rational> 106 | { 107 | return { 108 | lhs.numer * rhs.denom + rhs.numer * lhs.denom, 109 | lhs.denom * rhs.denom 110 | }; 111 | } 112 | 113 | template 114 | constexpr auto operator-(rational lhs, rational rhs) 115 | -> rational> 116 | { 117 | return { 118 | lhs.numer * rhs.denom - rhs.numer * lhs.denom, 119 | lhs.denom * rhs.denom 120 | }; 121 | } 122 | 123 | template 124 | constexpr auto operator*(rational lhs, rational rhs) 125 | -> rational> 126 | { 127 | return { 128 | lhs.numer * rhs.numer, 129 | lhs.denom * rhs.denom 130 | }; 131 | } 132 | 133 | template 134 | constexpr auto operator/(rational lhs, rational rhs) 135 | -> rational> 136 | { 137 | return { 138 | lhs.numer * rhs.denom, 139 | lhs.denom * rhs.numer 140 | }; 141 | } 142 | 143 | template 144 | constexpr auto operator+(rational lhs, Integer rhs) 145 | -> rational> 146 | { 147 | return { 148 | lhs.numer + rhs * lhs.denom, 149 | lhs.denom 150 | }; 151 | } 152 | 153 | template 154 | constexpr auto operator-(rational lhs, Integer rhs) 155 | -> rational> 156 | { 157 | return { 158 | lhs.numer - rhs * lhs.denom, 159 | lhs.denom 160 | }; 161 | } 162 | 163 | template 164 | constexpr auto operator*(rational lhs, Integer rhs) 165 | -> rational> 166 | { 167 | return { 168 | lhs.numer * rhs, 169 | lhs.denom 170 | }; 171 | } 172 | 173 | template 174 | constexpr auto operator/(rational lhs, Integer rhs) 175 | -> rational> 176 | { 177 | return { 178 | lhs.numer, 179 | lhs.denom * rhs 180 | }; 181 | } 182 | 183 | template 184 | constexpr auto operator+(Integer lhs, rational rhs) 185 | -> rational> 186 | { 187 | return { 188 | lhs * rhs.denom + rhs.numer, 189 | rhs.denom 190 | }; 191 | } 192 | 193 | template 194 | constexpr auto operator-(Integer lhs, rational rhs) 195 | -> rational> 196 | { 197 | return { 198 | lhs * rhs.denom - rhs.numer, 199 | rhs.denom 200 | }; 201 | } 202 | 203 | template 204 | constexpr auto operator*(Integer lhs, rational rhs) 205 | -> rational> 206 | { 207 | return { 208 | lhs * rhs.numer, 209 | rhs.denom 210 | }; 211 | } 212 | 213 | template 214 | constexpr auto operator/(Integer lhs, rational rhs) 215 | -> rational> 216 | { 217 | return { 218 | lhs * rhs.denom, 219 | rhs.numer 220 | }; 221 | } 222 | 223 | //////////////////////////////////////////////////////////// 224 | // Relational operators 225 | 226 | template 227 | constexpr auto operator==(rational lhs, rational rhs) 228 | -> bool 229 | { 230 | return lhs.numer == rhs.numer 231 | && lhs.denom == rhs.denom; 232 | } 233 | 234 | template 235 | constexpr auto operator!=(rational lhs, rational rhs) 236 | -> bool 237 | { 238 | return !(lhs == rhs); 239 | } 240 | 241 | template 242 | constexpr auto operator<(rational lhs, rational rhs) 243 | -> bool 244 | { 245 | return lhs.numer * rhs.denom < lhs.denom * rhs.numer; 246 | } 247 | 248 | template 249 | constexpr auto operator>(rational lhs, rational rhs) 250 | -> bool 251 | { 252 | return lhs.numer * rhs.denom > lhs.denom * rhs.numer; 253 | } 254 | 255 | template 256 | constexpr auto operator<=(rational lhs, rational rhs) 257 | -> bool 258 | { 259 | return lhs.numer * rhs.denom <= lhs.denom * rhs.numer; 260 | } 261 | 262 | template 263 | constexpr auto operator>=(rational lhs, rational rhs) 264 | -> bool 265 | { 266 | return lhs.numer * rhs.denom >= lhs.denom * rhs.numer; 267 | } 268 | 269 | template 270 | constexpr auto operator==(rational lhs, Integer rhs) 271 | -> bool 272 | { 273 | return rhs * lhs.denom == lhs.numer; 274 | } 275 | 276 | template 277 | constexpr auto operator!=(rational lhs, Integer rhs) 278 | -> bool 279 | { 280 | return !(lhs == rhs); 281 | } 282 | 283 | template 284 | constexpr auto operator<(rational lhs, Integer rhs) 285 | -> bool 286 | { 287 | return lhs.numer < lhs.denom * rhs; 288 | } 289 | 290 | template 291 | constexpr auto operator>(rational lhs, Integer rhs) 292 | -> bool 293 | { 294 | return lhs.numer > lhs.denom * rhs; 295 | } 296 | 297 | template 298 | constexpr auto operator<=(rational lhs, Integer rhs) 299 | -> bool 300 | { 301 | return lhs.numer <= lhs.denom * rhs; 302 | } 303 | 304 | template 305 | constexpr auto operator>=(rational lhs, Integer rhs) 306 | -> bool 307 | { 308 | return lhs.numer >= lhs.denom * rhs; 309 | } 310 | 311 | template 312 | constexpr auto operator==(Integer lhs, rational rhs) 313 | -> bool 314 | { 315 | return lhs * rhs.denom == rhs.numer; 316 | } 317 | 318 | template 319 | constexpr auto operator!=(Integer lhs, rational rhs) 320 | -> bool 321 | { 322 | return !(rhs == lhs); 323 | } 324 | 325 | template 326 | constexpr auto operator<(Integer lhs, rational rhs) 327 | -> bool 328 | { 329 | return lhs * rhs.denom < rhs.numer; 330 | } 331 | 332 | template 333 | constexpr auto operator>(Integer lhs, rational rhs) 334 | -> bool 335 | { 336 | return lhs * rhs.denom > rhs.numer; 337 | } 338 | 339 | template 340 | constexpr auto operator<=(Integer lhs, rational rhs) 341 | -> bool 342 | { 343 | return lhs * rhs.denom <= rhs.numer; 344 | } 345 | 346 | template 347 | constexpr auto operator>=(Integer lhs, rational rhs) 348 | -> bool 349 | { 350 | return lhs * rhs.denom >= rhs.numer; 351 | } 352 | 353 | //////////////////////////////////////////////////////////// 354 | // Mathematical functions 355 | 356 | template 357 | constexpr auto sign(rational ratio) 358 | -> int 359 | { 360 | return (ratio.numer > 0) ? 1 : (ratio.numer < 0) ? -1 : 0; 361 | } 362 | 363 | template 364 | constexpr auto abs(rational ratio) 365 | -> rational 366 | { 367 | return (ratio >= 0) ? ratio : -ratio; 368 | } 369 | 370 | template 371 | constexpr auto floor(rational ratio) 372 | -> decltype(std::floor(T{})) 373 | { 374 | return smath::floor((long double) ratio); 375 | } 376 | 377 | template 378 | constexpr auto ceil(rational ratio) 379 | -> decltype(std::ceil(T{})) 380 | { 381 | return smath::ceil((long double) ratio); 382 | } 383 | 384 | template 385 | constexpr auto round(rational ratio) 386 | -> decltype(std::round(T{})) 387 | { 388 | return smath::round((long double) ratio); 389 | } 390 | 391 | template 392 | constexpr auto trunc(rational ratio) 393 | -> decltype(std::trunc(T{})) 394 | { 395 | return T((long double) ratio); 396 | } 397 | 398 | template 399 | constexpr auto reciprocal(rational ratio) 400 | -> rational 401 | { 402 | return { ratio.denom, ratio.numer }; 403 | } 404 | 405 | template 406 | constexpr auto pow(rational ratio, Integer exp) 407 | -> rational 408 | { 409 | static_assert(std::is_integral::value, 410 | "pow only accepts integer exponents"); 411 | 412 | return (exp == 0) ? rational(1) : 413 | (exp > 0) ? rational( 414 | pow(ratio.numer, exp), 415 | pow(ratio.denom, exp) 416 | ) : 417 | rational( 418 | pow(ratio.denom, -exp), 419 | pow(ratio.numer, -exp) 420 | ); 421 | } 422 | 423 | inline namespace literals 424 | { 425 | inline namespace rational_literals 426 | { 427 | //////////////////////////////////////////////////////////// 428 | // User-defined literals 429 | 430 | constexpr auto operator "" _r(unsigned long long n) 431 | -> rational 432 | { 433 | return { static_cast(n) }; 434 | } 435 | 436 | constexpr auto operator "" _rl(unsigned long long n) 437 | -> rational 438 | { 439 | return { static_cast(n) }; 440 | } 441 | 442 | constexpr auto operator "" _rll(unsigned long long n) 443 | -> rational 444 | { 445 | return { static_cast(n) }; 446 | } 447 | 448 | constexpr auto operator "" _ru(unsigned long long n) 449 | -> rational 450 | { 451 | return { static_cast(n) }; 452 | } 453 | 454 | constexpr auto operator "" _rul(unsigned long long n) 455 | -> rational 456 | { 457 | return { static_cast(n) }; 458 | } 459 | 460 | constexpr auto operator "" _rull(unsigned long long n) 461 | -> rational 462 | { 463 | return { n }; 464 | } 465 | }} 466 | -------------------------------------------------------------------------------- /include/static_math/complex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2013-2016 Morwenn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef SMATH_COMPLEX_H_ 25 | #define SMATH_COMPLEX_H_ 26 | 27 | //////////////////////////////////////////////////////////// 28 | // Headers 29 | //////////////////////////////////////////////////////////// 30 | #include 31 | #include 32 | #include 33 | 34 | namespace smath 35 | { 36 | /** 37 | * @brief Imaginary numbers 38 | */ 39 | template 40 | struct imaginary 41 | { 42 | static_assert(std::is_arithmetic::value, 43 | "an imaginary number can only contain arithmetic values"); 44 | 45 | using value_type = T; 46 | 47 | // Constructor 48 | constexpr imaginary(); 49 | constexpr imaginary(const imaginary& other) = default; 50 | 51 | constexpr explicit imaginary(value_type real); 52 | template 53 | constexpr explicit imaginary(imaginary other); 54 | 55 | // Operators 56 | template 57 | constexpr auto operator+=(imaginary other) 58 | -> imaginary&; 59 | template 60 | constexpr auto operator-=(imaginary other) 61 | -> imaginary&; 62 | constexpr auto operator*=(T real) 63 | -> imaginary&; 64 | constexpr auto operator/=(T real) 65 | -> imaginary&; 66 | 67 | // Member data 68 | value_type value = T{}; 69 | }; 70 | 71 | /** 72 | * @brief Complex numbers 73 | */ 74 | template 75 | struct complex 76 | { 77 | static_assert(std::is_arithmetic::value, 78 | "a complex number can only contain arithmetic values"); 79 | 80 | using value_type = T; 81 | 82 | //////////////////////////////////////////////////////////// 83 | // Constructors 84 | 85 | constexpr complex(); 86 | constexpr complex(const complex& other) = default; 87 | 88 | constexpr complex(value_type real, value_type imag); 89 | constexpr complex(value_type real, imaginary imag); 90 | constexpr complex(value_type real); 91 | constexpr complex(imaginary imag); 92 | template 93 | constexpr explicit complex(complex other); 94 | 95 | //////////////////////////////////////////////////////////// 96 | // Augmented assignment operators 97 | 98 | constexpr auto operator+=(T other) 99 | -> complex&; 100 | constexpr auto operator-=(T other) 101 | -> complex&; 102 | constexpr auto operator*=(T other) 103 | -> complex&; 104 | constexpr auto operator/=(T other) 105 | -> complex&; 106 | 107 | constexpr auto operator+=(imaginary other) 108 | -> complex&; 109 | constexpr auto operator-=(imaginary other) 110 | -> complex&; 111 | constexpr auto operator*=(imaginary other) 112 | -> complex&; 113 | constexpr auto operator/=(imaginary other) 114 | -> complex&; 115 | 116 | template 117 | constexpr auto operator+=(complex other) 118 | -> complex&; 119 | template 120 | constexpr auto operator-=(complex other) 121 | -> complex&; 122 | template 123 | constexpr auto operator*=(complex other) 124 | -> complex&; 125 | template 126 | constexpr auto operator/=(complex other) 127 | -> complex&; 128 | 129 | //////////////////////////////////////////////////////////// 130 | // Member data 131 | 132 | value_type real = T{}; 133 | imaginary imag = imaginary{}; 134 | }; 135 | 136 | //////////////////////////////////////////////////////////// 137 | // Unary arithmetic operators 138 | 139 | template 140 | constexpr auto operator+(imaginary imag) 141 | -> imaginary; 142 | template 143 | constexpr auto operator-(imaginary imag) 144 | -> imaginary; 145 | 146 | template 147 | constexpr auto operator+(complex ratio) 148 | -> complex; 149 | template 150 | constexpr auto operator-(complex ratio) 151 | -> complex; 152 | 153 | //////////////////////////////////////////////////////////// 154 | // Binary arithmetic operators 155 | 156 | template 157 | constexpr auto operator+(imaginary lhs, imaginary rhs) 158 | -> imaginary>; 159 | template 160 | constexpr auto operator-(imaginary lhs, imaginary rhs) 161 | -> imaginary>; 162 | template 163 | constexpr auto operator*(imaginary lhs, imaginary rhs) 164 | -> std::common_type_t; 165 | template 166 | constexpr auto operator/(imaginary lhs, imaginary rhs) 167 | -> std::common_type_t; 168 | 169 | template::value>> 171 | constexpr auto operator+(imaginary lhs, Number rhs) 172 | -> complex>; 173 | template::value>> 175 | constexpr auto operator-(imaginary lhs, Number rhs) 176 | -> complex>; 177 | template::value>> 179 | constexpr auto operator*(imaginary lhs, Number rhs) 180 | -> imaginary>; 181 | template::value>> 183 | constexpr auto operator/(imaginary lhs, Number rhs) 184 | -> imaginary>; 185 | 186 | template::value>> 188 | constexpr auto operator+(Number lhs, imaginary rhs) 189 | -> complex>; 190 | template::value>> 192 | constexpr auto operator-(Number lhs, imaginary rhs) 193 | -> complex>; 194 | template::value>> 196 | constexpr auto operator*(Number lhs, imaginary rhs) 197 | -> imaginary>; 198 | template::value>> 200 | constexpr auto operator/(Number lhs, imaginary rhs) 201 | -> imaginary>; 202 | 203 | template 204 | constexpr auto operator+(complex lhs, complex rhs) 205 | -> complex>; 206 | template 207 | constexpr auto operator-(complex lhs, complex rhs) 208 | -> complex>; 209 | template 210 | constexpr auto operator*(complex lhs, complex rhs) 211 | -> complex>; 212 | template 213 | constexpr auto operator/(complex lhs, complex rhs) 214 | -> complex>; 215 | 216 | template::value>> 218 | constexpr auto operator+(complex lhs, Number rhs) 219 | -> complex>; 220 | template::value>> 222 | constexpr auto operator-(complex lhs, Number rhs) 223 | -> complex>; 224 | template::value>> 226 | constexpr auto operator*(complex lhs, Number rhs) 227 | -> complex>; 228 | template::value>> 230 | constexpr auto operator/(complex lhs, Number rhs) 231 | -> complex>; 232 | 233 | template::value>> 235 | constexpr auto operator+(Number lhs, complex rhs) 236 | -> complex>; 237 | template::value>> 239 | constexpr auto operator-(Number lhs, complex rhs) 240 | -> complex>; 241 | template::value>> 243 | constexpr auto operator*(Number lhs, complex rhs) 244 | -> complex>; 245 | template::value>> 247 | constexpr auto operator/(Number lhs, complex rhs) 248 | -> complex>; 249 | 250 | template 251 | constexpr auto operator+(complex lhs, imaginary rhs) 252 | -> complex>; 253 | template 254 | constexpr auto operator-(complex lhs, imaginary rhs) 255 | -> complex>; 256 | template 257 | constexpr auto operator*(complex lhs, imaginary rhs) 258 | -> complex>; 259 | template 260 | constexpr auto operator/(complex lhs, imaginary rhs) 261 | -> complex>; 262 | 263 | template 264 | constexpr auto operator+(imaginary lhs, complex rhs) 265 | -> complex>; 266 | template 267 | constexpr auto operator-(imaginary lhs, complex rhs) 268 | -> complex>; 269 | template 270 | constexpr auto operator*(imaginary lhs, complex rhs) 271 | -> complex>; 272 | template 273 | constexpr auto operator/(imaginary lhs, complex rhs) 274 | -> complex>; 275 | 276 | //////////////////////////////////////////////////////////// 277 | // Comparison operators 278 | 279 | template 280 | constexpr auto operator==(imaginary lhs, imaginary rhs) 281 | -> bool; 282 | template 283 | constexpr auto operator!=(imaginary lhs, imaginary rhs) 284 | -> bool; 285 | 286 | template 287 | constexpr auto operator==(complex lhs, complex rhs) 288 | -> bool; 289 | template 290 | constexpr auto operator!=(complex lhs, complex rhs) 291 | -> bool; 292 | 293 | template::value>> 295 | constexpr auto operator==(complex lhs, Number rhs) 296 | -> bool; 297 | template::value>> 299 | constexpr auto operator!=(complex lhs, Number rhs) 300 | -> bool; 301 | 302 | template::value>> 304 | constexpr auto operator==(Number lhs, complex rhs) 305 | -> bool; 306 | template::value>> 308 | constexpr auto operator!=(Number lhs, complex rhs) 309 | -> bool; 310 | 311 | template 312 | constexpr auto operator==(complex lhs, imaginary rhs) 313 | -> bool; 314 | template 315 | constexpr auto operator!=(complex lhs, imaginary rhs) 316 | -> bool; 317 | 318 | template 319 | constexpr auto operator==(imaginary lhs, complex rhs) 320 | -> bool; 321 | template 322 | constexpr auto operator!=(imaginary lhs, complex rhs) 323 | -> bool; 324 | 325 | //////////////////////////////////////////////////////////// 326 | // Mathematical functions 327 | 328 | template 329 | constexpr auto abs(complex z) 330 | -> T; 331 | 332 | template 333 | constexpr auto norm(complex z) 334 | -> T; 335 | template 336 | constexpr auto norm(T value) 337 | -> T; 338 | 339 | template 340 | constexpr auto conj(complex z) 341 | -> complex; 342 | template 343 | constexpr auto conj(T value) 344 | -> complex; 345 | 346 | template 347 | constexpr auto polar(T rho, T theta) 348 | -> complex; 349 | 350 | inline namespace literals 351 | { 352 | inline namespace complex_literals 353 | { 354 | //////////////////////////////////////////////////////////// 355 | // Float user-defined literals 356 | 357 | constexpr auto operator"" _if(long double n) 358 | -> imaginary; 359 | 360 | constexpr auto operator"" _i(long double n) 361 | -> imaginary; 362 | 363 | constexpr auto operator"" _il(long double n) 364 | -> imaginary; 365 | 366 | //////////////////////////////////////////////////////////// 367 | // Integer user-defined literals 368 | 369 | constexpr auto operator"" _i(unsigned long long n) 370 | -> imaginary; 371 | 372 | constexpr auto operator"" _il(unsigned long long n) 373 | -> imaginary; 374 | 375 | constexpr auto operator"" _ill(unsigned long long n) 376 | -> imaginary; 377 | 378 | constexpr auto operator"" _ui(unsigned long long n) 379 | -> imaginary; 380 | 381 | constexpr auto operator"" _uil(unsigned long long n) 382 | -> imaginary; 383 | 384 | constexpr auto operator"" _uill(unsigned long long n) 385 | -> imaginary; 386 | }} 387 | 388 | #include "detail/complex.inl" 389 | } 390 | 391 | #endif // SMATH_COMPLEX_H_ 392 | --------------------------------------------------------------------------------