From ca834d3034ed5c6427b82dad95de45456de79290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Ba=C4=87?= Date: Mon, 12 Aug 2024 10:15:15 +0200 Subject: [PATCH] 2.x - c++23 (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * wip * type convertions * workflows + ci * wip tests * wip * wip * wip * wip * ut * workflow --------- Co-authored-by: Artur Bać --- .github/workflows/cmake.yml | 69 +- CMakeLists.txt | 37 +- CMakeModules/get_fixed_math_version.cmake | 2 +- CMakePresets.json | 253 +-- LICENCE | 24 - cmake/CPM.cmake | 24 + examples/brief-usage.cc | 9 +- fixed_lib/CMakeLists.txt | 10 +- fixed_lib/include/fixedmath/core_ops.h | 107 ++ fixed_lib/include/fixedmath/detail/common.h | 204 +- .../include/fixedmath/detail/type_traits.h | 175 +- .../include/fixedmath/detail/utility_cxx20.h | 336 +--- fixed_lib/include/fixedmath/fixed_math.hpp | 404 ++-- fixed_lib/include/fixedmath/iostream.h | 45 +- fixed_lib/include/fixedmath/limits.h | 126 +- fixed_lib/include/fixedmath/math.h | 1686 +++++++---------- fixed_lib/include/fixedmath/numbers.h | 36 +- fixed_lib/include/fixedmath/types.h | 163 +- .../include/fixedmath/unittests/addition.h | 75 - fixed_lib/include/fixedmath/unittests/atan.h | 373 ---- .../unittests/compile_time_unit_tests.h | 44 - .../include/fixedmath/unittests/division.h | 76 - .../fixedmath/unittests/fixed_construction.h | 35 - .../floating_point_type_convertions.h | 72 - .../unittests/integral_type_convertions.h | 42 - .../fixedmath/unittests/misc_functions.h | 50 - .../fixedmath/unittests/multiplication.h | 63 - fixed_lib/include/fixedmath/unittests/sin.h | 94 - fixed_lib/include/fixedmath/unittests/sqrt.h | 63 - .../fixedmath/unittests/substraction.h | 55 - fixed_lib/include/fixedmath/unittests/tan.h | 30 - .../include/fixedmath/unittests/type_traits.h | 118 -- .../fixedmath/unittests/unit_test_common.h | 34 - fixed_lib/src/cos_angle_table.h | 202 -- fixed_lib/src/fixed_math.cc | 145 -- fixed_lib/src/sin_angle_table.h | 202 -- fixed_lib/src/square_root_table.h | 150 -- fixed_lib/src/tan_table.h | 150 -- git_tag.sh | 33 +- perf_test_suite/perf.cc | 222 ++- table_gen/CMakeLists.txt | 11 - table_gen/table_gen.cc | 192 -- unit_tests/CMakeLists.txt | 104 +- unit_tests/addition_ut.cc | 71 + unit_tests/atan_ut.cc | 390 ++++ unit_tests/division_ut.cc | 83 + unit_tests/fixed_construction_ut.cc | 128 ++ unit_tests/hypot_not_abacus.cc | 13 +- unit_tests/include/atan.h | 23 + unit_tests/include/boost_ut.h | 14 + unit_tests/include/type_traits.h | 25 + unit_tests/include/unit_test_common.h | 35 + unit_tests/include/unit_test_core.h | 614 ++++++ unit_tests/misc_functions_ut.cc | 64 + unit_tests/multiplication_ut.cc | 67 + unit_tests/sin_cos_ut.cc | 104 + unit_tests/sqrt_ut.cc | 79 + unit_tests/subtraction_ut.cc | 61 + unit_tests/tan_ut.cc | 37 + unit_tests/type_convertions_ut.cc | 128 ++ 60 files changed, 3652 insertions(+), 4629 deletions(-) create mode 100644 cmake/CPM.cmake create mode 100644 fixed_lib/include/fixedmath/core_ops.h delete mode 100644 fixed_lib/include/fixedmath/unittests/addition.h delete mode 100644 fixed_lib/include/fixedmath/unittests/atan.h delete mode 100644 fixed_lib/include/fixedmath/unittests/compile_time_unit_tests.h delete mode 100644 fixed_lib/include/fixedmath/unittests/division.h delete mode 100644 fixed_lib/include/fixedmath/unittests/fixed_construction.h delete mode 100644 fixed_lib/include/fixedmath/unittests/floating_point_type_convertions.h delete mode 100644 fixed_lib/include/fixedmath/unittests/integral_type_convertions.h delete mode 100644 fixed_lib/include/fixedmath/unittests/misc_functions.h delete mode 100644 fixed_lib/include/fixedmath/unittests/multiplication.h delete mode 100644 fixed_lib/include/fixedmath/unittests/sin.h delete mode 100644 fixed_lib/include/fixedmath/unittests/sqrt.h delete mode 100644 fixed_lib/include/fixedmath/unittests/substraction.h delete mode 100644 fixed_lib/include/fixedmath/unittests/tan.h delete mode 100644 fixed_lib/include/fixedmath/unittests/type_traits.h delete mode 100644 fixed_lib/include/fixedmath/unittests/unit_test_common.h delete mode 100644 fixed_lib/src/cos_angle_table.h delete mode 100644 fixed_lib/src/fixed_math.cc delete mode 100644 fixed_lib/src/sin_angle_table.h delete mode 100644 fixed_lib/src/square_root_table.h delete mode 100644 fixed_lib/src/tan_table.h delete mode 100644 table_gen/CMakeLists.txt delete mode 100644 table_gen/table_gen.cc create mode 100644 unit_tests/addition_ut.cc create mode 100644 unit_tests/atan_ut.cc create mode 100644 unit_tests/division_ut.cc create mode 100644 unit_tests/fixed_construction_ut.cc create mode 100644 unit_tests/include/atan.h create mode 100644 unit_tests/include/boost_ut.h create mode 100644 unit_tests/include/type_traits.h create mode 100644 unit_tests/include/unit_test_common.h create mode 100644 unit_tests/include/unit_test_core.h create mode 100644 unit_tests/misc_functions_ut.cc create mode 100644 unit_tests/multiplication_ut.cc create mode 100644 unit_tests/sin_cos_ut.cc create mode 100644 unit_tests/sqrt_ut.cc create mode 100644 unit_tests/subtraction_ut.cc create mode 100644 unit_tests/tan_ut.cc create mode 100644 unit_tests/type_convertions_ut.cc diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5cc1222..4fa78a0 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,5 +1,4 @@ -name: CMake - +name: C++ CI on: push: branches: [ "master" ] @@ -11,46 +10,36 @@ on: paths-ignore: - 'README.md' - 'docs/**' - env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) BUILD_TYPE: Release jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-latest - + build-and-test-gcc: + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 - - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{github.workspace}}/build - - - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash - working-directory: ${{github.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DFIXEDMATH_ENABLE_UNIT_TESTS=ON - - - name: Build - working-directory: ${{github.workspace}}/build - shell: bash - # Execute the build. You can specify a specific target with "--target " - run: cmake --build . --config $BUILD_TYPE - - - name: Test - working-directory: ${{github.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C $BUILD_TYPE + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + sudo apt-get update && sudo apt-get install -y cmake ninja-build gcc-14 g++-14 + - name: gcc-14-release + run: cmake --workflow --preset="ci-gcc-14-release" + + build-and-test-clang: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: Add LLVM Repository + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 18 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake g++-14 ninja-build clang-18 libfmt-dev libc++-18-dev libc++abi-18-dev + + - name: clang-18-release + run: cmake --workflow --preset="ci-clang-18-release" + - name: clang-18-libc++-release + run: cmake --workflow --preset="ci-clang-18-libc++-release" diff --git a/CMakeLists.txt b/CMakeLists.txt index 23b27b8..bfd3c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.21 FATAL_ERROR ) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") include(get_fixed_math_version) +include(cmake/CPM.cmake) project(fixed_math LANGUAGES CXX @@ -10,7 +11,7 @@ project(fixed_math message(STATUS "fixed_math VERSION: ${fixed_math_VERSION}") set(fixed_math_HOMEPAGE_URL "https://github.com/arturbac/fixed_math") -set(fixed_math_DESCRIPTION "fixed point math library in C++17") +set(fixed_math_DESCRIPTION "fixed point math library in C++20") include(FeatureSummary) @@ -28,18 +29,18 @@ include(GNUInstallDirs) # options #----------------------------------------------------------------------------- if(PROJECT_IS_TOP_LEVEL) - option(FIXEDMATH_ENABLE_UNIT_TESTS "unit tests available from CTest" OFF ) + option(FIXEDMATH_ENABLE_UNIT_TESTS "unit tests available from CTest" ON ) add_feature_info("FIXEDMATH_ENABLE_UNIT_TESTS" FIXEDMATH_ENABLE_UNIT_TESTS "unit test available from CTest") option(FIXEDMATH_ENABLE_DEVEL_CODE "enable internaly used for development code" OFF ) add_feature_info("ENABLE_DEVEL_CODE" ENABLE_DEVEL_CODE "enable internaly used for development code") endif() -# CMAKE_CXX_STANDARD used for compilation of fixedmath will not affect CMAKE_CXX_STANDARD avaialble when importing library -if(NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 17 ) - message(STATUS "Assuming by default c++17 standard") - set( CMAKE_CXX_STANDARD 17 ) -endif() -set( CMAKE_CXX_STANDARD_REQUIRED ON ) + +# if(NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 23 ) +# message(STATUS "Assuming by default c++23 standard") +# set( CMAKE_CXX_STANDARD 23 ) +# endif() +# set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF) #----------------------------------------------------------------------------- @@ -48,24 +49,14 @@ set( CMAKE_CXX_EXTENSIONS OFF) add_subdirectory( fixed_lib ) -if(FIXEDMATH_ENABLE_DEVEL_CODE) - add_subdirectory(table_gen) - add_subdirectory(perf_test_suite) +if(PROJECT_IS_TOP_LEVEL AND FIXEDMATH_ENABLE_DEVEL_CODE) + # add_subdirectory(perf_test_suite) endif() -if( PROJECT_IS_TOP_LEVEL) - if( FIXEDMATH_ENABLE_UNIT_TESTS ) - enable_testing( TRUE ) - add_subdirectory(unit_tests) - endif() +if( PROJECT_IS_TOP_LEVEL AND FIXEDMATH_ENABLE_UNIT_TESTS) + enable_testing( TRUE ) + add_subdirectory(unit_tests) endif() -#----------------------------------------------------------------------------- -# Add clean-all target -#----------------------------------------------------------------------------- -add_custom_target(clean-all - COMMAND ${CMAKE_BUILD_TOOL} clean - COMMAND rm -rf ${CMAKE_BINARY_DIR}/ -) if( PROJECT_IS_TOP_LEVEL) feature_summary(WHAT ALL) diff --git a/CMakeModules/get_fixed_math_version.cmake b/CMakeModules/get_fixed_math_version.cmake index 4fcf30c..00f8d3f 100644 --- a/CMakeModules/get_fixed_math_version.cmake +++ b/CMakeModules/get_fixed_math_version.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) # Version 3.10 is required for string(JSON ...) +cmake_minimum_required(VERSION 3.23) # Version 3.10 is required for string(JSON ...) # Read the content of types.h into a variable file(READ fixed_lib/include/fixedmath/types.h types_h_content) diff --git a/CMakePresets.json b/CMakePresets.json index f741104..2874e69 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -9,9 +9,13 @@ { "name": "cfg-common", "hidden": true, - "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { "FIXEDMATH_ENABLE_UNIT_TESTS": "ON" } }, + { + "name": "cfg-build-dir", + "hidden": true, + "binaryDir": "${sourceDir}/build/${presetName}" + }, { "name": "cfg-ninja", "hidden": true, @@ -19,11 +23,6 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { - "name": "cfg-c++20", - "hidden": true, - "cacheVariables": { "CMAKE_CXX_STANDARD" : "20" } - }, - { "name": "cfg-c++23", "hidden": true, "cacheVariables": { "CMAKE_CXX_STANDARD" : "23" } @@ -38,285 +37,119 @@ } }, { - "name": "clang-17-release", + "name": "clang-18-release", "inherits": [ "cfg-common", "cfg-ninja", "cfg-c++23" ], - "cacheVariables": { "CMAKE_CXX_COMPILER" : "/usr/lib/llvm/17/bin/clang++" } - }, - { - "name": "clang-17-libc++release", - "inherits": ["clang-17-release", "cfg-libc++"] - }, - { - "name": "clang-16-release", - "inherits": [ "cfg-common", "cfg-ninja", "cfg-c++23" ], - "cacheVariables": { "CMAKE_CXX_COMPILER" : "/usr/lib/llvm/16/bin/clang++" } - }, - { - "name": "clang-16-libc++release", - "inherits": ["clang-16-release", "cfg-libc++"] - }, - { - "name": "clang-15-release", - "inherits": [ "cfg-common", "cfg-ninja", "cfg-c++20" ], - "cacheVariables": { "CMAKE_CXX_COMPILER": "/usr/lib/llvm/15/bin/clang++" } + "cacheVariables": { "CMAKE_CXX_COMPILER" : "clang++-18", "FIXEDMATH_ENABLE_DEVEL_CODE" : "ON" } }, { - "name": "clang-15-libc++release", - "inherits": ["clang-15-release", "cfg-libc++"] + "name": "ci-clang-18-release", + "inherits": [ "cfg-common", "cfg-build-dir", "cfg-ninja", "cfg-c++23" ], + "cacheVariables": { "CMAKE_CXX_COMPILER" : "clang++-18" } }, { - "name": "gcc-12-release", - "inherits": [ "cfg-common", "cfg-ninja", "cfg-c++20" ], - "cacheVariables": { - "CMAKE_CXX_COMPILER": "g++-12", - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } + "name": "ci-clang-18-libc++-release", + "inherits": ["ci-clang-18-release", "cfg-libc++"] }, { - "name": "gcc-13-release", - "inherits": [ "cfg-common", "cfg-ninja", "cfg-c++23" ], - "cacheVariables": { - "CMAKE_CXX_COMPILER": "g++-13", - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } + "name": "ci-gcc-14-release", + "inherits": [ "cfg-common", "cfg-build-dir", "cfg-ninja", "cfg-c++23" ], + "cacheVariables": {"CMAKE_CXX_COMPILER": "g++-14" } }, { - "name": "clangcl-release", - "inherits": "cfg-common", + "name": "ci-clangcl-release", + "inherits": ["cfg-common", "cfg-build-dir"], "generator": "Visual Studio 17 2022", "toolset": "ClangCL" }, { - "name": "msvc-release", - "inherits": "cfg-common", + "name": "ci-msvc-release", + "inherits": ["cfg-common", "cfg-build-dir"], "generator": "Visual Studio 17 2022" - }, - { - "name": "clang-15-release-coverage", - "inherits": "clang-15-release", - "cacheVariables": { - "CMAKE_CXX_FLAGS": "--coverage" - } } ], "buildPresets": [ { - "name": "clang-17-release", - "configurePreset": "clang-17-release" - }, - { - "name": "clang-17-libc++release", - "configurePreset": "clang-17-libc++release" - }, - { - "name": "clang-16-release", - "configurePreset": "clang-16-release" - }, - { - "name": "clang-16-libc++release", - "configurePreset": "clang-16-libc++release" + "name": "ci-clang-18-release", + "configurePreset": "ci-clang-18-release" }, { - "name": "clang-15-release", - "configurePreset": "clang-15-release" + "name": "ci-clang-18-libc++-release", + "configurePreset": "ci-clang-18-libc++-release" }, { - "name": "clang-15-libc++release", - "configurePreset": "clang-15-libc++release" - }, - { - "name": "gcc-12-release", - "configurePreset": "gcc-12-release" - }, - { - "name": "gcc-13-release", - "configurePreset": "gcc-13-release" + "name": "ci-gcc-14-release", + "configurePreset": "ci-gcc-14-release" } ], "testPresets": [ { - "name": "clang-17-release", - "configurePreset": "clang-17-release", - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} - }, - { - "name": "clang-17-libc++release", - "configurePreset": "clang-17-libc++release", - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} - }, - { - "name": "clang-16-release", - "configurePreset": "clang-16-release", - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} - }, - { - "name": "clang-16-libc++release", - "configurePreset": "clang-16-libc++release", - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} - }, - { - "name": "clang-15-release", - "configurePreset": "clang-15-release", + "name": "ci-clang-18-release", + "configurePreset": "ci-clang-18-release", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} }, { - "name": "clang-15-libc++release", - "configurePreset": "clang-15-libc++release", + "name": "ci-clang-18-libc++-release", + "configurePreset": "ci-clang-18-libc++-release", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} }, { - "name": "gcc-12-release", - "configurePreset": "gcc-12-release", - "output": {"outputOnFailure": true}, - "execution": {"noTestsAction": "error", "stopOnFailure": true} - }, - { - "name": "gcc-13-release", - "configurePreset": "gcc-13-release", + "name": "ci-gcc-14-release", + "configurePreset": "ci-gcc-14-release", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} } ], "workflowPresets": [ { - "name": "clang-17-release", - "steps": [ - { - "type": "configure", - "name": "clang-17-release" - }, - { - "type": "build", - "name": "clang-17-release" - }, - { - "type": "test", - "name": "clang-17-release" - } - ] - }, - { - "name": "clang-17-libc++release", - "steps": [ - { - "type": "configure", - "name": "clang-17-libc++release" - }, - { - "type": "build", - "name": "clang-17-libc++release" - }, - { - "type": "test", - "name": "clang-17-libc++release" - } - ] - }, - { - "name": "clang-16-release", - "steps": [ - { - "type": "configure", - "name": "clang-16-release" - }, - { - "type": "build", - "name": "clang-16-release" - }, - { - "type": "test", - "name": "clang-16-release" - } - ] - }, - { - "name": "clang-16-libc++release", - "steps": [ - { - "type": "configure", - "name": "clang-16-libc++release" - }, - { - "type": "build", - "name": "clang-16-libc++release" - }, - { - "type": "test", - "name": "clang-16-libc++release" - } - ] - }, - { - "name": "clang-15-release", - "steps": [ - { - "type": "configure", - "name": "clang-15-release" - }, - { - "type": "build", - "name": "clang-15-release" - }, - { - "type": "test", - "name": "clang-15-release" - } - ] - }, - { - "name": "clang-15-libc++release", + "name": "ci-clang-18-release", "steps": [ { "type": "configure", - "name": "clang-15-libc++release" + "name": "ci-clang-18-release" }, { "type": "build", - "name": "clang-15-libc++release" + "name": "ci-clang-18-release" }, { "type": "test", - "name": "clang-15-libc++release" + "name": "ci-clang-18-release" } ] }, { - "name": "gcc-12-release", + "name": "ci-clang-18-libc++-release", "steps": [ { "type": "configure", - "name": "gcc-12-release" + "name": "ci-clang-18-libc++-release" }, { "type": "build", - "name": "gcc-12-release" + "name": "ci-clang-18-libc++-release" }, { "type": "test", - "name": "gcc-12-release" + "name": "ci-clang-18-libc++-release" } ] }, { - "name": "gcc-13-release", + "name": "ci-gcc-14-release", "steps": [ { "type": "configure", - "name": "gcc-13-release" + "name": "ci-gcc-14-release" }, { "type": "build", - "name": "gcc-13-release" + "name": "ci-gcc-14-release" }, { "type": "test", - "name": "gcc-13-release" + "name": "ci-gcc-14-release" } ] } diff --git a/LICENCE b/LICENCE index b40cfe9..36b7cd9 100644 --- a/LICENCE +++ b/LICENCE @@ -1,27 +1,3 @@ -This library is available to anybody free of charge, under the terms of MIT License or Boost Software License - Version 1.0 - -Copyright (c) 2019-2021 arturbac (Artur Bać) - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 0000000..f2c1205 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.40.0) +set(CPM_HASH_SUM "7b354f3a5976c4626c876850c93944e52c83ec59a159ae5de5be7983f0e17a2a") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/examples/brief-usage.cc b/examples/brief-usage.cc index 11a09b5..060102a 100644 --- a/examples/brief-usage.cc +++ b/examples/brief-usage.cc @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + #include #include @@ -5,12 +9,13 @@ using fixedmath::fixed_t; using fixedmath::operator""_fix; // fixed and all functionality is constexpr so You can declare constants see features [1] -inline constexpr fixed_t foo_constant{fixedmath::tan(15 * fixedmath::phi / 180)}; +inline constexpr fixed_t foo_constant{fixedmath::fobj::tan(15 * fixedmath::phi / 180)}; constexpr fixed_t my_function(fixed_t value) { using namespace fixedmath; - return foo_constant + sin(value) / (1.41_fix - 2 * cos(value) / 4); + // You can use funcioons or function objects + return foo_constant + fobj::sin(value) / (1.41_fix - 2 * func::cos(value) / 4); } int main() diff --git a/fixed_lib/CMakeLists.txt b/fixed_lib/CMakeLists.txt index 46d6279..f0ae4cf 100644 --- a/fixed_lib/CMakeLists.txt +++ b/fixed_lib/CMakeLists.txt @@ -1,13 +1,12 @@ -add_library( fixed_math ) - +add_library( fixed_math INTERFACE ) +target_compile_features( fixed_math INTERFACE cxx_std_23 ) target_include_directories( fixed_math - PUBLIC + INTERFACE "$" "$/include>" ) -target_sources( fixed_math PRIVATE src/fixed_math.cc ) file(GLOB fixed_math_include_files ${CMAKE_CURRENT_SOURCE_DIR}/include/fixedmath/*.h @@ -20,9 +19,6 @@ file(GLOB fixed_math_include_files_detail install(TARGETS fixed_math EXPORT fixed_math_targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/fixed_lib/include/fixedmath/core_ops.h b/fixed_lib/include/fixedmath/core_ops.h new file mode 100644 index 0000000..4194f96 --- /dev/null +++ b/fixed_lib/include/fixedmath/core_ops.h @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + +#pragma once +#include +#include "types.h" +#include "limits.h" +#include "numbers.h" +#include "detail/common.h" + +namespace fixedmath::inline v2 + { +//------------------------------------------------------------------------------------------------------ +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator-(std::same_as auto l) noexcept -> fixed_t + { + return fix_carrier_t{-l.v}; + } + +//------------------------------------------------------------------------------------------------------ + +struct arithmetic_to_fixed_t + { + template + [[nodiscard, gnu::const, gnu::always_inline]] + ///\returns fixed on success or NaN if source value is out of range + static constexpr auto operator()(arithmetic_type value) noexcept -> fixed_t + { + if constexpr(std::is_integral_v) + { + if(std::cmp_less_equal(value, detail::limits_::max_integral()) + && std::cmp_greater_equal(value, detail::limits_::min_integral())) [[likely]] + { + if constexpr(typetraits::is_unsigned_v) + return fix_carrier_t{detail::unsigned_shift_left_unsigned<16>(value)}; + else + return fix_carrier_t{detail::unsigned_shift_left_signed<16>(value)}; + } + return quiet_NaN_result(); + } + else + { + using ft = arithmetic_type; + if(value < double(detail::limits_::max_integral()) && value > double(detail::limits_::min_integral())) [[likely]] + return fix_carrier_t(static_cast(value * 65536 + (value < ft(0) ? ft(-0.5) : ft(0.5)))); + + return quiet_NaN_result(); + } + } + }; + +///\brief Converts an floating point or integral to a fixed_t type +inline constexpr arithmetic_to_fixed_t arithmetic_to_fixed{}; + +constexpr auto operator""_fix(unsigned long long value) noexcept -> fixed_t + { + return arithmetic_to_fixed(static_cast(value)); + } + +constexpr auto operator""_fix(long double value) noexcept -> fixed_t + { + return arithmetic_to_fixed(static_cast(value)); + } + +template +constexpr fixed_t::fixed_t(arithmethic_type value) noexcept : v{arithmetic_to_fixed(value).v} + { + } + +//------------------------------------------------------------------------------------------------------ + +template +struct fixed_to_arithmetic_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto value) noexcept -> arithmethic_type + { + if constexpr(typetraits::is_integral_v) + { + fixed_internal tmp{(value.v >> 16) /*+ (( value.v & 0x8000) >> 15)*/}; + using al = std::numeric_limits; + static constexpr auto integral_min{al::min()}; + static constexpr auto integral_max{al::max()}; + if(std::cmp_greater_equal(tmp, integral_min) && std::cmp_less_equal(tmp, integral_max)) + return static_cast(tmp); + else + return std::numeric_limits::quiet_NaN(); + } + else + return static_cast(value.v) / arithmethic_type(65536); + } + }; + +///\brief Converts an fixed_t point value to an integral or floating point value. +template +inline constexpr fixed_to_arithmetic_t fixed_to_arithmetic{}; + +template +[[nodiscard]] +constexpr fixed_t::operator arithmethic_type() const noexcept + { + return fixed_to_arithmetic(*this); + } + + } // namespace fixedmath::inline v2 + diff --git a/fixed_lib/include/fixedmath/detail/common.h b/fixed_lib/include/fixedmath/detail/common.h index 0a33775..638fe95 100644 --- a/fixed_lib/include/fixedmath/detail/common.h +++ b/fixed_lib/include/fixedmath/detail/common.h @@ -1,124 +1,108 @@ +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + #pragma once #include "../types.h" -#include +#include -#define FIXEDMATH_PUBLIC gnu::visibility("default") +namespace fixedmath::inline v2::detail + { -#if defined(__GNUC__) || defined(__clang__) - #define fixed_likely(x) __builtin_expect(static_cast(x), 1) - #define fixed_unlikely(x) __builtin_expect(static_cast(x), 0) -#else - #define fixed_likely(x) ((x)) - #define fixed_unlikely(x) ((x)) -#endif +template +[[gnu::const, gnu::always_inline]] +constexpr auto unsigned_shift_left_signed(std::signed_integral auto value) noexcept -> fixed_internal + { + return static_cast( + (static_cast(value) << digits) + | (static_cast(value) & (fixed_internal_unsigned(1) << 63u)) + ); + } -namespace fixedmath::detail +template +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto unsigned_shift_left_unsigned(std::unsigned_integral auto value) noexcept -> fixed_internal { + return static_cast(static_cast(value) << digits); + } - template - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_internal unsigned_shift_left_signed( fixed_internal value ) noexcept - { - using unsigned_internal = std::make_unsigned::type; - return static_cast( - (static_cast( value ) << digits) - | (static_cast( value ) & ( unsigned_internal(1) << 63u)) - ); - } - - template - && is_unsigned_v> - > - [[nodiscard, gnu::const, gnu::always_inline ]] - constexpr auto promote_integral_unsigned_to_signed( value_type value ) noexcept - { - using signed_type = typename signed_type_by_size<((sizeof(value_type)<<1))>::type; - return static_cast( value ); - } - - template - [[nodiscard, gnu::const, gnu::always_inline ]] - constexpr auto promote_type_to_signed( value_type value ) noexcept - { - if constexpr ( detail::is_signed_v ) - return value; - else - return promote_integral_unsigned_to_signed( value ); - } - - template - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal unsigned_shift_left_unsigned( fixed_internal value ) noexcept - { - using unsigned_internal = std::make_unsigned::type; - return static_cast( - (static_cast( value ) << digits)); - } - - ///\returns the highest power of 4 that is less than or equal to \param value - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal highest_pwr4_clz( fixed_internal_unsigned value ) noexcept - { - if( fixed_likely( value != 0 ) ) - { - int clz{ cxx20::countl_zero( value ) }; - - clz = (64 - clz); - if( (clz & 1) == 0 ) - clz -= 1; - - return 1ll << (clz-1); - } - return 0; - } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal highest_pwr4( fixed_internal_unsigned value ) noexcept - { - // one starts at the highest power of four <= than the argument. - fixed_internal_unsigned pwr4 { 1ll << 62 }; // second-to-top bit set - - while (pwr4 > value) - pwr4 >>= 2; - return pwr4; - } - - template - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal mul_( fixed_internal x, fixed_internal y ) noexcept - { - return (x * y) >> precision; - } - template - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal div_( fixed_internal x, fixed_internal y ) noexcept - { - return (x< - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_internal fix_( fixed_internal x ) noexcept - { - return (x< +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto promote_type_to_signed(value_type value) noexcept + { + if constexpr(std::is_signed_v) + return value; + else { - if(!sign_) - return as_fixed(result); - return as_fixed(-result); + using signed_type = typetraits::promote_to_signed_t; + return static_cast(value); } - - template::value>> - constexpr void swap(T& a, T& b) noexcept + } + +[[nodiscard, gnu::const, gnu::always_inline]] +///\returns the highest power of 4 that is less than or equal to \ref value +constexpr auto highest_pwr4_clz(concepts::internal_unsigned auto value) noexcept -> fixed_internal + { + if(value != 0) [[likely]] { - T temp = a; - a = b; - b = temp; + int clz{std::countl_zero(value)}; + + clz = (64 - clz); + if((clz & 1) == 0) + clz -= 1; + + return fixed_internal(1ll << (clz - 1)); } + return 0; + } + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto highest_pwr4(std::unsigned_integral auto value) noexcept -> fixed_internal + { + // one starts at the highest power of four <= than the argument. + fixed_internal_unsigned pwr4{1ll << 62}; // second-to-top bit set + + while(pwr4 > value) + pwr4 >>= 2; + return fixed_internal(pwr4); + } + +template +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto mul_(concepts::internal auto x, concepts::internal auto y) noexcept -> fixed_internal + { + return (x * y) >> precision; + } + +template +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto div_(concepts::internal auto x, concepts::internal auto y) noexcept -> fixed_internal + { + return (x << precision) / y; + } + +template +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto fix_(std::integral auto x) noexcept -> fixed_internal + { + return fixed_internal(x) << precision; + } + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto set_sign(bool sign_, concepts::internal auto result) -> fixed_t + { + if(!sign_) + return as_fixed(result); + return as_fixed(-result); + } + +template +constexpr void swap(T & a, T & b) noexcept + { + T temp = a; + a = b; + b = temp; } + } // namespace fixedmath::inline v2::detail diff --git a/fixed_lib/include/fixedmath/detail/type_traits.h b/fixed_lib/include/fixedmath/detail/type_traits.h index 4b8714e..4777ba0 100644 --- a/fixed_lib/include/fixedmath/detail/type_traits.h +++ b/fixed_lib/include/fixedmath/detail/type_traits.h @@ -1,82 +1,111 @@ +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + #pragma once + #include +#include #include #include #include #include "utility_cxx20.h" -namespace fixedmath +namespace fixedmath::inline v2 + { +using fixed_internal = int64_t; +using fixed_internal_unsigned = uint64_t; + +struct fix_carrier_t; +struct fixed_t; + + } // namespace fixedmath::inline v2 + +namespace fixedmath::typetraits { - using fixed_internal = int64_t; - using fixed_internal_unsigned = uint64_t; - - struct fix_carrier_t; - struct fixed_t; - - } -namespace fixedmath::detail +// clang-format off +template struct signed_type_by_size { }; +// template<> struct signed_type_by_size<1> { using type = int8_t; }; +template<> struct signed_type_by_size<2> { using type = int16_t; }; +template<> struct signed_type_by_size<4> { using type = int32_t; }; +template<> struct signed_type_by_size<8> { using type = int64_t; }; +template<> struct signed_type_by_size<16>{ using type = int64_t; }; + +// clang-format on + +template +using signed_type_by_size_t = typename signed_type_by_size::type; + +template +using promote_to_signed_t = signed_type_by_size_t<(sizeof(T) << 1)>; + +template +inline constexpr bool is_integral_v = std::is_integral_v; + +template +inline constexpr bool is_fixed_point_v = std::is_same_v; + +template +inline constexpr bool is_signed_v = std::is_signed_v || is_fixed_point_v; + +template +inline constexpr bool is_unsigned_v = std::is_unsigned_v; + +template +inline constexpr bool is_floating_point_v = std::is_floating_point_v || is_fixed_point_v; + +template +inline constexpr bool is_arithmetic_v = is_integral_v || is_floating_point_v; + +template +inline constexpr bool is_arithmetic_and_not_fixed_v = is_arithmetic_v && (!is_fixed_point_v); + +template +inline constexpr bool is_floating_point_and_not_fixed_v = std::is_floating_point_v; + +template +inline constexpr bool is_arithmetic_and_one_is_fixed_v + = is_arithmetic_v && is_arithmetic_v && (is_fixed_point_v || is_fixed_point_v); + +template +inline constexpr bool one_of_is_double_v = std::is_same_v || std::is_same_v; + } // namespace fixedmath::typetraits + +namespace fixedmath::inline v2::concepts + { +using std::integral; +template +concept internal_unsigned = std::same_as; + +template +concept internal = std::same_as; + +template +concept fixed_point = typetraits::is_fixed_point_v; + +template +concept floating_point = typetraits::is_floating_point_v; + +template +concept arithmetic = typetraits::is_arithmetic_v; + +template +concept arithmetic_and_not_fixed = typetraits::is_arithmetic_and_not_fixed_v; + +template +concept floating_point_and_not_fixed = typetraits::is_floating_point_and_not_fixed_v; + +template +concept arithmetic_and_one_is_fixed = typetraits::is_arithmetic_and_one_is_fixed_v; + +template +concept one_of_is_double = typetraits::one_of_is_double_v; + + } // namespace fixedmath::inline v2::concepts + +namespace fixedmath::inline v2::detail { - template - struct signed_type_by_size {}; - - template<> - struct signed_type_by_size<1> { using type = int8_t; }; - - template<> - struct signed_type_by_size<2> { using type = int16_t; }; - - template<> - struct signed_type_by_size<4> { using type = int32_t; }; - - template<> - struct signed_type_by_size<8> { using type = int64_t; }; - - template<> - struct signed_type_by_size<16> { using type = int64_t; }; - - // concepts - template - inline constexpr bool is_signed_v = std::numeric_limits::is_signed; - - template - inline constexpr bool is_unsigned_v = !std::numeric_limits::is_signed; - - template - inline constexpr bool is_fixed_v = std::is_same_v; - - template - inline constexpr bool is_double_v = std::is_same_v; - - template - inline constexpr bool is_integral_v = std::is_integral_v; - - template - inline constexpr bool is_floating_point_v = std::is_floating_point_v - || is_fixed_v; - - template - inline constexpr bool is_arithmetic_v = - is_integral_v - || is_floating_point_v; - - template - inline constexpr bool is_arithmetic_and_not_fixed_v = - is_arithmetic_v && (!is_fixed_v); - - template - inline constexpr bool is_floating_point_and_not_fixed_v = - is_floating_point_v && (!is_fixed_v); - - template - inline constexpr bool arithmetic_and_one_is_fixed_v = - is_arithmetic_v && - is_arithmetic_v && - ( is_fixed_v || is_fixed_v ); - - template - inline constexpr bool one_of_is_double_v = is_double_v || is_double_v; - - using limits_ = std::numeric_limits; - using flimits_ = std::numeric_limits; - using dlimits_ = std::numeric_limits; - } +using limits_ = std::numeric_limits; +using flimits_ = std::numeric_limits; +using dlimits_ = std::numeric_limits; + } // namespace fixedmath::inline v2::detail diff --git a/fixed_lib/include/fixedmath/detail/utility_cxx20.h b/fixed_lib/include/fixedmath/detail/utility_cxx20.h index af6f888..ba2c332 100644 --- a/fixed_lib/include/fixedmath/detail/utility_cxx20.h +++ b/fixed_lib/include/fixedmath/detail/utility_cxx20.h @@ -1,24 +1,7 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + #pragma once #if !defined(SMALL_VECTORS_CXX_UTILITY) @@ -29,309 +12,30 @@ #include #include #include -#if __cplusplus > 201703L #include #include -#endif -// on linux depending on system build c++ standard libc++ version has various test macros undefined even for pure constexpr inline functions .. -#if defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 20 - #if !defined(__cpp_lib_bitops) - #define cpp_lib_bitops 201907L - #endif -#endif namespace cxx20 -{ -#if defined(__cpp_lib_integer_comparison_functions) - using std::cmp_equal; - using std::cmp_not_equal; - using std::cmp_less; - using std::cmp_greater; - using std::cmp_less_equal; - using std::cmp_greater_equal; -#else -#if !defined(integer_comparison_functions_defiend) -#define integer_comparison_functions_defiend - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_equal( T t, U u ) noexcept - { - using UT = typename std::make_unsigned::type; - using UU = typename std::make_unsigned::type; - if constexpr (std::is_signed::value == std::is_signed::value) - return t == u; - else if constexpr (std::is_signed::value) - return t < 0 ? false : static_cast(t) == u; - else - return u < 0 ? false : t == static_cast(u); - } - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_not_equal( T t, U u ) noexcept { return !cmp_equal(t, u); } - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_less( T t, U u ) noexcept - { - using UT = typename std::make_unsigned::type; - using UU = typename std::make_unsigned::type; - if constexpr (std::is_signed::value == std::is_signed::value ) - return t < u; - else if constexpr (std::is_signed::value) - return t < 0 ? true : static_cast(t) < u; - else - return u < 0 ? false : t < static_cast(u); - } - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_greater( T t, U u ) noexcept { return cmp_less(u, t); } - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_less_equal( T t, U u ) noexcept { return !cmp_greater(t, u); } - - ///\brief Compare the values. negative signed integers always compare less than (and not equal to) unsigned integers: the comparison is safe against lossy integer conversion. - template< class T, class U > - constexpr bool cmp_greater_equal( T t, U u ) noexcept { return !cmp_less(t, u); } -#endif // integer_comparison_functions_defiend -#endif // __cpp_lib_integer_comparison_functions - -#if defined(__cpp_lib_bitops) || defined(cpp_lib_bitops) - using std::countr_zero; - using std::countl_zero; -#else - template - constexpr int countl_zero(T value ) noexcept - { - static_assert(std::is_unsigned_v); - static_assert(std::is_integral::value && sizeof(T) <= 8); -#if defined(_MSC_VER) - //msvc c++17 naive loop implementation - return std::_Countl_zero_fallback(value); -#else - constexpr auto number_digits { std::numeric_limits::digits }; - - if (value == 0) - return number_digits; - else - { - if constexpr (sizeof(T) < 4) - { - int lz{ __builtin_clz(value) }; - return lz - 8 * (sizeof(int) - sizeof(T)); - } - else if constexpr (sizeof(T) == 4) - return __builtin_clz(value); - else if constexpr (sizeof(T) == 8) - { - if constexpr (sizeof(long) == 4) - return __builtin_clzll(value); - else - return __builtin_clzl(value); - } - } -#endif - } - - static_assert( countl_zero(uint8_t(1)) == 8 - 1 ); - static_assert( countl_zero(uint16_t(1)) == 16 - 1 ); - static_assert(countl_zero(uint32_t{ 1 }) == 32 - 1); - static_assert( countl_zero(uint32_t{ 2 }) == 32 - 2 ); - static_assert( countl_zero(uint32_t{ 4 }) == 32 - 3 ); - static_assert( countl_zero(uint64_t(4)) == 64 - 3 ); - - - template - constexpr int countr_zero(T value ) noexcept - { - static_assert(std::is_unsigned_v); - static_assert(std::is_integral::value && sizeof(T) <= 8); -#if defined(_MSC_VER) - return std::_Countr_zero(value); -#else - static_assert(std::is_integral::value && sizeof(T)<=8); - - constexpr auto number_digits { std::numeric_limits::digits }; - - if (value == 0) - return number_digits; - else - { - if constexpr( sizeof(T) < 4 ) - { - int lz{ __builtin_ctz( value ) }; - return lz - 8 * (sizeof(int) - sizeof(T)); - } - else if constexpr( sizeof(T) == 4 ) - return __builtin_ctz( value ); - else if constexpr( sizeof(T) == 8 ) - { - if constexpr( sizeof(long) == 4 ) - return __builtin_ctz( value ); - else - return __builtin_ctz( value ); - } - } -#endif - } -#endif //__cpp_lib_bitops - -#if defined(__cpp_lib_bit_cast) - using std::bit_cast; -#else //defined(__cpp_lib_bit_cast) -#if __has_builtin(__builtin_bit_cast) - - template -#if __cplusplus > 201703L - requires requires(To, From) - { - sizeof(To) == sizeof(From); - requires std::is_trivially_copyable_v; - requires std::is_trivially_copyable_v; - } -#endif - constexpr To bit_cast( From const & src) noexcept - { -#if __cplusplus <= 201703L - static_assert(std::is_trivially_copyable_v); - static_assert(std::is_trivially_copyable_v); -#endif - return __builtin_bit_cast(To,src); - } -#endif //__has_builtin(__builtin_bit_cast) -#endif //defined(__cpp_lib_bit_cast) - -#if defined(__cpp_lib_assume_aligned) - using std::assume_aligned; -#else - template< std::size_t N, class T > - [[nodiscard]] - constexpr T* assume_aligned(T* ptr) { - #if __has_builtin(__builtin_assume_aligned) - #if __cplusplus > 201703L - if( !std::is_constant_evaluated()) - #endif - return reinterpret_cast(__builtin_assume_aligned(ptr,N)); - #if __cplusplus > 201703L - else - return ptr; - #endif - #else - return ptr; - #endif - } -#endif - } + +using std::assume_aligned; +using std::bit_cast; +using std::byteswap; +using std::countl_zero; +using std::countr_zero; + } // namespace cxx20 namespace cxx23 -{ + { #if defined(__cpp_lib_to_underlying) - using std::to_underlying; -#else - template - constexpr std::underlying_type_t to_underlying( T value ) noexcept - { return static_cast>(value); } -#endif - -#if defined(__cpp_lib_byteswap) - using std::byteswap; +using std::to_underlying; #else - // -O3 -std=c++20 - //x86_64 - // byteswap(unsigned long): # @byteswap(unsigned long) - // mov rax, rdi - // bswap rax - // ret - // byteswap(double): # @byteswap(double) - // movq rax, xmm0 - // bswap rax - // movq xmm0, rax - // ret - //aarch64 - // byteswap(unsigned long): - // fmov d0, x0 - // rev64 v0.8b, v0.8b - // umov x0, v0.d[0] - // ret - // byteswap(double): - // fmov x0, d0 - // rev x0, x0 - // fmov d0, x0 - // ret - // - namespace detail - { - template - struct swap_bytes_impl_t - { - [[gnu::always_inline]] - static inline constexpr void swap( std::byte (&l)[sz] ) noexcept - { - swap_bytes_impl_t::swap( l ); - std::swap( l[ix], l[sz-1-ix]); - } - }; - template - struct swap_bytes_impl_t - { - [[gnu::always_inline]] - static inline constexpr void swap( std::byte (&l)[sz] ) noexcept - { - std::swap( l[0], l[sz-1]); - } - }; - - template - [[gnu::always_inline]] - inline constexpr void swap_bytes(std::byte (&l)[sz]) noexcept - { - swap_bytes_impl_t::swap(l); - } - -#if __cplusplus > 201703L - template - concept trivially_copyable = std::is_trivially_copyable_v; - - template - concept even_value_size = (sizeof(T) & 1) == 0; - - template - concept byte_swap_constraints = - requires( value_type ) - { - requires detail::trivially_copyable; - requires detail::even_value_size; - }; -#endif - } - -#if __cplusplus > 201703L - template -#else - template -#endif - [[gnu::always_inline,gnu::const]] - constexpr value_type byteswap( value_type big_or_le ) noexcept - { -#if __cplusplus <= 201703L - static_assert(std::is_trivially_copyable_v); - static_assert((sizeof(value_type) & 1) == 0); -#endif - struct store_type - { - alignas(alignof(value_type)) - std::byte data[sizeof(value_type)]; - }; - - store_type raw { cxx20::bit_cast(big_or_le) }; - detail::swap_bytes(raw.data); - return cxx20::bit_cast(raw); - } +template +constexpr std::underlying_type_t to_underlying(T value) noexcept + { + return static_cast>(value); + } #endif -} -#endif //SMALL_VECTORS_CXX_UTILITY + } // namespace cxx23 +#endif // SMALL_VECTORS_CXX_UTILITY diff --git a/fixed_lib/include/fixedmath/fixed_math.hpp b/fixed_lib/include/fixedmath/fixed_math.hpp index 0bc2d69..4dd6056 100644 --- a/fixed_lib/include/fixedmath/fixed_math.hpp +++ b/fixed_lib/include/fixedmath/fixed_math.hpp @@ -1,203 +1,215 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math #pragma once -#if defined(_MSC_VER) -__pragma( warning (push) ) -__pragma( warning(disable : 5030) ) //unknown attribute -__pragma( warning(disable : 4554) ) //false positive about order of execution >> - -#endif #include "types.h" #include "limits.h" #include "math.h" -#if defined(_MSC_VER) -__pragma( warning (pop) ) -#endif - -namespace fixedmath -{ - //representated fractions in fixed and any of sum of them - // 1 1<<0 0.0000152587890625 - // 2 1<<1 0.0000305175781250 - // 4 1<<2 0.0000610351562500 - // 8 1<<3 0.0001220703125000 - // 16 1<<4 0.0002441406250000 - // 32 1<<5 0.0004882812500000 - // 64 1<<6 0.0009765625000000 - // 128 1<<7 0.0019531250000000 - // 256 1<<8 0.0039062500000000 - // 512 1<<9 0.0078125000000000 - // 1024 1<<10 0.0156250000000000 - // 2048 1<<11 0.0312500000000000 - // 4096 1<<12 0.0625000000000000 - // 8192 1<<13 0.1250000000000000 - // 16384 1<<14 0.2500000000000000 - // 32768 1<<15 0.5000000000000000 - - ///\brief main type used in calculations - struct fixed_t; - - ///\brief fixed number negation - constexpr fixed_t operator -( fixed_t l ) noexcept; - - ///\brief converts any floating point or integral value into fixed point - template - constexpr fixed_t arithmetic_to_fixed( arithmethic_type value ) noexcept; - - /// implicit convertion to double from fixed - //constexpr fixed_t::operator double() const noexcept - - /// explicit convertion to integral or float - //template - //constexpr fixed_t::operator arithmethic_type() const noexcept - - ///\brief converts fixed_t into any floating point or integral type - template - constexpr arithmethic_type fixed_to_arithmetic( fixed_t value ) noexcept; - - ///\return absolute value of fixed_t - constexpr fixed_t abs( fixed_t value ) noexcept; - - ///\brief tests for NaN fixed - ///returns true if \param value is NaN - constexpr bool isnan( fixed_t value ) noexcept; - - constexpr fixed_t ceil( fixed_t value ) noexcept; - - constexpr fixed_t floor( fixed_t value ) noexcept; - - ///\brief converts angle 0 - 360 to radians. - template - constexpr fixed_t angle_to_radians( integral_type angle ) noexcept; - - ///\brief shifts right value of \param l by \param r digits - constexpr fixed_t operator >> ( fixed_t l, int r ) noexcept; - - ///\brief shifts left value of \param l by \param r digits - constexpr fixed_t operator << ( fixed_t l, int r ) noexcept; - - ///\brief returns result of addition of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto fixed_addition( supported_type1 lh, supported_type2 rh) noexcept; - - ///\brief returns result of addition of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto operator + ( supported_type1 l, supported_type2 r ) noexcept; - - template - constexpr fixed_t & operator += ( fixed_t & l, supported_type r ) noexcept; - - ///\brief returns result of substraction of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto fixed_substract( supported_type1 lh, supported_type2 rh) noexcept; - - template - inline fixed_t & operator -= ( fixed_t & lh, supported_type rh ) noexcept; - - ///\brief returns result of substraction of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto operator - ( supported_type1 l, supported_type2 r ) noexcept; - - ///\brief returns result of multiplication of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto fixed_multiply( supported_type1 lh, supported_type2 rh) noexcept; - - template - constexpr fixed_t & operator *= ( fixed_t & lh, supported_type rh ) noexcept; - - ///\brief returns result of multiplication of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto operator * ( supported_type1 lh, supported_type2 rh ) noexcept; - - ///\brief returns result of division of two arguments - ///\notice when one of arguments is double precission operation is promoted to double - ///\returns value of type fixed_t or double - template - constexpr auto fixed_division(supported_type1 lh, supported_type2 rh ) noexcept; - - template - constexpr fixed_t & operator /= ( fixed_t & lh, supported_type rh ) noexcept; - - template - constexpr auto operator / ( supported_type1 lh, supported_type2 rh ) noexcept; - - //You can check if constexpr sqrt is avaiable with, for c++20 is always avaiable - //if constexpr(fixedmath::sqrt_constexpr_available) - ///\returns square root - FIXEDMATH_SQRT_CONSTEXPR fixed_t sqrt(fixed_t value) noexcept; - - FIXEDMATH_SQRT_CONSTEXPR fixed_t hypot(fixed_t lh, fixed_t rh ) noexcept; - - ///\returns sine of \param rad in radians - constexpr fixed_t sin( fixed_t rad ) noexcept; - - ///\returns cosine of value in radians - constexpr fixed_t cos( fixed_t rad ) noexcept; - - ///\returns tangent of \param rad - constexpr fixed_t tan( fixed_t rad ) noexcept; - - ///\returns arcus sine - ///\warning valid range < -1 .. 1 > - constexpr fixed_t asin( fixed_t x ) noexcept; - - ///\returns arcus sine - ///\warning valid range < -1 .. 1 > - constexpr fixed_t acos( fixed_t x ) noexcept; - - ///\returns arcus tangent of \param x - ///\warning valid range < -1 .. 1 > - constexpr fixed_t atan( fixed_t x ) noexcept; - - ///\returns arcus tangent of y/x using the signs of arguments to determine the correct quadrant. - constexpr fixed_t atan2( fixed_t y, fixed_t x ) noexcept; - - ///\returns arc tan in range 0..+/-127 where 127 represents phi/2 - constexpr fixed_t atan_index( fixed_t value ) noexcept; - - ///\returns sine of \param angle specified in degrees - template - constexpr fixed_t sin_angle(supported_type angle) noexcept; - - ///\returns cosine of \param angle specified in degrees - template - constexpr fixed_t cos_angle(supported_type angle) noexcept; - - ///\returns tangent of \param angle specified in degrees - template - constexpr fixed_t tan_angle(supported_type angle) noexcept; -} +namespace fixedmath::inline v2 + { +// representative fractions in fixed and any of sum of them +// 1 1<<0 0.0000152587890625 +// 2 1<<1 0.0000305175781250 +// 4 1<<2 0.0000610351562500 +// 8 1<<3 0.0001220703125000 +// 16 1<<4 0.0002441406250000 +// 32 1<<5 0.0004882812500000 +// 64 1<<6 0.0009765625000000 +// 128 1<<7 0.0019531250000000 +// 256 1<<8 0.0039062500000000 +// 512 1<<9 0.0078125000000000 +// 1024 1<<10 0.0156250000000000 +// 2048 1<<11 0.0312500000000000 +// 4096 1<<12 0.0625000000000000 +// 8192 1<<13 0.1250000000000000 +// 16384 1<<14 0.2500000000000000 +// 32768 1<<15 0.5000000000000000 + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator>>(std::same_as auto l, int r) noexcept -> fixed_t + { + return fobj::rshift(l, r); + } + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator<<(std::same_as auto l, int r) noexcept -> fixed_t + { + return fobj::lshift(l, r); + } + +inline auto constexpr operator&(std::same_as auto l, std::same_as auto r) noexcept -> fixed_t + { + return fobj::bit_and(l, r); + } + +[[gnu::always_inline]] +constexpr auto operator+=(fixed_t & l, concepts::arithmetic auto r) noexcept -> fixed_t & + { + l = fobj::add(l, r); + return l; + } + +///\brief returns result of addition of to arguments +///\note when one of arguments is double precission operation is promoted to double +template + requires concepts::arithmetic_and_one_is_fixed +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator+(supported_type1 l, supported_type2 r) noexcept + { + return fobj::add(l, r); + } + +[[gnu::always_inline]] +inline constexpr auto operator-=(fixed_t & lh, concepts::arithmetic auto rh) noexcept -> fixed_t & + { + lh = fobj::subtract(lh, rh); + return lh; + } + +template + requires concepts::arithmetic_and_one_is_fixed +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator-(supported_type1 lh, supported_type2 rh) noexcept + { + return fobj::subtract(lh, rh); + } + +[[gnu::always_inline]] +constexpr auto operator*=(fixed_t & lh, concepts::arithmetic auto rh) noexcept -> fixed_t & + { + lh = fobj::multiply(lh, rh); + return lh; + } + +template + requires concepts::arithmetic_and_one_is_fixed +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator*(supported_type1 lh, supported_type2 rh) noexcept + { + return fobj::multiply(lh, rh); + } + +[[gnu::always_inline]] +constexpr auto operator/=(fixed_t & lh, concepts::arithmetic auto rh) noexcept -> fixed_t & + { + lh = fobj::division(lh, rh); + return lh; + } + +template + requires concepts::arithmetic_and_one_is_fixed +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator/(supported_type1 lh, supported_type2 rh) noexcept + { + return fobj::division(lh, rh); + } + +namespace func + { + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto abs(std::same_as auto value) noexcept -> fixed_t + { + return fobj::abs(value); + } + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto isnan(std::same_as auto value) noexcept -> bool + { + return fobj::isnan(value); + } + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto ceil(std::same_as auto value) noexcept -> fixed_t + { + return fobj::ceil(value); + } + + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto floor(std::same_as auto value) noexcept -> fixed_t + { + return fobj::floor(value); + } + + template + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto angle_to_radians(integral_type angle) noexcept -> fixed_t + { + return fobj::angle_to_radians(angle); + } + + [[nodiscard]] + constexpr auto sqrt(std::same_as auto value) noexcept -> fixed_t + { + return fobj::sqrt(value); + } + + [[nodiscard]] + constexpr auto hypot(std::same_as auto lh, std::same_as auto rh) noexcept -> fixed_t + { + return fobj::hypot(lh, rh); + } + + [[nodiscard, gnu::const]] + constexpr auto sin(std::same_as auto rad) noexcept -> fixed_t + { + return fobj::sin(rad); + } + + [[nodiscard, gnu::const]] + constexpr auto cos(std::same_as auto rad) noexcept -> fixed_t + { + return fobj::cos(rad); + } + + [[nodiscard, gnu::const]] + constexpr auto tan(std::same_as auto rad) noexcept -> fixed_t + { + return fobj::tan(rad); + } + + [[nodiscard, gnu::const]] + constexpr auto atan(std::same_as auto value) noexcept -> fixed_t + { + return fobj::atan(value); + } + + [[nodiscard, gnu::const]] + constexpr auto atan2(std::same_as auto y, std::same_as auto x) noexcept -> fixed_t + { + return fobj::atan2(y, x); + } + + [[nodiscard, gnu::const]] + constexpr auto asin(std::same_as auto x) noexcept -> fixed_t + { + return fobj::asin(x); + } + + [[nodiscard, gnu::const]] + constexpr auto acos(std::same_as auto x) noexcept -> fixed_t + { + return fobj::acos(x); + } + + [[nodiscard, gnu::const]] + constexpr auto sin_angle(concepts::arithmetic auto angle) noexcept -> fixed_t + { + return fobj::sin_angle(angle); + } + + [[nodiscard, gnu::const]] + constexpr auto cos_angle(concepts::arithmetic auto angle) noexcept -> fixed_t + { + return fobj::cos_angle(angle); + } + + [[nodiscard, gnu::const]] + constexpr auto tan_angle(concepts::arithmetic auto angle) noexcept -> fixed_t + { + return fobj::tan_angle(angle); + } + } // namespace func + } // namespace fixedmath::inline v2 diff --git a/fixed_lib/include/fixedmath/iostream.h b/fixed_lib/include/fixedmath/iostream.h index c0de668..3768c84 100644 --- a/fixed_lib/include/fixedmath/iostream.h +++ b/fixed_lib/include/fixedmath/iostream.h @@ -1,38 +1,21 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math #pragma once #include "math.h" #include #include + namespace fixedmath -{ - inline std::ostream & operator << ( std::ostream & outstr, fixed_t src ) - { - if( src != std::numeric_limits::quiet_NaN() ) - outstr << std::fixed << std::setprecision( 16 ) << static_cast( src ); - else - outstr << "NaN"; - return outstr; - } -} + { +inline std::ostream & operator<<(std::ostream & outstr, fixed_t src) + { + if(src != std::numeric_limits::quiet_NaN()) + outstr << std::fixed << std::setprecision(16) << static_cast(src); + else + outstr << "NaN"; + return outstr; + } + } // namespace fixedmath diff --git a/fixed_lib/include/fixedmath/limits.h b/fixed_lib/include/fixedmath/limits.h index 8644feb..3ad1d9b 100644 --- a/fixed_lib/include/fixedmath/limits.h +++ b/fixed_lib/include/fixedmath/limits.h @@ -1,76 +1,66 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math #pragma once #include "types.h" + namespace fixedmath -{ - -} + { + } + namespace std -{ - template<> - struct numeric_limits - { - using value_type = fixedmath::fixed_t; - using fixed_internal = fixedmath::fixed_internal; - using fix_carrier_t = fixedmath::fix_carrier_t; - - static constexpr bool is_integer { false }; - static constexpr bool is_specialized { true }; - static constexpr bool is_signed { true }; - static constexpr bool is_exact{ true }; - static constexpr bool has_infinity{}; - static constexpr bool has_quiet_NaN{ true }; - static constexpr bool has_signaling_NaN{}; - static constexpr float_denorm_style has_denorm{denorm_absent}; - static constexpr bool has_denorm_loss{}; - static constexpr float_round_style round_style{round_toward_zero}; - static constexpr bool is_iec559{}; - static constexpr bool is_bounded{true}; - static constexpr bool is_modulo{}; - static constexpr int digits{16}; - static constexpr int digits10{4}; - static constexpr int max_digits10{6}; - static constexpr int radix{2}; - static constexpr bool traps{true}; - static constexpr bool tinyness_before{}; - - static constexpr value_type min() noexcept{ return fix_carrier_t{fixed_internal{1}}; }; - static constexpr value_type lowest() noexcept{ return fix_carrier_t{fixed_internal{-0x7FFFFFFFFFFFFFFEll}}; }; - static constexpr value_type max() noexcept { return fix_carrier_t{fixed_internal{0x7FFFFFFFFFFFFFFEll}}; } - static constexpr value_type one() noexcept { return fix_carrier_t{fixed_internal{65536}}; } - static constexpr value_type epsilon() noexcept { return fix_carrier_t{fixed_internal{1}}; } - static constexpr value_type round_error() noexcept { return fix_carrier_t{fixed_internal{1}}; } - static constexpr value_type quiet_NaN() noexcept { return fix_carrier_t{fixed_internal{0x7FFFFFFFFFFFFFFFll}}; } - - static constexpr int32_t max_integral() noexcept { return 2147483647; } - static constexpr int32_t min_integral() noexcept{ return -2147483647; }; - }; - -} + { +template<> +struct numeric_limits + { + using value_type = fixedmath::fixed_t; + using fixed_internal = fixedmath::fixed_internal; + using fix_carrier_t = fixedmath::fix_carrier_t; + + static constexpr bool is_integer{false}; + static constexpr bool is_specialized{true}; + static constexpr bool is_signed{true}; + static constexpr bool is_exact{true}; + static constexpr bool has_infinity{}; + static constexpr bool has_quiet_NaN{true}; + static constexpr bool has_signaling_NaN{}; + static constexpr bool has_denorm_loss{}; + static constexpr float_round_style round_style{round_toward_zero}; + static constexpr bool is_iec559{}; + static constexpr bool is_bounded{true}; + static constexpr bool is_modulo{}; + static constexpr int digits{16}; + static constexpr int digits10{4}; + static constexpr int max_digits10{6}; + static constexpr int radix{2}; + static constexpr bool traps{true}; + static constexpr bool tinyness_before{}; + + static consteval value_type min() noexcept { return fix_carrier_t{fixed_internal{1}}; } + + static consteval value_type lowest() noexcept { return fix_carrier_t{fixed_internal{-0x7FFFFFFFFFFFFFFEll}}; } + + static consteval value_type max() noexcept { return fix_carrier_t{fixed_internal{0x7FFFFFFFFFFFFFFEll}}; } + + static consteval value_type one() noexcept { return fix_carrier_t{fixed_internal{65536}}; } + + static consteval value_type epsilon() noexcept { return fix_carrier_t{fixed_internal{1}}; } + + static consteval value_type round_error() noexcept { return fix_carrier_t{fixed_internal{1}}; } + + static consteval value_type quiet_NaN() noexcept { return fix_carrier_t{fixed_internal{0x7FFFFFFFFFFFFFFFll}}; } + + static consteval int32_t max_integral() noexcept { return 2147483647; } + + static consteval int32_t min_integral() noexcept { return -2147483647; } + }; + + } // namespace std + namespace fixedmath -{ -inline constexpr fixed_t quiet_NaN_result() noexcept { return std::numeric_limits::quiet_NaN(); } -} + { +inline consteval auto quiet_NaN_result() -> fixed_t { return std::numeric_limits::quiet_NaN(); } + } // namespace fixedmath diff --git a/fixed_lib/include/fixedmath/math.h b/fixed_lib/include/fixedmath/math.h index d2bb043..c95b84d 100644 --- a/fixed_lib/include/fixedmath/math.h +++ b/fixed_lib/include/fixedmath/math.h @@ -1,951 +1,713 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math #pragma once + #include -#include "types.h" -#include "limits.h" -#include "numbers.h" -#include "detail/common.h" +#include "core_ops.h" #include -namespace fixedmath -{ - template> - > - constexpr fixed_t arithmetic_to_fixed( arithmethic_type value ) noexcept; - - template - constexpr fixed_t::fixed_t( arithmethic_type const & value ) noexcept - : v{ arithmetic_to_fixed(value).v } - { - static_assert( detail::is_arithmetic_and_not_fixed_v ); - } - - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t operator -( fixed_t l ) noexcept { return fix_carrier_t{-l.v}; } - - //------------------------------------------------------------------------------------------------------ - ///\brief Converts an integral to a fixed_t - /// \returns fixed on success or NaN if source value is out of range - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t integral_to_fixed(integral_type value) noexcept - { - if( fixed_likely(cxx20::cmp_less_equal(value, detail::limits_::max_integral()) && - cxx20::cmp_greater_equal(value, detail::limits_::min_integral()) ) ) - { - if constexpr ( detail::is_unsigned_v ) - return fix_carrier_t{detail::unsigned_shift_left_unsigned<16>(value)}; - else - return fix_carrier_t{detail::unsigned_shift_left_signed<16>(value)}; - } - return quiet_NaN_result(); - } - - constexpr fixed_t operator ""_fix ( unsigned long long value ) noexcept - { - return integral_to_fixed( static_cast( value )); - } - - //------------------------------------------------------------------------------------------------------ - /// \brief Converts a floating point value to a fixed_t - /// \returns fixed on success or NaN if source value is out of range - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t floating_point_to_fixed (floating_point_type value) noexcept - { - using ft = floating_point_type; - - if( fixed_likely( value < double(detail::limits_::max_integral()) && - value > double(detail::limits_::min_integral())) ) - return fix_carrier_t( static_cast(value * 65536 + (value < ft(0) ? ft(-0.5) : ft(0.5) )) ); +namespace fixedmath::inline v2::detail + { - return quiet_NaN_result(); - } - - constexpr fixed_t operator ""_fix ( long double value ) noexcept +template +[[nodiscard, gnu::const, gnu::always_inline]] +inline constexpr double promote_to_double(supported_type value) noexcept + { + if constexpr(std::same_as) + return value; + else + return fixed_to_arithmetic(value); + } + +template +[[nodiscard, gnu::const, gnu::always_inline]] +inline constexpr fixed_t promote_to_fixed(supported_type value) noexcept + { + if constexpr(std::same_as) + return value; + else + return arithmetic_to_fixed(value); + } + } // namespace fixedmath::inline v2::detail + +namespace fixedmath::inline v2::fobj + { +namespace detail + { + using namespace fixedmath::detail; + } + +//------------------------------------------------------------------------------------------------------ +struct abs_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto value) noexcept -> fixed_t { - return floating_point_to_fixed( static_cast( value )); + // cmp x0, #0 // =0 + // cneg x0, x0, mi + return as_fixed(value.v > 0 ? value.v : -value.v); } + }; - //------------------------------------------------------------------------------------------------------ - ///\brief Converts an fixed_t point value to an integral. - template>> - [[ gnu::const, gnu::always_inline ]] - constexpr integral_type fixed_to_integral ( fixed_t value ) noexcept - { - fixed_internal tmp{ ( value.v >> 16 ) /*+ (( value.v & 0x8000) >> 15)*/ }; - using al = std::numeric_limits; - if( cxx20::cmp_greater_equal( tmp, al::min() ) && cxx20::cmp_less_equal( tmp, al::max() ) ) - return static_cast( tmp ); - return std::numeric_limits::quiet_NaN(); - } +inline constexpr abs_t abs; + +//------------------------------------------------------------------------------------------------------ - //------------------------------------------------------------------------------------------------------ - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr floating_point_type fixed_to_floating_point( fixed_t value ) noexcept +struct isnan_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto value) noexcept -> bool { - using ft = floating_point_type; - return static_cast(value.v) / ft(65536); + return abs(value) == quiet_NaN_result(); } + }; - //------------------------------------------------------------------------------------------------------ +inline constexpr isnan_t isnan; - template> - > - constexpr arithmethic_type fixed_to_arithmetic( fixed_t value ) noexcept - { - if constexpr ( detail::is_integral_v ) - return fixed_to_integral( value ); - else - return fixed_to_floating_point( value ); - } - - template - [[ nodiscard ]] - constexpr fixed_t::operator arithmethic_type() const noexcept - { - return fixed_to_arithmetic( *this ); - } - //------------------------------------------------------------------------------------------------------ - template> - > - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t make_fixed( arithmethic_type value ) noexcept - { - if constexpr( detail::is_floating_point_v ) - return floating_point_to_fixed( value ); - else - return integral_to_fixed(value); - } - - template - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t arithmetic_to_fixed( arithmethic_type value ) noexcept - { return make_fixed( value ); } - //------------------------------------------------------------------------------------------------------ - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t abs( fixed_t value ) noexcept - { - // cmp x0, #0 // =0 - // cneg x0, x0, mi - return as_fixed(value.v > 0 ? value.v : -value.v); - } - //------------------------------------------------------------------------------------------------------ - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool isnan( fixed_t value ) noexcept - { - return abs( value ) == quiet_NaN_result(); - } +//------------------------------------------------------------------------------------------------------ - //------------------------------------------------------------------------------------------------------ - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t operator >> ( fixed_t l, int r ) noexcept - { - if( fixed_likely(r >= 0 ) ) +struct rshift_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto l, int r) noexcept -> fixed_t + { + if(r >= 0) [[likely]] return fix_carrier_t{l.v >> r}; return quiet_NaN_result(); } - - //------------------------------------------------------------------------------------------------------ - - [[ gnu::const ]] - constexpr fixed_t operator << ( fixed_t l, int r ) noexcept - { + }; + +inline constexpr rshift_t rshift; + +//------------------------------------------------------------------------------------------------------ + +struct lshift_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto l, int r) noexcept -> fixed_t + { using unsigned_fix_internal = std::make_unsigned::type; - - if( fixed_likely( r >= 0 ) ) - return - fix_carrier_t{fixed_internal( - (( ( unsigned_fix_internal(l.v) ) << r ) & unsigned_fix_internal(0x7fffffffffffffffull)) //lsh unsigned value and clear overwritten sign bit - | ( (1ull<<63) & unsigned_fix_internal(l.v) ) //transfer source sign bit - )}; + + if(r >= 0) [[likely]] + return fix_carrier_t{fixed_internal( + (((unsigned_fix_internal(l.v)) << r) & unsigned_fix_internal(0x7fffffffffffffffull) + ) // lsh unsigned value and clear overwritten sign bit + | ((1ull << 63) & unsigned_fix_internal(l.v)) // transfer source sign bit + )}; return quiet_NaN_result(); } - //------------------------------------------------------------------------------------------------------ - - [[ gnu::const, gnu::always_inline ]] - inline fixed_t constexpr - operator & ( fixed_t l, fixed_t r ) noexcept { return fix_carrier_t{l.v & r.v}; } - - //------------------------------------------------------------------------------------------------------ - namespace detail + }; + +inline constexpr lshift_t lshift; + +//------------------------------------------------------------------------------------------------------ + +struct bit_and_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + inline auto constexpr operator()(std::same_as auto l, std::same_as auto r) noexcept -> fixed_t { - ///\brief Returns the sum of two fixed_t point values. - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_additioni(fixed_t lh, fixed_t rh ) noexcept - { - fixed_t result { fix_carrier_t{lh.v + rh.v} }; - if( fixed_unlikely(result >= 0_fix) ) - { - if( fixed_unlikely((lh < 0_fix ) && ( rh < 0_fix)) ) - return -quiet_NaN_result(); - } - else - { - if( fixed_unlikely((lh > 0_fix ) && ( rh > 0_fix )) ) - return quiet_NaN_result(); - } - return result; - } - - template - [[ gnu::const, gnu::always_inline ]] - constexpr double promote_to_double( supported_type value ) noexcept - { - if constexpr( is_double_v ) - return value; - else - return fixed_to_floating_point( value ); - } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t promote_to_fixed( supported_type value ) noexcept - { - if constexpr( detail::is_fixed_v ) - return value; - else - return arithmetic_to_fixed( value ); - } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr double promoted_double_addition( supported_type1 lh, supported_type2 rh ) noexcept + return fix_carrier_t{l.v & r.v}; + } + }; + +inline constexpr bit_and_t bit_and; + +//------------------------------------------------------------------------------------------------------ + +namespace detail + { + ///\brief Returns the sum of two fixed_t point values. + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_additioni(std::same_as auto lh, std::same_as auto rh) noexcept -> fixed_t + { + fixed_t result{fix_carrier_t{lh.v + rh.v}}; + if(result >= 0_fix) [[unlikely]] { - return promote_to_double(lh) + promote_to_double( rh ); + if((lh < 0_fix) && (rh < 0_fix)) [[unlikely]] + return -quiet_NaN_result(); } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t promoted_fixed_addition( supported_type1 lh, supported_type2 rh ) noexcept + else { - return fixed_additioni(promote_to_fixed(lh), promote_to_fixed( rh ) ); + if((lh > 0_fix) && (rh > 0_fix)) [[unlikely]] + return quiet_NaN_result(); } + return result; } - + + } // namespace detail + +struct add_t + { ///\brief returns result of addition of to arguments - ///\notice when one of arguments is double precission operation is promoted to double - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto fixed_addition( supported_type1 lh, supported_type2 rh) noexcept - { - if constexpr( detail::one_of_is_double_v ) - return detail::promoted_double_addition( rh, lh ); + ///\note when one of arguments is double precision operation is promoted to double + template + requires concepts::arithmetic_and_one_is_fixed + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(supported_type1 lh, supported_type2 rh) noexcept + { + if constexpr(typetraits::one_of_is_double_v) + return detail::promote_to_double(rh) + detail::promote_to_double(lh); else - return detail::promoted_fixed_addition( lh, rh ); - } - - template> - > - [[ gnu::always_inline ]] - constexpr fixed_t & operator += ( fixed_t & l, supported_type r ) noexcept - { - l = fixed_addition(l,r); - return l; + return detail::fixed_additioni(detail::promote_to_fixed(lh), detail::promote_to_fixed(rh)); } + }; - ///\brief returns result of addition of to arguments - ///\notice when one of arguments is double precission operation is promoted to double - template>> - [[ gnu::const, gnu::always_inline ]] - constexpr auto operator + ( supported_type1 l, supported_type2 r ) noexcept { return fixed_addition(l,r); } - - //------------------------------------------------------------------------------------------------------ - namespace detail - { - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_substracti(fixed_t lh, fixed_t rh) noexcept - { - fixed_t result { fix_carrier_t{lh.v - rh.v}}; +inline constexpr add_t add; - if(fixed_unlikely(result >= 0_fix)) - { - if( fixed_unlikely((lh < 0_fix) && (rh > 0_fix)) ) - return -quiet_NaN_result(); - } - else - { - if( fixed_unlikely((lh > 0_fix) && (rh < 0_fix)) ) - return quiet_NaN_result(); - } +//------------------------------------------------------------------------------------------------------ - return result; - } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr double promoted_double_substract( supported_type1 lh, supported_type2 rh ) noexcept +namespace detail + { + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_subtracti(std::same_as auto lh, std::same_as auto rh) noexcept -> fixed_t + { + fixed_t result{fix_carrier_t{lh.v - rh.v}}; + + if(result >= 0_fix) { - return promote_to_double(lh) - promote_to_double( rh ); + if((lh < 0_fix) && (rh > 0_fix)) [[unlikely]] + return -quiet_NaN_result(); } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t promoted_fixed_substract( supported_type1 lh, supported_type2 rh ) noexcept + else { - return fixed_substracti(promote_to_fixed(lh), promote_to_fixed( rh ) ); + if((lh > 0_fix) && (rh < 0_fix)) [[unlikely]] + return quiet_NaN_result(); } + + return result; } - + + } // namespace detail + +struct subtract_t + { ///\brief returns result of addition of to arguments - ///\notice when one of arguments is double precission operation is promoted to double - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto fixed_substract( supported_type1 lh, supported_type2 rh) noexcept - { - if constexpr( detail::is_double_v || detail::is_double_v ) - return detail::promoted_double_substract( lh, rh ); + ///\note when one of arguments is double precission operation is promoted to double + template + requires concepts::arithmetic_and_one_is_fixed + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(supported_type1 lh, supported_type2 rh) noexcept + { + if constexpr(typetraits::one_of_is_double_v) + return detail::promote_to_double(lh) - detail::promote_to_double(rh); else - return detail::promoted_fixed_substract( lh, rh ); + return detail::fixed_subtracti(detail::promote_to_fixed(lh), detail::promote_to_fixed(rh)); } - - template> - > - [[ gnu::always_inline ]] - inline fixed_t & operator -= ( fixed_t & lh, supported_type rh ) noexcept - { - lh = fixed_substract(lh,rh); - return lh; - } - - //3 overloads to avoid problem with vector implicit convertion - //see https://www.reddit.com/r/cpp_questions/comments/l2cbqe/bug_in_libstdc_or_not_question_about_static/ - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto operator - ( supported_type1 lh, supported_type2 rh ) noexcept + }; + +inline constexpr subtract_t subtract; + +//------------------------------------------------------------------------------------------------------ +/// \brief Returns the product of two fixed_t point values. + +namespace detail + { + constexpr bool check_multiply_result(std::same_as auto result) { - return fixed_substract(lh,rh); + return ( + result < as_fixed(fixed_internal(0x7fffffffffff0000ll)) + || result > as_fixed(fixed_internal(-0x7fffffffffff0000ll)) + ); } - - //------------------------------------------------------------------------------------------------------ - /// \brief Returns the product of two fixed_t point values. - namespace detail + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_multiplyi(std::same_as auto lh, std::same_as auto rh) noexcept -> fixed_t { - constexpr bool check_multiply_result( fixed_t result ) - { - return (result < as_fixed( fixed_internal(0x7fffffffffff0000ll) ) - || result > as_fixed( fixed_internal(-0x7fffffffffff0000ll)) ); - } - - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_multiplyi (fixed_t lh, fixed_t rh) noexcept - { - fixed_t result { fix_carrier_t{ lh.v * rh.v }}; + fixed_t result{fix_carrier_t{lh.v * rh.v}}; - if( fixed_likely( check_multiply_result(result)) ) - return fix_carrier_t{ result.v >> 16 }; - - return quiet_NaN_result(); - } - //double will promote fixed - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr double promoted_double_multiply( supported_type1 lh, supported_type2 rh ) noexcept - { - return promote_to_double(lh) * promote_to_double( rh ); - } - - //floats will be promoted - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t promoted_fixed_multiply( supported_type1 lh, supported_type2 rh ) noexcept - { - return fixed_multiplyi(promote_to_fixed(lh), promote_to_fixed( rh ) ); - } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_multiply_scalar (fixed_t lh, integral_type rh) noexcept - { - fixed_t result { fix_carrier_t{ lh.v * promote_type_to_signed(rh) }}; + if(check_multiply_result(result)) [[likely]] + return fix_carrier_t{result.v >> 16}; - if( fixed_likely( check_multiply_result(result)) ) - return result; - return quiet_NaN_result(); - } - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_multiply_scalar (integral_type lh, fixed_t rh ) noexcept - { return fixed_multiply_scalar(rh,lh); } + return quiet_NaN_result(); } - - ///\brief returns result of addition of to arguments - ///\notice when one of arguments is double precission operation is promoted to double - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto fixed_multiply( supported_type1 lh, supported_type2 rh) noexcept + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_multiply_scalar(std::same_as auto lh, std::integral auto rh) noexcept -> fixed_t { - if constexpr( detail::is_double_v || detail::is_double_v ) - return detail::promoted_double_multiply( lh, rh ); - else if constexpr( detail::is_integral_v || detail::is_integral_v ) - return detail::fixed_multiply_scalar( lh, rh); - else - return detail::promoted_fixed_multiply( lh, rh ); + fixed_t result{fix_carrier_t{lh.v * promote_type_to_signed(rh)}}; + + if(check_multiply_result(result)) [[likely]] + return result; + return quiet_NaN_result(); } - - template> - > - [[ gnu::always_inline ]] - constexpr fixed_t & operator *= ( fixed_t & lh, supported_type rh ) noexcept + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_multiply_scalar(std::integral auto lh, std::same_as auto rh) noexcept -> fixed_t { - lh = fixed_multiply(lh,rh); - return lh; + return fixed_multiply_scalar(rh, lh); } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto operator * ( supported_type1 lh, supported_type2 rh ) noexcept - { - return fixed_multiply(lh,rh); + } // namespace detail + +struct multiply_t + { + ///\brief returns result of addition of to arguments + ///\note when one of arguments is double precission operation is promoted to double + template + requires concepts::arithmetic_and_one_is_fixed + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(supported_type1 lh, supported_type2 rh) noexcept + { + if constexpr(typetraits::one_of_is_double_v) + return detail::promote_to_double(lh) * detail::promote_to_double(rh); + else if constexpr(std::is_integral_v || std::is_integral_v) + return detail::fixed_multiply_scalar(lh, rh); + else + return detail::fixed_multiplyi(detail::promote_to_fixed(lh), detail::promote_to_fixed(rh)); } + }; + +inline constexpr multiply_t multiply; + +//------------------------------------------------------------------------------------------------------ - //------------------------------------------------------------------------------------------------------ - namespace detail +namespace detail + { + constexpr bool check_division_result(std::same_as auto result) { - constexpr bool check_division_result( fixed_t result ) - { - return result <= as_fixed( fixed_internal(0x7fffffffffffll) ) - && result >= as_fixed( fixed_internal(-0x7fffffffffffll) ); - } + return result <= as_fixed(fixed_internal(0x7fffffffffffll)) + && result >= as_fixed(fixed_internal(-0x7fffffffffffll)); + } - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_divisionf( fixed_t x, fixed_t y) noexcept + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_divisionf(std::same_as auto x, std::same_as auto y) noexcept -> fixed_t + { + if(y.v != 0) [[likely]] { - if( fixed_likely(y.v != 0) ) - { - fixed_t result { as_fixed( (x << 16).v / y.v ) }; -// if( fixed_likely( check_division_result(result)) ) - return result; - } - return quiet_NaN_result(); //abort ? + fixed_t result{as_fixed((x << 16).v / y.v)}; + return result; } + return quiet_NaN_result(); // abort ? + } - //floats will be promoted - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t promoted_fixed_division( supported_type1 lh, supported_type2 rh ) noexcept - { - //promote only one of arguments, doesnt allow using this function for ppromothing twu not fixed types - return fixed_divisionf(promote_to_fixed(lh), promote_to_fixed( rh ) ); - } - - //double will promote fixed - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr double promoted_double_division( supported_type1 lh, supported_type2 rh ) noexcept - { - //promote only one of arguments, doesnt allow using this function for ppromothing twu not fixed types - return promote_to_double(lh) / promote_to_double( rh ); - } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr fixed_t fixed_division_by_scalar(fixed_t lh, integral_type rh ) noexcept + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto fixed_division_by_scalar(std::same_as auto lh, std::integral auto rh) noexcept -> fixed_t + { + if(rh != 0) [[likely]] { - if( fixed_likely(rh != 0) ) - { - fixed_t const result = as_fixed( lh.v / promote_type_to_signed(rh) ); -// if( fixed_likely( check_division_result(result)) ) - return result; - } - return quiet_NaN_result(); //abort ? + fixed_t const result = as_fixed(lh.v / detail::promote_type_to_signed(rh)); + return result; } + return quiet_NaN_result(); // abort ? } - - template> - > - [[ gnu::const, gnu::always_inline ]] - constexpr auto fixed_division(supported_type1 lh, supported_type2 rh ) noexcept + } // namespace detail + +struct division_t + { + template + requires concepts::arithmetic_and_one_is_fixed + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(supported_type1 lh, supported_type2 rh) noexcept { - if constexpr( detail::is_integral_v ) - return detail::fixed_division_by_scalar( lh, rh ); - else if constexpr ( detail::one_of_is_double_v ) - return detail::promoted_double_division( lh, rh ); + if constexpr(std::is_integral_v) + return detail::fixed_division_by_scalar(lh, rh); + else if constexpr(typetraits::one_of_is_double_v) + return detail::promote_to_double(lh) / detail::promote_to_double(rh); else - return detail::promoted_fixed_division( lh, rh ); + return detail::fixed_divisionf(detail::promote_to_fixed(lh), detail::promote_to_fixed(rh)); } + }; - template> - > - [[ gnu::always_inline ]] - constexpr fixed_t & operator /= ( fixed_t & lh, supported_type rh ) noexcept - { - lh = fixed_division(lh,rh); - return lh; - } - - template>> - [[ gnu::const, gnu::always_inline ]] - constexpr auto operator / ( supported_type1 lh, supported_type2 rh ) noexcept - { - return fixed_division(lh,rh); - } +inline constexpr division_t division; - //------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------ - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t ceil( fixed_t value ) noexcept +struct ceil_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto value) noexcept -> fixed_t { - fixed_internal result { (value.v + 0xffff) & ~((1<<16ll)-1) }; - if( value.v < result ) + fixed_internal result{(value.v + 0xffff) & ~((1 << 16ll) - 1)}; + if(value.v < result) return as_fixed(result); return quiet_NaN_result(); } - - //------------------------------------------------------------------------------------------------------ - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t floor( fixed_t value ) noexcept + }; + +inline constexpr ceil_t ceil; + +//------------------------------------------------------------------------------------------------------ + +struct floor_t + { + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(std::same_as auto value) noexcept -> fixed_t { - value = as_fixed( value.v & ~((1<<16)-1) ); + value = as_fixed(value.v & ~((1 << 16) - 1)); return value; } - - //------------------------------------------------------------------------------------------------------ + }; + +inline constexpr floor_t floor; + +//------------------------------------------------------------------------------------------------------ + +struct angle_to_radians_t + { ///\brief converts angle 0 - 360 to radians. - template> - > - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t angle_to_radians( integral_type angle ) noexcept + template + requires(sizeof(integral_type) > 1) + [[nodiscard, gnu::const, gnu::always_inline]] + static constexpr auto operator()(integral_type angle) noexcept -> fixed_t { - if( angle >= integral_type(0) && angle <= integral_type(360) ) - return integral_to_fixed(angle) * fixedmath::phi / 180; - return quiet_NaN_result(); + if(angle >= integral_type(0) && angle <= integral_type(360)) + return division(multiply(arithmetic_to_fixed(angle), fixedmath::phi), 180); + return quiet_NaN_result(); } + }; + +inline constexpr angle_to_radians_t angle_to_radians; - - //------------------------------------------------------------------------------------------------------ - uint16_t square_root_tab( uint8_t index ) noexcept; - - [[nodiscard,FIXEDMATH_PUBLIC, deprecated]] - fixed_t sqrt_aprox(fixed_t value) noexcept; - namespace detail +//------------------------------------------------------------------------------------------------------ + +namespace detail + { + ///\brief Square root by abacus algorithm + [[nodiscard, gnu::const]] + constexpr auto sqrt_abacus(fixed_t value) noexcept -> fixed_t { - ///\brief Square root by abacus algorithm - [[ nodiscard, gnu::const]] - constexpr fixed_t sqrt_abacus( fixed_t value ) noexcept + if(value.v < 0 || value.v >= (1ll << 48)) [[unlikely]] + return std::numeric_limits::quiet_NaN(); + + value.v <<= 16; + + fixed_internal pwr4{detail::highest_pwr4_clz(fixed_internal_unsigned(value.v))}; + + fixed_internal result{}; + while(pwr4 != 0) { - if( fixed_unlikely(value.v < 0 || value.v >= (1ll<<48)) ) - return std::numeric_limits::quiet_NaN(); - - value.v <<= 16; - - fixed_internal pwr4 { detail::highest_pwr4_clz(value.v) }; - - fixed_internal result{}; - while( pwr4 != 0 ) + if(value.v >= (result + pwr4)) { - if( value.v >= ( result + pwr4 ) ) - { - value.v -= result + pwr4; - result += pwr4 << 1; - } - result >>= 1; - pwr4 >>= 2; + value.v -= result + pwr4; + result += pwr4 << 1; } - return as_fixed(result); - } - - [[ nodiscard, gnu::const]] - inline fixed_t sqrt_std_math( fixed_t value ) noexcept - { - return floating_point_to_fixed(std::sqrt( fixed_to_floating_point(value))); + result >>= 1; + pwr4 >>= 2; } + return as_fixed(result); } -#if defined(FIXEDMATH_ENABLE_SQRT_ABACUS_ALGO) || __cplusplus >= 202000L - #define FIXEDMATH_SQRT_CONSTEXPR constexpr -#else - #define FIXEDMATH_SQRT_CONSTEXPR inline -#endif - -#if __cplusplus < 202000L -#if defined(FIXEDMATH_ENABLE_SQRT_ABACUS_ALGO) - inline constexpr bool sqrt_constexpr_available = true; - constexpr fixed_t sqrt( fixed_t value ) noexcept - { - return detail::sqrt_abacus(value); - } -#else - inline constexpr bool sqrt_constexpr_available = false; - [[ nodiscard, gnu::const]] - inline fixed_t sqrt( fixed_t value ) noexcept - { - return detail::sqrt_std_math(value); - } -#endif -#else - inline constexpr bool sqrt_constexpr_available = true; - - constexpr fixed_t sqrt( fixed_t value ) noexcept + } // namespace detail + +inline constexpr bool sqrt_constexpr_available = true; + +struct sqrt_t + { + [[nodiscard]] + static constexpr auto operator()(std::same_as auto value) noexcept -> fixed_t { - if (std::is_constant_evaluated() ) + if(std::is_constant_evaluated()) return detail::sqrt_abacus(value); else - return detail::sqrt_std_math(value); + return arithmetic_to_fixed(std::sqrt(fixed_to_arithmetic(value))); } -#endif - [[nodiscard,FIXEDMATH_PUBLIC,deprecated]] - fixed_t hypot_aprox (fixed_t lh, fixed_t rh ) noexcept; + }; +inline constexpr sqrt_t sqrt; - [[ nodiscard, gnu::const]] - FIXEDMATH_SQRT_CONSTEXPR fixed_t hypot(fixed_t lh, fixed_t rh ) noexcept +//------------------------------------------------------------------------------------------------------ + +struct hypot_t + { + [[nodiscard]] + static constexpr auto operator()(std::same_as auto lh, std::same_as auto rh) noexcept -> fixed_t { constexpr int prec_ = 16; - //sqrt(X^2+Y^2) = sqrt( (X/D)^2+(Y/D)^2) * D - //D = 2^n - if( lh < 0_fix ) + // sqrt(X^2+Y^2) = sqrt( (X/D)^2+(Y/D)^2) * D + // D = 2^n + if(lh < 0_fix) lh = -lh; - if( rh < 0_fix ) + if(rh < 0_fix) rh = -rh; - uint64_t uhi { static_cast(lh.v)}; - uint64_t ulo { static_cast(rh.v)}; - - //reorder hi/lo - if( uhi < ulo ) + uint64_t uhi{static_cast(lh.v)}; + uint64_t ulo{static_cast(rh.v)}; + + // reorder hi/lo + if(uhi < ulo) detail::swap(uhi, ulo); - if( fixed_unlikely(uhi == 0) ) + if(uhi == 0) [[unlikely]] return 0_fix; - //check hi for overflow and shift right with d - else if( uhi >= (1ull<<30) ) + // check hi for overflow and shift right with d + else if(uhi >= (1ull << 30)) { - int rshbits{ 48 - cxx20::countl_zero( uhi ) }; + int rshbits{48 - cxx20::countl_zero(uhi)}; uhi >>= rshbits; ulo >>= rshbits; - return as_fixed(sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_ ) ).v << rshbits) ; + return as_fixed(sqrt(as_fixed(fixed_internal(uhi * uhi + ulo * ulo) >> prec_)).v << rshbits); } - //else check lo for underflow and shift left with d - else if( ulo < (1<<16) ) + // else check lo for underflow and shift left with d + else if(ulo < (1 << 16)) { - int lshbits{ std::max(cxx20::countl_zero( uhi ) - 30,0) >> 1 }; + int lshbits{std::max(cxx20::countl_zero(uhi) - 30, 0) >> 1}; uhi <<= lshbits; ulo <<= lshbits; - return as_fixed( sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_) ).v >> lshbits); + return as_fixed(sqrt(as_fixed(fixed_internal(uhi * uhi + ulo * ulo) >> prec_)).v >> lshbits); } else - return sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_ ) ); + return sqrt(as_fixed(fixed_internal(uhi * uhi + ulo * ulo) >> prec_)); } + }; - //------------------------------------------------------------------------------------------------------ - // for trigonometric functions maclurin taylor series are used - // https://en.wikipedia.org/wiki/Taylor_series - namespace detail +inline constexpr hypot_t hypot; + +//------------------------------------------------------------------------------------------------------ +// for trigonometric functions maclurin taylor series are used +// https://en.wikipedia.org/wiki/Taylor_series +namespace detail + { + ///\return \ref rad normalized into range -phi/2 .. 3phi/2 + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto sin_range(std::same_as auto rad) noexcept -> fixed_t { - ///\returns \param rad normalized into range -phi/2 .. 3phi/2 - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr fixed_t sin_range( fixed_t rad ) noexcept + // maximum performance for values in range thus fixed_unlikely + if(rad < -fixpidiv2 || rad > add(phi, fixpidiv2)) [[unlikely]] { - constexpr fixed_t phi2 { phi/2 }; - constexpr fixed_t _2phi { 2*phi }; - - //maximum performance for values in range thus fixed_unlikely - if( fixed_unlikely( rad < -phi2 || rad > phi+phi2 ) ) - { - rad = as_fixed( ( phi2.v + rad.v) % _2phi.v - phi2.v ); - if( fixed_unlikely( rad < -phi2 ) ) - rad = as_fixed( rad.v + _2phi.v ); - } - return rad; + rad = as_fixed((fixpidiv2.v + rad.v) % fixpi2.v - fixpidiv2.v); + if(rad < -fixpidiv2) [[unlikely]] + rad = as_fixed(rad.v + fixpi2.v); } + return rad; } - ///\returns sine of value in radians + } // namespace detail + +struct sin_t + { + ///\return sine of value in radians /// Y = X - X^3/ 3! + X^5/ 5! - ... + (-1)^(n+1) * X^(2*n-1)/(2n-1)! - /// X - X^3/ 3! + X^5/ 5! - X^7/7! + /// X - X^3/ 3! + X^5/ 5! - X^7/7! /// X - X^3/6 + x^3*x^2/(6*20) - x^3*x^2*x^2/(6*20*42) /// /// let X2 = X*X /// X * (1 - X2*(1 - X2*(1 - X2/42)/20)/6) /// /// error is less or equal to X^9/9! - [[ nodiscard,gnu::const ]] - constexpr fixed_t sin( fixed_t rad ) noexcept + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto rad) noexcept -> fixed_t { - constexpr fixed_t phi2 { phi/2 }; using detail::mul_; - rad = detail::sin_range(rad); - + // on arm64 condition is compiled as subtraction with csel instruction without jump // mov w9, #9279 // movk w9, #3, lsl #16 // cmp x0, x8 // sub x9, x9, x0 // csel x9, x9, x0, gt - if(fixed_unlikely( rad > phi2) ) - rad = phi - rad; //inverse of phi/2 .. -phi/2 - - //aprox valid for -phi/2 .. phi/2 - constexpr int prec_ = 16; - fixed_internal x { rad.v }; - fixed_internal x2{ mul_(x,x) }; -#if 0 - constexpr fixed_internal one__{ fixed_internal{1}<(x,( one__ - mul_(x2,( one__ - mul_(x2,( one__-x2/42))/5))/3)) }; -#else - // reduce number of divisions - /* - { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 42 } } right ) cdot { 1 over 20 } } right ) { 1 over 6 } } right ) } - { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 2 } { 1 over 21 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) } - { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over 21 } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) } - { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over { 5 cdot 21 } } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) } - { x left ( { 1 - x ^ 2 { 1 over { 3 cdot 5 cdot 21 } } left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) } - { x left ( { 3 cdot 5 cdot 21 - x ^ 2 left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) { 1 over { 3 cdot 5 cdot 21 } } } - { x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) :315 } - { x left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 42 - x ^ 2 } right ) cdot { 1 over 8 } } right ) { 1 over 2 } } right ) :315 } - */ - constexpr fixed_internal _42{ fixed_internal{42}<(x,( _315 - mul_(x2,( _105 - mul_(x2,(_42-x2))))))/315 }; - fixed_internal result{ mul_(x,( _315 - mul_(x2,( _105 - x2*(_42-x2)))))/315 }; -#endif + if(rad > fixpidiv2) [[unlikely]] + rad = phi - rad; // inverse of phi/2 .. -phi/2 + + // aprox valid for -phi/2 .. phi/2 + static constexpr int prec_ = 16; + fixed_internal x{rad.v}; + fixed_internal x2{mul_(x, x)}; + // reduce number of divisions + /* + { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 42 } } right ) cdot { 1 over 20 } } + right ) { 1 over 6 } } right ) } { x left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 cdot { 1 over 2 } { + 1 over 21 } } right ) cdot { 1 over 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) } { x + left ( { 1 - x ^ 2 left ( { 1 - x ^ 2 { 1 over 21 } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over + 4 } cdot { 1 over 5 } } right ) { 1 over 2 } cdot { 1 over 3 } } right ) } { x left ( { 1 - x ^ 2 left ( { 1 - x ^ + 2 { 1 over { 5 cdot 21 } } left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 + } cdot { 1 over 3 } } right ) } { x left ( { 1 - x ^ 2 { 1 over { 3 cdot 5 cdot 21 } } left ( { 5 cdot 21 - x ^ 2 + left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) } { x left ( { + 3 cdot 5 cdot 21 - x ^ 2 left ( { 5 cdot 21 - x ^ 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over + 4 } } right ) { 1 over 2 } } right ) { 1 over { 3 cdot 5 cdot 21 } } } { x left ( { 315 - x ^ 2 left ( { 105 - x ^ + 2 left ( { 21 - x ^ 2 cdot { 1 over 2 } } right ) cdot { 1 over 4 } } right ) { 1 over 2 } } right ) :315 } { x + left ( { 315 - x ^ 2 left ( { 105 - x ^ 2 left ( { 42 - x ^ 2 } right ) cdot { 1 over 8 } } right ) { 1 over 2 } } + right ) :315 } + */ + static constexpr fixed_internal _42{fixed_internal{42} << prec_}; + static constexpr fixed_internal _105{fixed_internal{105} << (prec_ + prec_ + 3)}; + static constexpr fixed_internal _315{fixed_internal{315} << prec_}; + fixed_internal result{mul_(x, (_315 - mul_(x2, (_105 - x2 * (_42 - x2))))) / 315}; return as_fixed(result); } + }; - //------------------------------------------------------------------------------------------------------ - ///\returns cosine of value in radians - [[ nodiscard, gnu::const ]] - constexpr fixed_t cos( fixed_t rad ) noexcept - { - constexpr fixed_t phi2 { fixpidiv2 }; - //more effective to use sine than calculate maclurin series for cosine - //as maclurin series give precise results for -pi/2 .. pi/2 - return sin( phi2 + rad ); - } - - //------------------------------------------------------------------------------------------------------ - // tan - // Bernoulli number B 2*n - // 1 1/6 - // 2 -1/30 - // 3 1/42 - // 4 -1/30 - // 5 5/66 - // 6 -691/2730 - // 7 7/6 - // 8 -3617/510 - // 9 43867/798 - namespace detail - { - // { { 1 over 6 } { { left ( - 4 right ) ^ 1 left ( 1 - 4 ^ 1 right ) } over fact left ( 2 right ) } x + { - 1 over 30 } { { left ( - 4 right ) ^ 2 left ( 1 - 4 ^ 2 right ) } over fact left ( 2 cdot 2 right ) } x ^ left ( 2 cdot 2 - 1 right ) + { 1 over 42 } { { left ( - 4 right ) ^ 3 left ( 1 - 4 ^ 3 right ) } over fact left ( 2 cdot 3 right ) } x ^ left ( 2 cdot 3 - 1 right ) + { - 1 over 30 } cdot { { left ( - 4 right ) ^ 4 left ( 1 - 4 ^ 4 right ) } over fact left ( 2 cdot 4 right ) } x ^ left ( { 2 cdot 4 - 1 } right ) + { 5 over 66 } cdot { { left ( - 4 right ) ^ 5 left ( 1 - 4 ^ 5 right ) } over fact left ( 2 cdot 5 right ) } x ^ left ( { 2 cdot 5 - 1 } right ) + { - 691 over 2730 } cdot { { left ( - 4 right ) ^ 6 left ( 1 - 4 ^ 6 right ) } over fact left ( 2 cdot 6 right ) } x ^ left ( { 2 cdot 6 - 1 } right ) + { 7 over 6 } { { left ( - 4 right ) ^ 7 left ( 1 - 4 ^ 7 right ) } over fact left ( 2 cdot 7 right ) } x ^ left ( { 2 cdot 7 - 1 } right ) + { - 3617 over 510 } { { left ( - 4 right ) ^ 8 left ( 1 - 4 ^ 8 right ) } over fact left ( 2 cdot 8 right ) } x ^ left ( { 2 cdot 8 - 1 } right ) } - - // { x + { 1 over 3 } x ^ 3 + { 2 over 15 } x ^ 5 + { 17 over 315 } x ^ 7 + { 62 over 2835 } x ^ 9 + { 1382 over 155925 } x ^ 11 + { 21844 over 6081075 } x ^ 13 + { 929569 over 638512875 } x ^ 15 } - // { x left ( { 1 + { 1 over 3 } x ^ 2 + { 2 over 15 } x ^ 4 + { 17 over 315 } x ^ 6 + { 62 over 2835 } x ^ 8 + { 1382 over 155925 } x ^ 10 + { 21844 over 6081075 } x ^ 12 + { 929569 over 638512875 } x ^ 14 } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 2 over 5 } x ^ 2 + { 17 over 105 } x ^ 4 + { 62 over 945 } x ^ 6 + { 1382 over 51975 } x ^ 8 + { 21844 over 2027025 } x ^ 10 + { 929569 over 212837625 } x ^ 12 } right ) } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 17 over 21 } x ^ 2 + { 62 over 189 } x ^ 4 + { 1382 over 10395 } x ^ 6 + { 21844 over 405405 } x ^ 8 + { 929569 over 42567525 } x ^ 10 } right ) } right ) } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 62 over 9 } x ^ 2 + { 1382 over 495 } x ^ 4 + { 21844 over 19305 } x ^ 6 + { 929569 over 2027025 } x ^ 8 } right ) } right ) } right ) } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 left ( { 62 + { 1382 over 55 } x ^ 2 + { 21844 over 2145 } x ^ 4 + { 929569 over 225225 } x ^ 6 } right ) } right ) } right ) } right ) } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 left ( { 62 + { 1 over 55 } x ^ 2 left ( { 1382 + { 21844 over 39 } x ^ 2 + { 929569 over 4095 } x ^ 4 } right ) } right ) } right ) } right ) } right ) } right ) } - // { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 left ( { 62 + { 1 over 55 } x ^ 2 left ( { 1382 + { 1 over 39 } x ^ 2 left ( { 21844 + { 929569 over 105 } x ^ 4 } right ) } right ) } right ) } right ) } right ) } right ) } right ) } - // { x left ( { 1 + x ^ 2 left ( { 1 + x ^ 2 left ( { 2 + x ^ 2 left ( { 17 + x ^ 2 left ( { 62 + x ^ 2 left ( { 1382 + x ^ 2 left ( { 21844 + { 929569 over 105 } x ^ 4 } right ) :39 } right ) :55 } right ) :9 } right ) :21 } right ) :5 } right ) :3 } right ) } - template - [[ nodiscard, gnu::const, gnu::always_inline]] - constexpr fixed_internal tan_( fixed_internal x ) noexcept - { - fixed_internal x2{ mul_(x,x) }; - - fixed_internal y0_{ fix_(21844) + 929569 * x2 / 105 }; - fixed_internal y1_{ fix_(1382) + mul_(x2,y0_)/ 39 }; - fixed_internal y2_{ fix_(62) + mul_(x2,y1_) / 55 }; - fixed_internal y3_{ fix_(17) + mul_(x2,y2_)/ 9 }; - fixed_internal y4_{ fix_(2) + mul_(x2,y3_)/ 21 }; - fixed_internal y5_{ fix_(1) + mul_(x2,y4_)/ 5 }; - fixed_internal y6_{ fix_(1) + mul_(x2,y5_)/ 3 }; - fixed_internal res{ mul_(x,y6_) }; - return res; - } - - template - [[ nodiscard,gnu::const]] - constexpr fixed_internal tan2_( fixed_internal b ) - { - constexpr fixed_internal one_{fix_(1) }; - b = b - a; - fixed_internal tan_b { tan_(b) }; - return div_( tan_a + tan_b, one_ - mul_(tan_a, tan_b)); - } - - [[ nodiscard,gnu::const, gnu::always_inline ]] - constexpr fixed_internal tan_range( fixed_internal x ) noexcept - { - constexpr fixed_t phi2 { phi/2 }; - - //maximum performance for values in range thus fixed_unlikely - if( fixed_unlikely(x > phi2.v) ) - x = x % phi.v; +inline constexpr sin_t sin; - return x; - } - } - - [[ nodiscard, gnu::const]] - constexpr fixed_t tan( fixed_t rad ) noexcept +//------------------------------------------------------------------------------------------------------ +struct cos_t + { + ///\returns cosine of value in radians + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto rad) noexcept -> fixed_t + { + // more effective to use sine than calculate maclurin series for cosine + // as maclurin series give precise results for -pi/2 .. pi/2 + return sin(add(fixpidiv2, rad)); + } + }; + +inline constexpr cos_t cos; + +//------------------------------------------------------------------------------------------------------ +// tan +// Bernoulli number B 2*n +// 1 1/6 +// 2 -1/30 +// 3 1/42 +// 4 -1/30 +// 5 5/66 +// 6 -691/2730 +// 7 7/6 +// 8 -3617/510 +// 9 43867/798 +namespace detail + { + // { { 1 over 6 } { { left ( - 4 right ) ^ 1 left ( 1 - 4 ^ 1 right ) } over fact left ( 2 right ) } x + { - 1 over + // 30 } { { left ( - 4 right ) ^ 2 left ( 1 - 4 ^ 2 right ) } over fact left ( 2 cdot 2 right ) } x ^ left ( 2 cdot + // 2 - 1 right ) + { 1 over 42 } { { left ( - 4 right ) ^ 3 left ( 1 - 4 ^ 3 right ) } over fact left ( 2 cdot 3 + // right ) } x ^ left ( 2 cdot 3 - 1 right ) + { - 1 over 30 } cdot { { left ( - 4 right ) ^ 4 left ( 1 - 4 ^ 4 + // right ) } over fact left ( 2 cdot 4 right ) } x ^ left ( { 2 cdot 4 - 1 } right ) + { 5 over 66 } cdot { { left ( + // - 4 right ) ^ 5 left ( 1 - 4 ^ 5 right ) } over fact left ( 2 cdot 5 right ) } x ^ left ( { 2 cdot 5 - 1 } right + // ) + { - 691 over 2730 } cdot { { left ( - 4 right ) ^ 6 left ( 1 - 4 ^ 6 right ) } over fact left ( 2 cdot 6 + // right ) } x ^ left ( { 2 cdot 6 - 1 } right ) + { 7 over 6 } { { left ( - 4 right ) ^ 7 left ( 1 - 4 ^ 7 right ) + // } over fact left ( 2 cdot 7 right ) } x ^ left ( { 2 cdot 7 - 1 } right ) + { - 3617 over 510 } { { left ( - 4 + // right ) ^ 8 left ( 1 - 4 ^ 8 right ) } over fact left ( 2 cdot 8 right ) } x ^ left ( { 2 cdot 8 - 1 } right ) } + + // { x + { 1 over 3 } x ^ 3 + { 2 over 15 } x ^ 5 + { 17 over 315 } x ^ 7 + { 62 over 2835 } x ^ 9 + { 1382 over + // 155925 } x ^ 11 + { 21844 over 6081075 } x ^ 13 + { 929569 over 638512875 } x ^ 15 } { x left ( { 1 + { 1 over 3 + // } x ^ 2 + { 2 over 15 } x ^ 4 + { 17 over 315 } x ^ 6 + { 62 over 2835 } x ^ 8 + { 1382 over 155925 } x ^ 10 + { + // 21844 over 6081075 } x ^ 12 + { 929569 over 638512875 } x ^ 14 } right ) } { x left ( { 1 + { 1 over 3 } x ^ 2 + // left ( { 1 + { 2 over 5 } x ^ 2 + { 17 over 105 } x ^ 4 + { 62 over 945 } x ^ 6 + { 1382 over 51975 } x ^ 8 + { + // 21844 over 2027025 } x ^ 10 + { 929569 over 212837625 } x ^ 12 } right ) } right ) } { x left ( { 1 + { 1 over 3 + // } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 17 over 21 } x ^ 2 + { 62 over 189 } x ^ 4 + { 1382 over + // 10395 } x ^ 6 + { 21844 over 405405 } x ^ 8 + { 929569 over 42567525 } x ^ 10 } right ) } right ) } right ) } { x + // left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { + // 62 over 9 } x ^ 2 + { 1382 over 495 } x ^ 4 + { 21844 over 19305 } x ^ 6 + { 929569 over 2027025 } x ^ 8 } right + // ) } right ) } right ) } right ) } { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + // + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 left ( { 62 + { 1382 over 55 } x ^ 2 + { 21844 over 2145 } + // x ^ 4 + { 929569 over 225225 } x ^ 6 } right ) } right ) } right ) } right ) } right ) } { x left ( { 1 + { 1 + // over 3 } x ^ 2 left ( { 1 + { 1 over 5 } x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 + // left ( { 62 + { 1 over 55 } x ^ 2 left ( { 1382 + { 21844 over 39 } x ^ 2 + { 929569 over 4095 } x ^ 4 } right ) + // } right ) } right ) } right ) } right ) } right ) } { x left ( { 1 + { 1 over 3 } x ^ 2 left ( { 1 + { 1 over 5 } + // x ^ 2 left ( { 2 + { 1 over 21 } x ^ 2 left ( { 17 + { 1 over 9 } x ^ 2 left ( { 62 + { 1 over 55 } x ^ 2 left ( + // { 1382 + { 1 over 39 } x ^ 2 left ( { 21844 + { 929569 over 105 } x ^ 4 } right ) } right ) } right ) } right ) } + // right ) } right ) } right ) } { x left ( { 1 + x ^ 2 left ( { 1 + x ^ 2 left ( { 2 + x ^ 2 left ( { 17 + x ^ 2 + // left ( { 62 + x ^ 2 left ( { 1382 + x ^ 2 left ( { 21844 + { 929569 over 105 } x ^ 4 } right ) :39 } right ) :55 + // } right ) :9 } right ) :21 } right ) :5 } right ) :3 } right ) } + template + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto tan_(fixed_internal x) noexcept -> fixed_internal + { + fixed_internal x2{mul_(x, x)}; + + fixed_internal y0_{fix_(21844) + 929569 * x2 / 105}; + fixed_internal y1_{fix_(1382) + mul_(x2, y0_) / 39}; + fixed_internal y2_{fix_(62) + mul_(x2, y1_) / 55}; + fixed_internal y3_{fix_(17) + mul_(x2, y2_) / 9}; + fixed_internal y4_{fix_(2) + mul_(x2, y3_) / 21}; + fixed_internal y5_{fix_(1) + mul_(x2, y4_) / 5}; + fixed_internal y6_{fix_(1) + mul_(x2, y5_) / 3}; + fixed_internal res{mul_(x, y6_)}; + return res; + } + + template + [[nodiscard, gnu::const]] + constexpr auto tan2_(fixed_internal b) -> fixed_internal + { + constexpr fixed_internal one_{fix_(1)}; + b = b - a; + fixed_internal tan_b{tan_(b)}; + return div_(tan_a + tan_b, one_ - mul_(tan_a, tan_b)); + } + + [[nodiscard, gnu::const, gnu::always_inline]] + constexpr auto tan_range(fixed_internal x) noexcept -> fixed_internal + { + // maximum performance for values in range thus fixed_unlikely + if(x > fixpidiv2.v) [[unlikely]] + x = x % phi.v; + + return x; + } + } // namespace detail + +struct tan_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto rad) noexcept -> fixed_t { using detail::div_; using detail::tan_; - - constexpr int prec_ = 16; - constexpr int prec_inc = 4; - constexpr fixed_internal one_{ detail::fix_(1) }; - //tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a) tan(b)) - fixed_internal x { rad.v }; - bool sign_ {}; - if( x < 0 ) + + static constexpr int prec_ = 16; + static constexpr int prec_inc = 4; + static constexpr fixed_internal one_{detail::fix_(1)}; + // tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a) tan(b)) + fixed_internal x{rad.v}; + bool sign_{}; + if(x < 0) { x = -x; sign_ = true; } - //normalize the range to phi/2 + // normalize the range to phi/2 x = detail::tan_range(x); - - if( fixed_likely( x != fixpidiv2.v ) ) + + if(x != fixpidiv2.v) [[likely]] { - fixed_internal res_tan {}; - if( x <= fixpidiv4.v ) - res_tan = tan_(x<>prec_inc; + fixed_internal res_tan{}; + if(x <= fixpidiv4.v) + res_tan = tan_(x << prec_inc) >> prec_inc; else - res_tan = div_( one_, tan_( (fixpidiv2.v<>prec_inc ); - if( sign_ ) + res_tan = div_(one_, tan_((fixpidiv2.v << prec_inc) - (x << prec_inc)) >> prec_inc); + if(sign_) res_tan = -res_tan; return as_fixed(res_tan); - } + } else return quiet_NaN_result(); } - - //------------------------------------------------------------------------------------------------------ - // atan - // Y = X - X^3/3 + X^5/5 - X^7/7 + X^9/9 -X^11/11 - // { x - { x ^ 3 over 3 } + { x ^ 5 over 5 } - { x ^ 7 over 7 } + { x ^ 9 over 9 } - { x ^ 11 over 11 } } - // { { 1 over 11 } x left ( { 11 + x ^ 2 left ( { - { 11 over 3 } + x ^ 2 left ( { { 11 over 5 } + x ^ 2 left ( { - { 11 over 7 } + x ^ 2 left ( { { 11 over 9 } - x ^ 2 } right ) } right ) } right ) } right ) } right ) } - namespace detail + }; + +inline constexpr tan_t tan; + +//------------------------------------------------------------------------------------------------------ +// atan +// Y = X - X^3/3 + X^5/5 - X^7/7 + X^9/9 -X^11/11 +// { x - { x ^ 3 over 3 } + { x ^ 5 over 5 } - { x ^ 7 over 7 } + { x ^ 9 over 9 } - { x ^ 11 over 11 } } +// { { 1 over 11 } x left ( { 11 + x ^ 2 left ( { - { 11 over 3 } + x ^ 2 left ( { { 11 over 5 } + x ^ 2 left ( { - { +// 11 over 7 } + x ^ 2 left ( { { 11 over 9 } - x ^ 2 } right ) } right ) } right ) } right ) } right ) } +namespace detail + { + // t=x*x + // 1/11*x(11+t(-11/3+t(11/5+t(-11/7+t(11/9-t))))) + template + constexpr auto atan(fixed_internal x) noexcept -> fixed_internal { -#if 0 - template - [[ nodiscard,gnu::const, gnu::always_inline ]] - constexpr fixed_internal atan( fixed_internal x ) noexcept - { - //this has less error - fixed_internal x2 { mul_(x, x) }; - fixed_internal x3 { mul_(x2, x) }; - fixed_internal x5 { mul_(x3, x2) }; - fixed_internal x7 { mul_(x5, x2) }; - fixed_internal x9 { mul_(x7, x2) }; - fixed_internal x11 { mul_(x9, x2) }; - - return x - x3/3 + x5/5 - x7/7 + x9/9 - x11/11; - } -#else - //t=x*x - //1/11*x(11+t(-11/3+t(11/5+t(-11/7+t(11/9-t))))) - template - constexpr fixed_internal atan( fixed_internal x ) noexcept - { - fixed_internal const t { mul_(x,x)}; - constexpr fixed_internal _11o9{ fix_(11)/9 }; - constexpr fixed_internal _11o7{ fix_(11)/7 }; - constexpr fixed_internal _11o5{ fix_(11)/5 }; - constexpr fixed_internal _11o3{ fix_(11)/3 }; - constexpr fixed_internal _11{ fix_(11) }; - - fixed_internal y{ _11o9 - t }; - y = -_11o7 + mul_(t, y); - y = _11o5 + mul_(t, y); - y = -_11o3 + mul_(t, y); - y = _11 + mul_(t, y); - return mul_(x, y) / 11; - } -#endif + fixed_internal const t{mul_(x, x)}; + static constexpr fixed_internal _11o9{fix_(11) / 9}; + static constexpr fixed_internal _11o7{fix_(11) / 7}; + static constexpr fixed_internal _11o5{fix_(11) / 5}; + static constexpr fixed_internal _11o3{fix_(11) / 3}; + static constexpr fixed_internal _11{fix_(11)}; - //arctan (x) = arctan(c) + arctan((x - c) / (1 + x*c)) - template - constexpr fixed_internal atan_sum( fixed_internal x ) - { - constexpr fixed_internal one_{fix_(1) }; - return atanc + atan( div_(x - c, one_ + mul_(x,c)) ); - } - } - - [[ nodiscard, gnu::const ]] - constexpr fixed_t atan( fixed_t value ) noexcept + fixed_internal y{_11o9 - t}; + y = -_11o7 + mul_(t, y); + y = _11o5 + mul_(t, y); + y = -_11o3 + mul_(t, y); + y = _11 + mul_(t, y); + return mul_(x, y) / 11; + } + + // arctan (x) = arctan(c) + arctan((x - c) / (1 + x*c)) + template + constexpr auto atan_sum(fixed_internal x) -> fixed_internal + { + static constexpr fixed_internal one_{fix_(1)}; + return atanc + atan(div_(x - c, one_ + mul_(x, c))); + } + } // namespace detail + +struct atan_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto value) noexcept -> fixed_t { using detail::atan; using detail::atan_sum; @@ -953,222 +715,200 @@ namespace fixedmath // arctan (1/x) = 0.5 * pi - arctan(x) [x > 0] // arctan (x) = arctan(c) + arctan((x - c) / (1 + x*c)) // arctan(x)' = 1/ (1+x^2) - constexpr int prec_ = 16; - - constexpr fixed_internal _7o16{ 28672 }; // 7/16 - constexpr fixed_internal atan_7o16 { 27028 }; // 27027,7307005264 - - constexpr fixed_internal _11o16 { 45056 }; // 11/16 - constexpr fixed_internal atan_11o16 { 39472 }; //39471,503516301 - - constexpr fixed_internal _19o16 { 77824 }; // 19/16 - constexpr fixed_internal atan_19o16 { 57076 }; //57075,52896291 - - constexpr fixed_internal _39o16 { 159744 }; // 19/16 - constexpr fixed_internal atan_39o16 { 77429 }; //77429,4473907736 - - fixed_internal x { value.v }; - bool sign_ {}; - if( x < 0 ) + static constexpr int prec_ = 16; + + static constexpr fixed_internal _7o16{28672}; // 7/16 + static constexpr fixed_internal atan_7o16{27028}; // 27027,7307005264 + + static constexpr fixed_internal _11o16{45056}; // 11/16 + static constexpr fixed_internal atan_11o16{39472}; // 39471,503516301 + + static constexpr fixed_internal _19o16{77824}; // 19/16 + static constexpr fixed_internal atan_19o16{57076}; // 57075,52896291 + + static constexpr fixed_internal _39o16{159744}; // 19/16 + static constexpr fixed_internal atan_39o16{77429}; // 77429,4473907736 + + fixed_internal x{value.v}; + bool sign_{}; + if(x < 0) { x = -x; sign_ = true; } fixed_internal result{}; - if( x < _7o16 ) - result = atan( x ); - else if( x < _11o16 ) - result = atan_sum( x ); - else if( x < _19o16 ) - result = atan_sum( x ); - else if( x < _39o16 ) - result = atan_sum( x ); + if(x < _7o16) + result = atan(x); + else if(x < _11o16) + result = atan_sum(x); + else if(x < _19o16) + result = atan_sum(x); + else if(x < _39o16) + result = atan_sum(x); else - result = atan_sum( x ); - - if( !sign_) + result = atan_sum(x); + + if(!sign_) return as_fixed(result); return as_fixed(-result); } - - [[ nodiscard, gnu::const ]] - constexpr fixed_t atan2( fixed_t y, fixed_t x ) noexcept + }; + +inline constexpr atan_t atan; + +struct atan2_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto y, std::same_as auto x) noexcept -> fixed_t { - if( x > 0_fix ) - return atan(y/x); - else if( x < 0_fix ) - { - if( y >= 0_fix ) - return atan(y/x) + phi; - else // y < 0 - return atan(y/x) - phi; - } - else // x ==0 - { - if( y > 0_fix ) + if(x > 0_fix) + return atan(y / x); + else if(x < 0_fix) + if(y >= 0_fix) + return atan(y / x) + phi; + else // y < 0 + return atan(y / x) - phi; + else // x ==0 + if(y > 0_fix) return fixpidiv2; - else if( y < 0_fix ) + else if(y < 0_fix) return -fixpidiv2; else return quiet_NaN_result(); - } - } - - namespace detail - { - // { x + { 1 over 6 } x ^ 3 + { 3 over 40 } x ^ 5 + { 5 over 112 } x ^ 7 + { 35 over 1152 } x ^ 9 + { 63 over 2816 } x ^ 11 } - // { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 } x ^ 6 + { 35 over 1152 } x ^ 8 + { 63 over 2816 } x ^ 10 } right ) } - // { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 } x ^ 6 + { 7 over 128 } x ^ 8 left ( { { 5 over 9 } + { 9 over 22 } x ^ 2 } right ) } right ) } - // { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 } x ^ 6 + { 7 over 99 } { 1 over 256 } x ^ 8 left ( { 110 + 81 x ^ 2 } right ) } right ) } - // { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 1 over { 112 cdot 99 } } x ^ 6 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } - // { x left ( { 1 + { 1 over 6 } x ^ 2 + { 1 over { 5 cdot 693 } } { 1 over 8 } x ^ 4 left ( { 693 cdot 3 + { 5 over 2 } x ^ 2 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } right ) } - // { { 1 over 10395 } x left ( { 10395 + { 1 over 2 } x ^ 2 left ( { 3465 + { 3 over 4 } x ^ 2 left ( { 2079 + { 5 over 2 } x ^ 2 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } right ) } right ) } -#if 1 - template - constexpr fixed_internal asin( fixed_internal x ) noexcept - { - fixed_internal x2{ mul_(x,x) }; - - constexpr fixed_internal _35o9{ div_(35,9) + 1 }; - constexpr fixed_internal _5o7{ div_(5,7) + 1 }; - constexpr fixed_internal _3o5{ div_(3,5) + 1 }; - constexpr fixed_internal _1o3{ div_(1,3) }; - constexpr fixed_internal _1{ fix_(1) }; - constexpr fixed_internal _63o11{ div_(63,11) + 1 }; - - - fixed_internal y6{ _35o9 + mul_(x2,_63o11) }; - fixed_internal y7{ _5o7 + mul_(x2,y6)}; - fixed_internal y8{ _3o5 + mul_(x2,y7)}; - fixed_internal y9{ _1o3 + mul_(x2,y8)}; - fixed_internal y10{ _1 + mul_(x2,y9)}; - - return mul_(x,y10); - } -#else - template - constexpr fixed_internal asin( fixed_internal x ) - { - fixed_internal x2{ mul_(x,x) }; - constexpr fixed_internal _110{ fix_(110) }; - constexpr fixed_internal _495{ fix_(495) }; - constexpr fixed_internal _2079{ fix_(2079) }; - constexpr fixed_internal _3465{ fix_(3465) }; - constexpr fixed_internal _10395{ fix_(10395) }; - - fixed_internal t0{ _110 + 81*x2 }; //(110 + 81x^2) - fixed_internal t1{ _495 + mul_(49*x2, t0) }; // 495 + 49x^2*t0/16 - fixed_internal t2{ _2079 + mul_(5*x2, t1) }; // 2079 + 6*x2*t1/2 - fixed_internal t3{ _3465 + mul_(3*x2, t2) }; // 3465+ 3x^2*t2/4 - fixed_internal t4{ _10395 + mul_(x2, t3) }; - return mul_(x,t4) / 10395; - } -#endif } - //------------------------------------------------------------------------------------------------------ - // asin |X| <= 1 - [[ nodiscard, gnu::const ]] - constexpr fixed_t asin( fixed_t x ) noexcept + }; + +inline constexpr atan2_t atan2; + +namespace detail + { + // { x + { 1 over 6 } x ^ 3 + { 3 over 40 } x ^ 5 + { 5 over 112 } x ^ 7 + { 35 over 1152 } x ^ 9 + { 63 over 2816 } + // x ^ 11 } { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 } x ^ 6 + { 35 over 1152 } x ^ + // 8 + { 63 over 2816 } x ^ 10 } right ) } { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 + // } x ^ 6 + { 7 over 128 } x ^ 8 left ( { { 5 over 9 } + { 9 over 22 } x ^ 2 } right ) } right ) } { x left ( { 1 + + // { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 5 over 112 } x ^ 6 + { 7 over 99 } { 1 over 256 } x ^ 8 left ( { 110 + // + 81 x ^ 2 } right ) } right ) } { x left ( { 1 + { 1 over 6 } x ^ 2 + { 3 over 40 } x ^ 4 + { 1 over { 112 cdot + // 99 } } x ^ 6 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } { x + // left ( { 1 + { 1 over 6 } x ^ 2 + { 1 over { 5 cdot 693 } } { 1 over 8 } x ^ 4 left ( { 693 cdot 3 + { 5 over 2 } + // x ^ 2 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } right ) } { { + // 1 over 10395 } x left ( { 10395 + { 1 over 2 } x ^ 2 left ( { 3465 + { 3 over 4 } x ^ 2 left ( { 2079 + { 5 over + // 2 } x ^ 2 left ( { 495 + 49 { 1 over 16 } x ^ 2 left ( { 110 + 81 x ^ 2 } right ) } right ) } right ) } right ) } + // right ) } + template + constexpr auto asin(fixed_internal x) noexcept -> fixed_internal + { + fixed_internal x2{mul_(x, x)}; + + constexpr fixed_internal _35o9{div_(35, 9) + 1}; + constexpr fixed_internal _5o7{div_(5, 7) + 1}; + constexpr fixed_internal _3o5{div_(3, 5) + 1}; + constexpr fixed_internal _1o3{div_(1, 3)}; + constexpr fixed_internal _1{fix_(1)}; + constexpr fixed_internal _63o11{div_(63, 11) + 1}; + + fixed_internal y6{_35o9 + mul_(x2, _63o11)}; + fixed_internal y7{_5o7 + mul_(x2, y6)}; + fixed_internal y8{_3o5 + mul_(x2, y7)}; + fixed_internal y9{_1o3 + mul_(x2, y8)}; + fixed_internal y10{_1 + mul_(x2, y9)}; + + return mul_(x, y10); + } + } // namespace detail + +//------------------------------------------------------------------------------------------------------ +// asin |X| <= 1 +struct asin_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto x) noexcept -> fixed_t { - using detail::set_sign; using detail::asin; - + using detail::set_sign; + fixed_internal x_{x.v}; - bool sign_ {}; - if( x_ < 0 ) + bool sign_{}; + if(x_ < 0) { x_ = -x_; sign_ = true; } - constexpr fixed_internal _1 { (1_fix).v }; - if( fixed_likely( x_ <= _1 ) ) + static constexpr fixed_internal _1{(1_fix).v}; + if(x_ <= _1) [[likely]] { constexpr int ext_prec = 4; - constexpr int prec = 16+ext_prec; + constexpr int prec = 16 + ext_prec; - if( x_ <= (0.60_fix).v ) + if(x_ <= (0.60_fix).v) { - fixed_internal result{ asin(x_<>ext_prec }; - return set_sign( sign_, result ); + fixed_internal result{asin(x_ << ext_prec) >> ext_prec}; + return set_sign(sign_, result); } - else + else { // asin(x) = pi/2-2*asin(sqrt((1-x)/2)) - fixed_internal sqr { sqrt( as_fixed((_1 - x_)>>1)).v }; - fixed_internal result{ fixpidiv2.v - (asin(sqr <>(ext_prec-1)) }; - return set_sign( sign_, result ); + fixed_internal sqr{sqrt(as_fixed((_1 - x_) >> 1)).v}; + fixed_internal result{fixpidiv2.v - (asin(sqr << ext_prec) >> (ext_prec - 1))}; + return set_sign(sign_, result); } } else return quiet_NaN_result(); } - //------------------------------------------------------------------------------------------------------ - // acos |X| <= 1 - [[ nodiscard, gnu::const ]] - constexpr fixed_t acos( fixed_t x ) noexcept + }; + +inline constexpr asin_t asin; + +//------------------------------------------------------------------------------------------------------ +// acos |X| <= 1 +struct acos_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(std::same_as auto x) noexcept -> fixed_t { - constexpr fixed_t phi2 { phi/2 }; - if( fixed_likely( x >= -1_fix && x <= 1_fix ) ) - return as_fixed( phi2.v - asin(x).v ); + if(x >= -1_fix && x <= 1_fix) [[likely]] + return as_fixed(fixpidiv2.v - asin(x).v); else return quiet_NaN_result(); } - - //------------------------------------------------------------------------------------------------------ - template - constexpr fixed_t sin_angle( supported_type angle ) noexcept - { - return sin( angle * phi / 180 ); - } - //------------------------------------------------------------------------------------------------------ - template - constexpr fixed_t cos_angle( supported_type angle ) noexcept - { - return cos( angle * phi / 180 ); - } - //------------------------------------------------------------------------------------------------------ - template - constexpr fixed_t tan_angle( supported_type angle ) noexcept + }; + +inline constexpr acos_t acos; + +//------------------------------------------------------------------------------------------------------ +struct sin_angle_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(concepts::arithmetic auto angle) noexcept -> fixed_t { - return tan( angle * phi / 180 ); + return sin(division(multiply(angle, phi), 180)); } - - //------------------------------------------------------------------------------------------------------ - // compat with old lib function - fixed_t sin_angle_tab( uint16_t degrees ) noexcept; - - [[deprecated,FIXEDMATH_PUBLIC]] - inline fixed_t sin_angle_aprox(int32_t angle) noexcept + }; + +inline constexpr sin_angle_t sin_angle; + +//------------------------------------------------------------------------------------------------------ +struct cos_angle_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(concepts::arithmetic auto angle) noexcept -> fixed_t { - if(fixed_unlikely(angle < 0 || angle > 360) ) - angle = angle % 360; - return sin_angle_tab(angle); + return cos(division(multiply(angle, phi), 180)); } + }; - //------------------------------------------------------------------------------------------------------ - // compat with old lib function - fixed_t cos_angle_tab( uint16_t degrees ) noexcept; - - [[deprecated,FIXEDMATH_PUBLIC]] - inline fixed_t cos_angle_aprox(int32_t angle) noexcept +inline cos_angle_t cos_angle; + +//------------------------------------------------------------------------------------------------------ +struct tan_angle_t + { + [[nodiscard, gnu::const]] + static constexpr auto operator()(concepts::arithmetic auto angle) noexcept -> fixed_t { - if( fixed_unlikely( angle < 0 || angle > 360) ) - angle = angle % 360; - return cos_angle_tab(angle); + return tan(division(multiply(angle, phi), 180)); } - - //------------------------------------------------------------------------------------------------------ - // compat with old lib function - fixed_t tan_tab( uint8_t index ) noexcept; - - [[nodiscard,FIXEDMATH_PUBLIC]] - fixed_t atan_index_aprox( fixed_t value ) noexcept; - - [[deprecated]] - inline fixed_t atan_aprox( fixed_t value ) noexcept { return atan_index_aprox( value ) * fixtorad_r; } - - - - - -} + }; + +inline constexpr tan_angle_t tan_angle; + + } // namespace fixedmath::inline v2::fobj diff --git a/fixed_lib/include/fixedmath/numbers.h b/fixed_lib/include/fixedmath/numbers.h index 78e67f5..558f400 100644 --- a/fixed_lib/include/fixedmath/numbers.h +++ b/fixed_lib/include/fixedmath/numbers.h @@ -1,23 +1,27 @@ +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math + #pragma once #include "types.h" namespace fixedmath -{ - inline constexpr fixed_t phi {as_fixed(205887) }; - inline constexpr fixed_t fixpi = phi; - inline constexpr fixed_t fixpi2 {as_fixed(411775)}; - inline constexpr fixed_t fixpi3 {as_fixed(617662)}; - inline constexpr fixed_t fixpidiv2 {as_fixed(102944)}; // phi/2 90deg - inline constexpr fixed_t fixpidiv3 {as_fixed(68629)}; // phi/3 60deg - inline constexpr fixed_t fixpidiv4 {as_fixed(51472)}; // phi/4 45deg + { +inline constexpr fixed_t phi{as_fixed(fixed_internal(205887))}; +inline constexpr fixed_t fixpi = phi; +inline constexpr fixed_t fixpi2{as_fixed(fixed_internal(411775))}; +inline constexpr fixed_t fixpi3{as_fixed(fixed_internal(617662))}; +inline constexpr fixed_t fixpidiv2{as_fixed(fixed_internal(102944))}; // phi/2 90deg +inline constexpr fixed_t fixpidiv3{as_fixed(fixed_internal(68629))}; // phi/3 60deg +inline constexpr fixed_t fixpidiv4{as_fixed(fixed_internal(51472))}; // phi/4 45deg - inline constexpr fixed_t fixa90 {as_fixed(5898240)}; - inline constexpr fixed_t fixa180 {as_fixed(11796480)}; - inline constexpr fixed_t fixa270 {as_fixed(17694720)}; - inline constexpr fixed_t fixa360 {as_fixed(23592960)}; +inline constexpr fixed_t fixa90{as_fixed(fixed_internal(5898240))}; +inline constexpr fixed_t fixa180{as_fixed(fixed_internal(11796480))}; +inline constexpr fixed_t fixa270{as_fixed(fixed_internal(17694720))}; +inline constexpr fixed_t fixa360{as_fixed(fixed_internal(23592960))}; - //fixed index to radians - inline constexpr fixed_t fixtorad_r = {as_fixed(1608)}; /* 2pi/256 */ - inline constexpr fixed_t radtofix_r = {as_fixed(2670177)}; /* 256/2pi */ -} +// fixed index to radians +inline constexpr fixed_t fixtorad_r = {as_fixed(fixed_internal(1608))}; // 2pi/256 +inline constexpr fixed_t radtofix_r = {as_fixed(fixed_internal(2670177))}; // 256/2pi + } // namespace fixedmath diff --git a/fixed_lib/include/fixedmath/types.h b/fixed_lib/include/fixedmath/types.h index 3284d5c..9ad1443 100644 --- a/fixed_lib/include/fixedmath/types.h +++ b/fixed_lib/include/fixedmath/types.h @@ -1,113 +1,66 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020-2024 Artur Bać +// SPDX-License-Identifier: BSL-1.0 +// SPDX-PackageHomePage: https://github.com/arturbac/fixed_math #pragma once #include "detail/type_traits.h" -#define FIXEDMATH_VERSION_MAJOR 1 +#define FIXEDMATH_VERSION_MAJOR 2 #define FIXEDMATH_VERSION_MINOR 0 -#define FIXEDMATH_VERSION_PATCH 1 -#define FIXEDMATH_VERSION_STRING "1.0.1" - -namespace fixedmath -{ - //the idea behind carrier is to use it as carier of internal int64 value in format of fixed to distinguish it from int64 integral type. - struct fix_carrier_t - { - fixed_internal v {}; - - constexpr fix_carrier_t() noexcept = default; - - constexpr fix_carrier_t( fix_carrier_t && ) noexcept = default; - constexpr fix_carrier_t( fix_carrier_t const & ) noexcept = default; - constexpr fix_carrier_t & operator=( fix_carrier_t && ) noexcept = default; - constexpr fix_carrier_t & operator=( fix_carrier_t const & ) noexcept = default; - - template> - > - explicit constexpr fix_carrier_t( input_type const & value) noexcept : v{value} - {} - - ~fix_carrier_t() = default; - }; - - ///\brief hermetization of fixed value to avoid implicit conversions from int64, long long - struct fixed_t +#define FIXEDMATH_VERSION_PATCH 0 +#define FIXEDMATH_VERSION_STRING "2.0.0" + +namespace fixedmath::inline v2 + { +// the idea behind carrier is to use it as carier of internal int64 value in format of fixed to distinguish it from +// int64 integral type. +struct fix_carrier_t + { + fixed_internal v{}; + + constexpr fix_carrier_t() noexcept = default; + + explicit constexpr fix_carrier_t(std::same_as auto const & value) noexcept : v{value} {} + }; + +///\brief hermetization of fixed value to avoid implicit conversions from int64, long long +struct fixed_t + { + fixed_internal v{}; + + template + explicit constexpr operator arithmethic_type() const noexcept; + + constexpr fixed_t() noexcept = default; + + constexpr fixed_t(std::same_as auto value) noexcept : v{value.v} {} + + explicit constexpr fixed_t(concepts::arithmetic_and_not_fixed auto value) noexcept; + }; + +struct as_fixed_t + { + constexpr auto operator()(std::same_as auto carried) const noexcept -> fixed_t { - fixed_internal v {}; - - template> - > - explicit constexpr operator arithmethic_type() const noexcept; - - constexpr fixed_t() noexcept = default; - - constexpr fixed_t( fixed_t && ) noexcept = default; - constexpr fixed_t( fixed_t const & ) noexcept = default; - - constexpr fixed_t & operator=( fixed_t && ) noexcept = default; - constexpr fixed_t & operator=( fixed_t const & ) noexcept = default; - - constexpr fixed_t( fix_carrier_t value) noexcept : v{ value.v }{} - - template> - > - explicit constexpr fixed_t( arithmethic_type const & value ) noexcept; - - ~fixed_t() = default; - }; - - - ///\brief constructs fixed from raw value in internal format - constexpr fixed_t as_fixed( fixed_internal carried ) noexcept { return fix_carrier_t{carried}; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator != ( fixed_t l, fixed_t r ) noexcept { return l.v != r.v; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator == ( fixed_t l, fixed_t r ) noexcept { return l.v == r.v; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator > ( fixed_t l, fixed_t r ) noexcept { return l.v > r.v; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator >= ( fixed_t l, fixed_t r ) noexcept { return l.v >= r.v; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator < ( fixed_t l, fixed_t r ) noexcept { return l.v < r.v; } - - [[ nodiscard, gnu::const, gnu::always_inline ]] - constexpr bool - operator <= ( fixed_t l, fixed_t r ) noexcept { return l.v <= r.v; } - - -} + return fix_carrier_t{carried}; + } + }; + +///\brief constructs fixed from raw value in internal format +inline constexpr as_fixed_t as_fixed; + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator==(std::same_as auto l, std::same_as auto r) noexcept -> bool + { + return l.v == r.v; + } + +[[nodiscard, gnu::const, gnu::always_inline]] +constexpr auto operator<=>(std::same_as auto l, std::same_as auto r) noexcept + { + return l.v <=> r.v; + } + + } // namespace fixedmath::inline v2 diff --git a/fixed_lib/include/fixedmath/unittests/addition.h b/fixed_lib/include/fixedmath/unittests/addition.h deleted file mode 100644 index 135b9f7..0000000 --- a/fixed_lib/include/fixedmath/unittests/addition.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - //------------------------------------------------------------------------------------------------------ - // - // fixed_addition - // -[[nodiscard]] -constexpr bool addition_unit_tests() noexcept - { - static_assert( fixed_addition( 0_fix, 1_fix ) == 1_fix ); - static_assert( fixed_addition( 1_fix, 1_fix ) == 2_fix ); - static_assert( fixed_addition( 10_fix, 1_fix ) == 11_fix ); - static_assert( fixed_addition( -10_fix, 1_fix ) == -9_fix ); - - static_assert( 0_fix + 1_fix == 1_fix ); - static_assert( 1_fix + 1_fix == 2_fix ); - static_assert( 10.4_fix + 1_fix == 11.4_fix ); - static_assert( -10_fix+ 1_fix == -9_fix ); - - static_assert( 0_fix + 1 == 1_fix ); - static_assert( 1 + 1_fix == 2_fix ); - static_assert( 10.4 + 1_fix == 11.4 ); - static_assert( 10.5_fix + 10.2 == 20.7 ); - static_assert( -10.5_fix + uint8_t(10) == -0.5_fix ); - static_assert( -10.5_fix + uint16_t(10) == -0.5_fix ); - static_assert( -10.5_fix + uint32_t(10) == -0.5_fix ); - static_assert( -10.5_fix + uint64_t(10) == -0.5_fix ); - static_assert( uint8_t(10) + -10.5_fix == -.5_fix ); - static_assert( uint16_t(10) + -10.5_fix == -.5_fix ); - static_assert( uint32_t(10) + -10.5_fix == -.5_fix ); - static_assert( uint64_t(10) + -10.5_fix == -.5_fix ); - static_assert( -10_fix+ 1 == -9_fix ); - static_assert( 10.5_fix + -10. == .5 ); - static_assert( 10.5_fix + -10.f == .5_fix ); - static_assert( limits_::max() < limits_::quiet_NaN() ); - static_assert( limits_::lowest() +1 != limits_::quiet_NaN() ); - - static_assert( as_fixed(limits_::max().v- 65536) + 1_fix != limits_::quiet_NaN() ); - - static_assert( test_resulting_type( int64_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + int64_t(1) ) ); - static_assert( test_resulting_type( uint64_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + uint64_t(1) ) ); - static_assert( test_resulting_type( 1_fix + 1_fix ) ); - static_assert( test_resulting_type( 1 + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + 1 ) ); - static_assert( test_resulting_type( int16_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + int16_t(1) ) ); - static_assert( test_resulting_type( uint16_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + uint16_t(1) ) ); - static_assert( test_resulting_type( int8_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + int8_t(1) ) ); - static_assert( test_resulting_type( uint8_t(1) + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + uint8_t(1) ) ); - static_assert( test_resulting_type( 1.f + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + 1.f ) ); - static_assert( test_resulting_type( 1. + 1_fix ) ); - static_assert( test_resulting_type( 1_fix + 1. ) ); - - constexpr auto i1 = 1_fix; - constexpr auto i2 = 10_fix; - auto const & i1r { i1 }; - auto const & i2r { i2 }; - if( i1r + i2r != 11_fix ) - return false; - - return true; - } - - static_assert(addition_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/atan.h b/fixed_lib/include/fixedmath/unittests/atan.h deleted file mode 100644 index bb4bc33..0000000 --- a/fixed_lib/include/fixedmath/unittests/atan.h +++ /dev/null @@ -1,373 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - - constexpr bool test_atan( fixed_t x, double expected ) - { - constexpr double expected_precision = 0.00005; //0.000025 - return ut_abs(atan( x ) - expected ) < expected_precision && ut_abs(atan( -x ) - -expected ) < expected_precision; - } - - constexpr bool test_atan2( fixed_t y, fixed_t x, double expected ) - { - constexpr double expected_precision = 0.00005; //0.000025 - return ut_abs(atan2( y,x ) - expected ) < expected_precision; - } - -[[nodiscard]] -constexpr bool atan_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // atan - // - static_assert( test_atan( 1_fix/16,0.062418809995957)); - static_assert( test_atan( 3_fix/16,0.185347949995695)); - static_assert( test_atan( 5_fix/16,0.302884868374971)); - static_assert( test_atan( 7_fix/16,0.412410441597387)); - static_assert( test_atan( 8_fix/16,0.463647609000806)); - static_assert( test_atan( 9_fix/16,0.512389460310738)); - static_assert( test_atan( 11_fix/16,0.602287346134964)); - static_assert( test_atan( 13_fix/16,0.682316554874748)); - static_assert( test_atan( 15_fix/16,0.753151280962194)); - static_assert( test_atan( 17_fix/16,0.815691923316223)); - static_assert( test_atan( 19_fix/16,0.870903457075653)); - static_assert( test_atan( 21_fix/16,0.919719605350417)); - static_assert( test_atan( 25_fix/16,1.00148313569423)); - static_assert( test_atan( 37_fix/16,1.16264722303981)); - static_assert( test_atan( 39_fix/16,1.18147960496176)); - static_assert( test_atan( 40_fix/16,1.19028994968253)); - static_assert( test_atan( 45_fix/16,1.22918083614709)); - - - static_assert( test_atan2(-1/2_fix,-1/2_fix, -2.3561944901923448 )); - - //Thise are generated according to representation of fractions in fixed_t then std::atan2(static_castD:\projects\fixed_math\fixed_lib\include\fixedmath\unittests\addition.h(19,43): fatal error C1001: Wewnêtrzny b³¹d kompilatora. -//1 > (plik kompilatora „d : \A01\_work\2\s\src\vctools\Compiler\CxxFE\sl\p1\c\constexpr\constexpr.cpp”, wiersz 6887) - -#include "type_traits.h" -#include "integral_type_convertions.h" -#include "floating_point_type_convertions.h" -#include "fixed_construction.h" -#include "addition.h" -#include "substraction.h" -#include "multiplication.h" -#include "division.h" -#if defined(FIXEDMATH_ENABLE_SQRT_ABACUS_ALGO) -#include "sqrt.h" -#endif -#include "misc_functions.h" -#include "sin.h" -#include "tan.h" -#include "atan.h" diff --git a/fixed_lib/include/fixedmath/unittests/division.h b/fixed_lib/include/fixedmath/unittests/division.h deleted file mode 100644 index 3817b53..0000000 --- a/fixed_lib/include/fixedmath/unittests/division.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - //------------------------------------------------------------------------------------------------------ - // - // fixed_division - // -[[nodiscard]] -constexpr bool division_unit_tests() noexcept - { - static_assert( 1_fix / 1_fix == 1_fix ); - static_assert( -1_fix / 1_fix == -1_fix ); - static_assert( 1_fix / -1_fix == -1_fix ); - static_assert( -1_fix / -1_fix == 1_fix ); - static_assert( 1_fix / 1 == 1_fix ); - static_assert( 100_fix / 10_fix == 10_fix ); - static_assert( 100_fix / 10 == 10_fix ); - static_assert( -10_fix / 1 == -10_fix ); - static_assert( -10_fix / 1_fix == -10_fix ); - static_assert( 1_fix / 2_fix == 0.5_fix ); - static_assert( 1_fix / 4_fix == 0.25_fix ); - static_assert( -1_fix / 4 == -0.25_fix ); - - static_assert( int8_t{1} / -4_fix == -0.25_fix ); - static_assert( int16_t{1} / -4_fix == -0.25_fix ); - static_assert( int32_t{1} / -4_fix == -0.25_fix ); - static_assert( int64_t{1} / -4_fix == -0.25_fix ); - static_assert( float{1} / -4_fix == -0.25_fix ); - static_assert( double{1} / -4_fix == -0.25 ); - - static_assert( uint8_t{1} / -4_fix == -0.25_fix ); - static_assert( uint16_t{1} / -4_fix == -0.25_fix ); - static_assert( uint32_t{1} / -4_fix == -0.25_fix ); - static_assert( uint64_t{1} / -4_fix == -0.25_fix ); - - static_assert( -1_fix / uint8_t(4) == -0.25_fix ); - static_assert( -1_fix / uint16_t(4) == -0.25_fix ); - static_assert( -1_fix / uint32_t(4) == -0.25_fix ); - static_assert( -1_fix / uint64_t(4) == -0.25_fix ); - - static_assert( -1_fix / int8_t(4) == -0.25_fix ); - static_assert( -1_fix / int16_t(4) == -0.25_fix ); - static_assert( -1_fix / int32_t(4) == -0.25_fix ); - static_assert( -1_fix / int64_t(4) == -0.25_fix ); - - - static_assert( 1 / 4_fix == 0.25_fix ); - static_assert( test_resulting_type( int64_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / int64_t(1) ) ); - static_assert( test_resulting_type( uint64_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / uint64_t(1) ) ); - static_assert( test_resulting_type( 1_fix / 1_fix ) ); - static_assert( test_resulting_type( 1 / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / 1 ) ); - static_assert( test_resulting_type( int16_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / int16_t(1) ) ); - static_assert( test_resulting_type( uint16_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / uint16_t(1) ) ); - static_assert( test_resulting_type( int8_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / int8_t(1) ) ); - static_assert( test_resulting_type( uint8_t(1) / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / uint8_t(1) ) ); - static_assert( test_resulting_type( 1.f / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / 1.f ) ); - static_assert( test_resulting_type( 1. / 1_fix ) ); - static_assert( test_resulting_type( 1_fix / 1. ) ); - - return true; - } - - static_assert(division_unit_tests()); -} - diff --git a/fixed_lib/include/fixedmath/unittests/fixed_construction.h b/fixed_lib/include/fixedmath/unittests/fixed_construction.h deleted file mode 100644 index 3126274..0000000 --- a/fixed_lib/include/fixedmath/unittests/fixed_construction.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ -[[nodiscard]] -constexpr bool fixed_construction_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // fixed explicit arithemtic type constructor - // - static_assert( fixed_t{1} == 1_fix ); - static_assert( fixed_t{1u} == 1_fix ); - static_assert( fixed_t{1lu} == 1_fix ); - static_assert( fixed_t{1llu} == 1_fix ); - static_assert( fixed_t{-1} == -1_fix ); - static_assert( fixed_t{1.f} == 1_fix ); - static_assert( fixed_t{-1.f} == -1_fix ); - static_assert( fixed_t{2} == 2_fix ); - static_assert( fixed_t{-2} == -2_fix ); - static_assert( fixed_t{2.f} == 2_fix ); - static_assert( fixed_t{-2.f} == -2_fix ); - static_assert( fixed_t{4.f} == 4_fix ); - static_assert( fixed_t{-4.f} == -4_fix ); - - static_assert( fixed_t{ 4096ll } == 4096_fix ); - static_assert( fixed_t{ -4096ll } == -4096_fix ); - static_assert( fixed_t{ 4096llu } == 4096_fix ); - - return true; - } - - static_assert(fixed_construction_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/floating_point_type_convertions.h b/fixed_lib/include/fixedmath/unittests/floating_point_type_convertions.h deleted file mode 100644 index 230040d..0000000 --- a/fixed_lib/include/fixedmath/unittests/floating_point_type_convertions.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ -[[nodiscard]] -constexpr bool floating_point_type_convertions_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // floating_point_to_fixed unit tests - // - static_assert( floating_point_to_fixed(0.f) == 0_fix ); - static_assert( floating_point_to_fixed(-1.f) == -limits_::one() ); - static_assert( floating_point_to_fixed(-1.f) != limits_::one() ); - static_assert( floating_point_to_fixed(-1.f) != 0_fix ); - static_assert( floating_point_to_fixed(1.f) != 0_fix ); - static_assert( floating_point_to_fixed(1.f) != integral_to_fixed(-1) ); - static_assert( floating_point_to_fixed(1.f) == integral_to_fixed(1) ); - static_assert( floating_point_to_fixed(0.f) == 0_fix ); - static_assert( floating_point_to_fixed(float(limits_::max_integral())) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(flimits_::max()) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(float(limits_::max_integral()+1ll)) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(float(limits_::min_integral())) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(float(limits_::min_integral()-1ll)) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(flimits_::lowest()) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(flimits_::min()) != limits_::quiet_NaN() ); - - static_assert( floating_point_to_fixed(-1.) == -limits_::one() ); - static_assert( floating_point_to_fixed(-1.) != limits_::one() ); - static_assert( floating_point_to_fixed(-1.) != 0_fix ); - static_assert( floating_point_to_fixed(1.) != 0_fix ); - static_assert( floating_point_to_fixed(1.) != integral_to_fixed(-1) ); - static_assert( floating_point_to_fixed(1.) == integral_to_fixed(1) ); - static_assert( floating_point_to_fixed(double(limits_::max_integral())) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(double(limits_::max_integral()-1ll)) != limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(double(limits_::max_integral()+1ll)) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(double(limits_::min_integral())) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(double(limits_::min_integral()-1ll)) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(double(limits_::min_integral()+1ll)) != limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(dlimits_::lowest()) == limits_::quiet_NaN() ); - static_assert( floating_point_to_fixed(dlimits_::min()) != limits_::quiet_NaN() ); - - //------------------------------------------------------------------------------------------------------ - // - // fixed_to_floating_point - // - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.f)) == 0.f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(1.f)) == 1.f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.25f)) == 0.25f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.5f)) == 0.5f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.75f)) == 0.75f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-1.f)) == -1.f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.25f)) == -0.25f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.5f)) == -0.5f ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.75f)) == -0.75f ); - - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.f)) == 0. ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(1.f)) == 1. ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.25f)) == 0.25 ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.5f)) == 0.5 ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(0.75f)) == 0.75 ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-1.f)) == -1. ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.25f)) == -0.25 ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.5f)) == -0.5 ); - static_assert( fixed_to_floating_point(floating_point_to_fixed(-0.75f)) == -0.75 ); - return true; - } - - static_assert(floating_point_type_convertions_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/integral_type_convertions.h b/fixed_lib/include/fixedmath/unittests/integral_type_convertions.h deleted file mode 100644 index 9745620..0000000 --- a/fixed_lib/include/fixedmath/unittests/integral_type_convertions.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ -[[nodiscard]] -constexpr bool integral_type_convertions_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // integral_to_fixed unit tests - // - static_assert( integral_to_fixed(0) == 0_fix ); - static_assert( integral_to_fixed(1) == limits_::one() ); - static_assert( integral_to_fixed(-1) == -limits_::one() ); - static_assert( integral_to_fixed(-1) != limits_::one() ); - static_assert( integral_to_fixed(-1) != 0_fix ); - static_assert( integral_to_fixed(1) != 0_fix ); - static_assert( integral_to_fixed(1) != integral_to_fixed(-1) ); - static_assert( integral_to_fixed(1) == integral_to_fixed(1) ); - - static_assert( 0_fix == fixed_t{}); - static_assert( 1_fix == limits_::one()); - static_assert( -1_fix == -limits_::one()); - static_assert( as_fixed(0x80000000LL) == 32768_fix); - static_assert( as_fixed(0) == 0_fix); - static_assert( as_fixed(1ll<<32) == 65536_fix ); - - //------------------------------------------------------------------------------------------------------ - // - // fixed_to_integral - // - static_assert( fixed_to_integral(0.25_fix) == 0 ); - static_assert( fixed_to_integral(1.25_fix) == 1 ); - static_assert( fixed_to_integral(100.25_fix) == 100 ); - static_assert( fixed_to_integral(100.55_fix) == 100 ); - static_assert( fixed_to_integral(100.55_fix) == 100 ); - return true; - } - static_assert(integral_type_convertions_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/misc_functions.h b/fixed_lib/include/fixedmath/unittests/misc_functions.h deleted file mode 100644 index 898d2b1..0000000 --- a/fixed_lib/include/fixedmath/unittests/misc_functions.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ -[[nodiscard]] -constexpr bool misc_functions_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // ceil - // - static_assert( ceil(-0.25_fix) == 0_fix ); - static_assert( ceil(-1.25_fix) == -1_fix ); - static_assert( ceil(-10.25_fix) == -10_fix ); - static_assert( ceil(-10.95_fix) == -10_fix ); - static_assert( ceil(0.25_fix) == 1_fix ); - static_assert( ceil(0.75_fix) == 1_fix ); - static_assert( ceil(as_fixed(1)) == 1_fix ); - static_assert( ceil(5.25_fix) == 6_fix ); - - //------------------------------------------------------------------------------------------------------ - // - // floor - // - static_assert( fixed_to_integral(floor(0.25_fix)) == 0 ); - static_assert( floor( -1_fix + limits_::epsilon()) == -1_fix ); // - static_assert( floor( -1_fix - limits_::epsilon()) == -2_fix ); // - static_assert( floor(-0.25_fix) == -1_fix ); - static_assert( floor(0.25_fix) == 0_fix ); - static_assert( floor(0.95_fix) == 0_fix ); - static_assert( floor(1.25_fix) == 1_fix ); - static_assert( floor(-1.25_fix) == -2_fix ); - - //------------------------------------------------------------------------------------------------------ - // - // angle_to_radians - // - static_assert( angle_to_radians(0) == 0_fix ); - static_assert( angle_to_radians(180) == 3.1415926536_fix ); - static_assert( angle_to_radians(180) == phi ); - static_assert( angle_to_radians(90) == phi/2 ); - static_assert( angle_to_radians(45) == phi/4 ); - - return true; - } - - static_assert(misc_functions_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/multiplication.h b/fixed_lib/include/fixedmath/unittests/multiplication.h deleted file mode 100644 index d297d12..0000000 --- a/fixed_lib/include/fixedmath/unittests/multiplication.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ -[[nodiscard]] -constexpr bool multiplication_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // fixed_multiply - // - static_assert( 1_fix * 1_fix == 1_fix ); - static_assert( 10_fix * 0.5_fix == 5_fix ); - static_assert( abs(0.8_fix * 0.2_fix) - 0.16_fix <= limits_::epsilon() ); - static_assert( abs(0.8_fix * -0.2_fix) > 0_fix ); - - static_assert( -1.25_fix * int8_t(4) == -5_fix ); - static_assert( -1.25_fix * int16_t(4) == -5_fix ); - static_assert( -1.25_fix * int32_t(4) == -5_fix ); - static_assert( -1.25_fix * int64_t(4) == -5_fix ); - - static_assert( -1.25_fix * uint8_t(4) == -5_fix ); - static_assert( -1.25_fix * uint16_t(4) == -5_fix ); - static_assert( -1.25_fix * uint32_t(4) == -5_fix ); - static_assert( -1.25_fix * uint64_t(4) == -5_fix ); - - static_assert( int8_t(4) * -1.25_fix == -5_fix ); - static_assert( int16_t(4) * -1.25_fix == -5_fix ); - static_assert( int32_t(4) * -1.25_fix == -5_fix ); - static_assert( int64_t(4) * -1.25_fix == -5_fix ); - - static_assert( uint8_t(4) * -1.25_fix == -5_fix ); - static_assert( uint16_t(4) * -1.25_fix == -5_fix ); - static_assert( uint32_t(4) * -1.25_fix == -5_fix ); - static_assert( uint64_t(4) * -1.25_fix == -5_fix ); - - static_assert( test_resulting_type( int64_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * int64_t(1) ) ); - static_assert( test_resulting_type( uint64_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * uint64_t(1) ) ); - static_assert( test_resulting_type( 1_fix * 1_fix ) ); - static_assert( test_resulting_type( 1 * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * 1 ) ); - static_assert( test_resulting_type( int16_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * int16_t(1) ) ); - static_assert( test_resulting_type( uint16_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * uint16_t(1) ) ); - static_assert( test_resulting_type( int8_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * int8_t(1) ) ); - static_assert( test_resulting_type( uint8_t(1) * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * uint8_t(1) ) ); - static_assert( test_resulting_type( 1.f * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * 1.f ) ); - static_assert( test_resulting_type( 1. * 1_fix ) ); - static_assert( test_resulting_type( 1_fix * 1. ) ); - - return true; - } - - static_assert(multiplication_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/sin.h b/fixed_lib/include/fixedmath/unittests/sin.h deleted file mode 100644 index e527ad6..0000000 --- a/fixed_lib/include/fixedmath/unittests/sin.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - constexpr bool test_sin( fixed_t x, fixed_t expected ) - { - return abs(sin( x ) - expected ) < 0.0001_fix && - abs(sin( x + 2*phi ) - expected ) < 0.0001_fix && - abs(sin( x - 2*phi ) - expected ) < 0.0001_fix && - abs(sin( x + 4*phi ) - expected ) < 0.0001_fix; - } - - constexpr bool test_cos( fixed_t x, fixed_t expected ) - { - return abs(cos( x ) - expected ) < 0.0001_fix && - abs(cos( x + 2*phi ) - expected ) < 0.0001_fix && - abs(cos( x - 2*phi ) - expected ) < 0.0001_fix && - abs(cos( x + 4*phi ) - expected ) < 0.0001_fix; - } -[[nodiscard]] -constexpr bool sin_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // sin - // - - static_assert( test_sin( phi + phi/2 , -0.9998626708984375_fix )); - static_assert( test_sin( phi + phi/4 , -0.7071075439453125_fix )); - static_assert( test_sin( phi, 0_fix )); - static_assert( test_sin( 0_fix , 0_fix )); - static_assert( test_sin( phi /2 + phi/4, 0.7071075439453125_fix )); - - static_assert( test_sin( phi/2_fix, 0.9998474121093750_fix )); - static_assert( test_sin( phi/4_fix, 0.7070922851562500_fix )); - static_assert( test_sin( phi/5_fix, 0.5877838134765625_fix )); - static_assert( test_sin( phi/8_fix, 0.3826599121093750_fix )); - static_assert( test_sin( phi/16_fix, 0.1950683593750000_fix )); - static_assert( test_sin(-phi/16_fix, -0.1950836181640625_fix )); - static_assert( test_sin( phi/-8_fix, -0.3826751708984375_fix )); - static_assert( test_sin( phi/-5_fix, -0.5877990722656250_fix )); - static_assert( test_sin( phi/-4_fix, -0.7071075439453125_fix )); - static_assert( test_sin( phi/-2_fix, -0.9998626708984375_fix )); - - static_assert( test_sin( phi + phi + phi/2, 0.9998474121093750_fix)); - static_assert( test_sin( phi + phi + phi/4, 0.7070922851562500_fix)); - static_assert( test_sin( phi + phi, 0_fix)); - static_assert( test_sin( phi + phi /2 + phi/4, -0.7071228027343750_fix)); - static_assert( test_sin( 2*phi + phi + phi/2, -0.9998626708984375_fix)); - static_assert( test_sin( 2*phi + phi + phi/4, -0.7071075439453125_fix)); - static_assert( test_sin( 2*phi + phi, 0_fix)); - static_assert( test_sin( 2*phi + phi /2 + phi/4, 0.7071075439453125_fix)); - - static_assert( test_sin( -phi-phi /16, 0.1950683593750000_fix )); - static_assert( test_sin( -phi-phi /8, 0.3826599121093750_fix )); - static_assert( test_sin( -phi-phi /5, 0.5877838134765625_fix )); - static_assert( test_sin( -phi-phi /4, 0.7070922851562500_fix )); - static_assert( test_sin( -phi-phi /2, 0.9998474121093750_fix )); - - static_assert( test_sin( -6*phi + -95* phi / 180, -0.9961242675781250_fix )); - static_assert( test_sin( -4*phi + -95* phi / 180, -0.9961242675781250_fix )); - static_assert( test_sin( -2*phi + -95* phi / 180, -0.9961242675781250_fix )); - static_assert( test_sin( -95* phi / 180, -0.9961242675781250_fix )); - static_assert( test_sin( -90* phi / 180, -0.9998626708984375_fix )); - static_assert( test_sin( -85* phi / 180, -0.9961090087890625_fix )); - - //------------------------------------------------------------------------------------------------------ - // - // cos - // - - static_assert( test_cos( 2 * phi, 0.9998474121093750_fix )); - static_assert( test_cos( phi, -0.9998626708984375_fix )); - static_assert( test_cos( phi /2 + phi/4, -0.7071075439453125_fix )); - static_assert( test_cos( phi /2, 0_fix )); - static_assert( test_cos( phi /3, 0.4999847412109375_fix )); - static_assert( test_cos( phi /4, 0.7071075439453125_fix )); - static_assert( test_cos( phi /16, 0.9807281494140625_fix )); - static_assert( test_cos( 0_fix, 0.9998474121093750_fix )); - static_assert( test_cos( -phi /16, 0.9807434082031250_fix )); - static_assert( test_cos( -phi /4, 0.7071075439453125_fix )); - static_assert( test_cos( -phi /3, 0.5000000000000000_fix )); - static_assert( test_cos( -phi /2, 0.0001_fix )); - static_assert( test_cos( -phi /2 + -phi/4, -0.7070922851562500_fix )); - static_assert( test_cos( -phi, -0.9998626708984375_fix )); - static_assert( test_cos( 2 * -phi, 0.9998474121093750_fix )); - - return true; - } - - static_assert(sin_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/sqrt.h b/fixed_lib/include/fixedmath/unittests/sqrt.h deleted file mode 100644 index 03e5309..0000000 --- a/fixed_lib/include/fixedmath/unittests/sqrt.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - constexpr bool test_hypot( fixed_t x, fixed_t y, fixed_t expected ) - { - return abs( hypot( x, y ) - expected ) < 0.00001_fix && - abs( hypot( -x, y ) - expected ) < 0.00001_fix && - abs( hypot( x, -y ) - expected ) < 0.00001_fix && - abs( hypot( -x, -y ) - expected ) < 0.00001_fix; - } - -[[nodiscard]] -constexpr bool sqrt_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // sqrt - // - static_assert( sqrt(1.4111175537109375_fix) == 1.1878967285156250_fix); - static_assert( sqrt(2.0000000000000000_fix) == 1.4141998291015625_fix); - static_assert( sqrt(2.0124969482421875_fix) == 1.4186248779296875_fix); - static_assert( sqrt(3.3333282470703125_fix) == 1.8257293701171875_fix); - static_assert( sqrt(4.0000000000000000_fix) == 2.0000000000000000_fix); - static_assert( sqrt(3331.0000000000000000_fix) == 57.7148132324218750_fix); - static_assert( sqrt(33331.0000000000000000_fix) == 182.5677947998046875_fix); - static_assert( sqrt(333331.1000061035156250_fix) == 577.3483276367187500_fix); - static_assert( sqrt(3333331.0215148925781250_fix) == 1825.7412109375000000_fix); - //------------------------------------------------------------------------------------------------------ - // - // hypot - // - - static_assert( test_hypot(-14.991608_fix,-0.837158_fix, 15.0149536132812500_fix)); - static_assert( test_hypot(-14.991608_fix,-0.837158_fix, 15.0149536132812500_fix)); - static_assert( test_hypot(-0.774933_fix,-4.295090_fix, 4.3644256591796875_fix)); - static_assert( test_hypot(-20.245346_fix,-0.909424_fix, 20.2657470703125_fix)); - static_assert( test_hypot(14.9916076660156250_fix,0_fix, 14.9916076660156250_fix)); - static_assert( test_hypot(0_fix, 14.9916076660156250_fix, 14.9916076660156250_fix)); - - static_assert( test_hypot(as_fixed(1ul<<30),as_fixed(1<<0ul), 16384_fix) ); - static_assert( test_hypot(as_fixed(1ul<<33),as_fixed(1ul<<31), 135104_fix) ); - static_assert( test_hypot(as_fixed(1ul<<32),as_fixed(1ul<<31), 73270_fix)); - static_assert( test_hypot(as_fixed(1ul<<31),as_fixed(1ul<<31), 46340_fix)); - static_assert( test_hypot(as_fixed(1ul<<32),as_fixed(1ul), 65536_fix)); - static_assert( test_hypot(as_fixed(1ul<<30),as_fixed(1<<30ul), 23170_fix)); - static_assert( test_hypot(as_fixed((1ul<<30)-1), as_fixed((1ul<<30)-1), 23170.4749755859375_fix) ); - - static_assert( test_hypot(as_fixed(1),as_fixed(1), 0.0000152587890625_fix)); - static_assert( test_hypot(as_fixed(2),as_fixed(2), 0.0000305175781250_fix)); - static_assert( test_hypot(as_fixed(1),as_fixed(3), 0.0000457763671875_fix)); - static_assert( test_hypot(as_fixed(2),as_fixed(3), 0.0000457763671875_fix)); - static_assert( test_hypot(0.0125_fix,0.125_fix, 0.1256103515625000_fix)); - static_assert( test_hypot(1_fix,1_fix, 1.4141998291015625_fix)); - static_assert( test_hypot(0.5_fix,0.25_fix, 0.5590057373046875_fix)); - - return true; - } - - static_assert(sqrt_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/substraction.h b/fixed_lib/include/fixedmath/unittests/substraction.h deleted file mode 100644 index aafa507..0000000 --- a/fixed_lib/include/fixedmath/unittests/substraction.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - //------------------------------------------------------------------------------------------------------ - // - // fixed_substract - // -[[nodiscard]] -constexpr bool substraction_unit_tests() noexcept - { - static_assert( 0.2_fix - 1.2_fix == -1_fix ); - static_assert( 3.2_fix - 1.2_fix == 2_fix ); - static_assert( -4.2_fix - 1.2_fix == -5.4_fix ); - static_assert( -4.2_fix + 1.2_fix == -3_fix ); - static_assert( 1_fix - 1. == 1. - 1. ); - static_assert( 2_fix - 1. == 2. - 1. ); - static_assert( -2_fix - 1. == -2. - 1. ); - static_assert( -2_fix + 1. == -2. + 1. ); - static_assert( -10.5_fix - uint8_t(10) == -20.5_fix ); - static_assert( -10.5_fix - uint16_t(10) == -20.5_fix ); - static_assert( -10.5_fix - uint32_t(10) == -20.5_fix ); - static_assert( -10.5_fix - uint64_t(10) == -20.5_fix ); - static_assert( uint8_t(10) -10.5_fix == -.5_fix ); - static_assert( uint16_t(10) -10.5_fix == -.5_fix ); - static_assert( uint32_t(10) -10.5_fix == -.5_fix ); - static_assert( uint64_t(10) -10.5_fix == -.5_fix ); - static_assert( limits_::max() -1 != limits_::quiet_NaN() ); - - static_assert( test_resulting_type( int64_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - int64_t(1) ) ); - static_assert( test_resulting_type( uint64_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - uint64_t(1) ) ); - static_assert( test_resulting_type( 1_fix - 1_fix ) ); - static_assert( test_resulting_type( 1 - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - 1 ) ); - static_assert( test_resulting_type( int16_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - int16_t(1) ) ); - static_assert( test_resulting_type( uint16_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - uint16_t(1) ) ); - static_assert( test_resulting_type( int8_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - int8_t(1) ) ); - static_assert( test_resulting_type( uint8_t(1) - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - uint8_t(1) ) ); - static_assert( test_resulting_type( 1.f - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - 1.f ) ); - static_assert( test_resulting_type( 1. - 1_fix ) ); - static_assert( test_resulting_type( 1_fix - 1. ) ); - - return true; - } - static_assert(substraction_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/tan.h b/fixed_lib/include/fixedmath/unittests/tan.h deleted file mode 100644 index aa480e3..0000000 --- a/fixed_lib/include/fixedmath/unittests/tan.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - //------------------------------------------------------------------------------------------------------ - // - // tan - // - constexpr bool test_tan( fixed_t x, double expected ) - { - return ut_abs(tan( x ) - expected ) < 0.0001 && ut_abs(tan( -x ) - -expected ) < 0.0001; - } -[[nodiscard]] -constexpr bool tan_unit_tests() noexcept - { - static_assert(test_tan( phi /2 + phi /32 , -10.155854941143394 )); - static_assert(test_tan( phi /3, 1.7320423410947752 )); - static_assert(test_tan( phi /4, 0.9999739372166156 )); - static_assert(test_tan( phi /5, 0.7265312623733221 )); - static_assert(test_tan( phi /8, 0.4141969903665098 )); - static_assert(test_tan( phi /16, 0.1988970837416414 )); - static_assert(test_tan( 0_fix , 0.)); - - return true; - } - - static_assert(tan_unit_tests()); -} diff --git a/fixed_lib/include/fixedmath/unittests/type_traits.h b/fixed_lib/include/fixedmath/unittests/type_traits.h deleted file mode 100644 index 82102e1..0000000 --- a/fixed_lib/include/fixedmath/unittests/type_traits.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include "unit_test_common.h" - -namespace fixedmath -{ - -using detail::limits_; -using detail::flimits_; -using detail::dlimits_; -[[nodiscard]] -constexpr bool type_traits_unit_tests() noexcept - { - //------------------------------------------------------------------------------------------------------ - // - // type traits - // - using detail::is_fixed_v; - - static_assert( is_fixed_v ); - static_assert( !is_fixed_v ); - static_assert( !is_fixed_v ); - - using detail::is_double_v; - static_assert( is_double_v ); - static_assert( !is_double_v ); - static_assert( !is_double_v ); - - using detail::is_integral_v; - static_assert( is_integral_v ); - static_assert( is_integral_v ); - static_assert( is_integral_v ); - static_assert( is_integral_v ); - static_assert( !is_integral_v ); - static_assert( !is_integral_v ); - - using detail::is_signed_v; - static_assert( is_signed_v ); - static_assert( is_signed_v ); - static_assert( is_signed_v ); - static_assert( is_signed_v ); - static_assert( is_signed_v ); - static_assert( is_signed_v ); - static_assert( !is_signed_v ); - static_assert( !is_signed_v ); - static_assert( !is_signed_v ); - static_assert( !is_signed_v ); - static_assert( is_signed_v ); - - using detail::is_unsigned_v; - static_assert( !is_unsigned_v ); - static_assert( !is_unsigned_v ); - static_assert( !is_unsigned_v ); - static_assert( !is_unsigned_v ); - static_assert( !is_unsigned_v ); - static_assert( !is_unsigned_v ); - static_assert( is_unsigned_v ); - static_assert( is_unsigned_v ); - static_assert( is_unsigned_v ); - static_assert( is_unsigned_v ); - static_assert( !is_unsigned_v ); - - using detail::is_arithmetic_v; - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - static_assert( detail::is_arithmetic_v ); - - using detail::is_floating_point_v; - - using detail::is_arithmetic_and_not_fixed_v; - static_assert( !is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - static_assert( is_arithmetic_and_not_fixed_v ); - - using detail::arithmetic_and_one_is_fixed_v; - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( arithmetic_and_one_is_fixed_v ); - static_assert( !arithmetic_and_one_is_fixed_v ); - static_assert( !arithmetic_and_one_is_fixed_v ); - - using detail::one_of_is_double_v; - static_assert( !one_of_is_double_v ); - static_assert( !one_of_is_double_v ); - static_assert( one_of_is_double_v ); - static_assert( !one_of_is_double_v ); - static_assert( !one_of_is_double_v ); - static_assert( one_of_is_double_v ); - static_assert( !one_of_is_double_v ); - static_assert( !one_of_is_double_v ); - static_assert( one_of_is_double_v ); - - return true; - } - - static_assert(type_traits_unit_tests()); -} - diff --git a/fixed_lib/include/fixedmath/unittests/unit_test_common.h b/fixed_lib/include/fixedmath/unittests/unit_test_common.h deleted file mode 100644 index f73c01c..0000000 --- a/fixed_lib/include/fixedmath/unittests/unit_test_common.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include - -namespace fixedmath -{ - using detail::limits_; - using detail::flimits_; - using detail::dlimits_; - - - #define make_const_value(x) const_val - #define static_assert_equal(x, y) static_assert( assert_equal_t< make_const_value( x ), make_const_value( y ) >::eq() ) - - template - struct const_val { - static constexpr T value { val }; - constexpr const_val() = default; - constexpr const_val(T) {} - }; - - template - constexpr bool test_resulting_type( input ) { return std::is_same::value; } - - //llvm11 libcxx is not constexpr ready - template>> - constexpr value_type ut_abs( value_type value ) - { - static_assert( detail::is_arithmetic_v ); - return value > value_type{0} ? value : -value; - } -} diff --git a/fixed_lib/src/cos_angle_table.h b/fixed_lib/src/cos_angle_table.h deleted file mode 100644 index b575dc6..0000000 --- a/fixed_lib/src/cos_angle_table.h +++ /dev/null @@ -1,202 +0,0 @@ -#pragma once -// generated on Jan 11 2021 20:12:50 -#include - -#include -#include -#include -#include - -namespace fixedmath { - -// cosine of full circle for input in degrees -static std::array cos_angle_table__ { - - 65536ll /* cos(0) ~=1.0000000000000000*/, 65526ll /* cos(0.0174532572428385) ~=0.9998474121093750*/, - 65496ll /* cos(0.0349065144856771) ~=0.9993896484375000*/, 65446ll /* cos(0.0523597717285156) ~=0.9986267089843750*/, - 65376ll /* cos(0.0698130289713542) ~=0.9975585937500000*/, 65287ll /* cos(0.0872662862141927) ~=0.9962005615234375*/, - 65177ll /* cos(0.1047195434570312) ~=0.9945220947265625*/, 65048ll /* cos(0.1221728006998698) ~=0.9925537109375000*/, - 64898ll /* cos(0.1396260579427083) ~=0.9902648925781250*/, 64729ll /* cos(0.1570793151855469) ~=0.9876861572265625*/, - 64540ll /* cos(0.1745325724283854) ~=0.9848022460937500*/, 64332ll /* cos(0.1919858296712240) ~=0.9816284179687500*/, - 64104ll /* cos(0.2094390869140625) ~=0.9781494140625000*/, 63856ll /* cos(0.2268923441569010) ~=0.9743652343750000*/, - 63589ll /* cos(0.2443456013997396) ~=0.9702911376953125*/, 63303ll /* cos(0.2617988586425781) ~=0.9659271240234375*/, - 62997ll /* cos(0.2792521158854167) ~=0.9612579345703125*/, 62672ll /* cos(0.2967053731282552) ~=0.9562988281250000*/, - 62328ll /* cos(0.3141586303710938) ~=0.9510498046875000*/, 61966ll /* cos(0.3316118876139323) ~=0.9455261230468750*/, - 61584ll /* cos(0.3490651448567708) ~=0.9396972656250000*/, 61183ll /* cos(0.3665184020996094) ~=0.9335784912109375*/, - 60764ll /* cos(0.3839716593424479) ~=0.9271850585937500*/, 60326ll /* cos(0.4014249165852865) ~=0.9205017089843750*/, - 59870ll /* cos(0.4188781738281250) ~=0.9135437011718750*/, 59396ll /* cos(0.4363314310709636) ~=0.9063110351562500*/, - 58903ll /* cos(0.4537846883138021) ~=0.8987884521484375*/, 58393ll /* cos(0.4712379455566406) ~=0.8910064697265625*/, - 57865ll /* cos(0.4886912027994791) ~=0.8829498291015625*/, 57319ll /* cos(0.5061444600423177) ~=0.8746185302734375*/, - 56756ll /* cos(0.5235977172851562) ~=0.8660278320312500*/, 56175ll /* cos(0.5410509745279948) ~=0.8571624755859375*/, - 55578ll /* cos(0.5585042317708333) ~=0.8480529785156250*/, 54963ll /* cos(0.5759574890136718) ~=0.8386688232421875*/, - 54332ll /* cos(0.5934107462565105) ~=0.8290405273437500*/, 53684ll /* cos(0.6108640034993490) ~=0.8191528320312500*/, - 53020ll /* cos(0.6283172607421875) ~=0.8090209960937500*/, 52339ll /* cos(0.6457705179850260) ~=0.7986297607421875*/, - 51643ll /* cos(0.6632237752278646) ~=0.7880096435546875*/, 50931ll /* cos(0.6806770324707031) ~=0.7771453857421875*/, - 50204ll /* cos(0.6981302897135416) ~=0.7660522460937500*/, 49461ll /* cos(0.7155835469563802) ~=0.7547149658203125*/, - 48703ll /* cos(0.7330368041992188) ~=0.7431488037109375*/, 47930ll /* cos(0.7504900614420573) ~=0.7313537597656250*/, - 47143ll /* cos(0.7679433186848958) ~=0.7193450927734375*/, 46341ll /* cos(0.7853965759277344) ~=0.7071075439453125*/, - 45525ll /* cos(0.8028498331705729) ~=0.6946563720703125*/, 44696ll /* cos(0.8203030904134114) ~=0.6820068359375000*/, - 43852ll /* cos(0.8377563476562500) ~=0.6691284179687500*/, 42996ll /* cos(0.8552096048990886) ~=0.6560668945312500*/, - 42126ll /* cos(0.8726628621419271) ~=0.6427917480468750*/, 41243ll /* cos(0.8901161193847656) ~=0.6293182373046875*/, - 40348ll /* cos(0.9075693766276042) ~=0.6156616210937500*/, 39441ll /* cos(0.9250226338704427) ~=0.6018218994140625*/, - 38521ll /* cos(0.9424758911132812) ~=0.5877838134765625*/, 37590ll /* cos(0.9599291483561198) ~=0.5735778808593750*/, - 36647ll /* cos(0.9773824055989583) ~=0.5591888427734375*/, 35694ll /* cos(0.9948356628417969) ~=0.5446472167968750*/, - 34729ll /* cos(1.0122889200846354) ~=0.5299224853515625*/, 33754ll /* cos(1.0297421773274740) ~=0.5150451660156250*/, - 32768ll /* cos(1.0471954345703125) ~=0.5000000000000000*/, 31773ll /* cos(1.0646486918131510) ~=0.4848175048828125*/, - 30767ll /* cos(1.0821019490559896) ~=0.4694671630859375*/, 29753ll /* cos(1.0995552062988281) ~=0.4539947509765625*/, - 28729ll /* cos(1.1170084635416666) ~=0.4383697509765625*/, 27697ll /* cos(1.1344617207845051) ~=0.4226226806640625*/, - 26656ll /* cos(1.1519149780273437) ~=0.4067382812500000*/, 25607ll /* cos(1.1693682352701822) ~=0.3907318115234375*/, - 24550ll /* cos(1.1868214925130209) ~=0.3746032714843750*/, 23486ll /* cos(1.2042747497558595) ~=0.3583679199218750*/, - 22415ll /* cos(1.2217280069986980) ~=0.3420257568359375*/, 21337ll /* cos(1.2391812642415365) ~=0.3255767822265625*/, - 20252ll /* cos(1.2566345214843750) ~=0.3090209960937500*/, 19161ll /* cos(1.2740877787272136) ~=0.2923736572265625*/, - 18064ll /* cos(1.2915410359700521) ~=0.2756347656250000*/, 16962ll /* cos(1.3089942932128906) ~=0.2588195800781250*/, - 15855ll /* cos(1.3264475504557292) ~=0.2419281005859375*/, 14743ll /* cos(1.3439008076985677) ~=0.2249603271484375*/, - 13626ll /* cos(1.3613540649414062) ~=0.2079162597656250*/, 12505ll /* cos(1.3788073221842447) ~=0.1908111572265625*/, - 11380ll /* cos(1.3962605794270833) ~=0.1736450195312500*/, 10252ll /* cos(1.4137138366699218) ~=0.1564331054687500*/, - 9121ll /* cos(1.4311670939127603) ~=0.1391754150390625*/, 7987ll /* cos(1.4486203511555991) ~=0.1218719482421875*/, - 6851ll /* cos(1.4660736083984376) ~=0.1045379638671875*/, 5712ll /* cos(1.4835268656412761) ~=0.0871582031250000*/, - 4572ll /* cos(1.5009801228841146) ~=0.0697631835937500*/, 3430ll /* cos(1.5184333801269532) ~=0.0523376464843750*/, - 2287ll /* cos(1.5358866373697917) ~=0.0348968505859375*/, 1144ll /* cos(1.5533398946126302) ~=0.0174560546875000*/, - 0ll /* cos(1.5707931518554688) ~=0.0000000000000000*/, -1144ll /* cos(1.5882464090983073) ~=-0.0174560546875000*/, - -2287ll /* cos(1.6056996663411458) ~=-0.0348968505859375*/, -3430ll /* cos(1.6231529235839843) ~=-0.0523376464843750*/, - -4571ll /* cos(1.6406061808268229) ~=-0.0697479248046875*/, -5712ll /* cos(1.6580594380696614) ~=-0.0871582031250000*/, - -6850ll /* cos(1.6755126953124999) ~=-0.1045227050781250*/, -7987ll /* cos(1.6929659525553384) ~=-0.1218719482421875*/, - -9121ll /* cos(1.7104192097981772) ~=-0.1391754150390625*/, -10252ll /* cos(1.7278724670410157) ~=-0.1564331054687500*/, - -11380ll /* cos(1.7453257242838542) ~=-0.1736450195312500*/, -12505ll /* cos(1.7627789815266928) ~=-0.1908111572265625*/, - -13625ll /* cos(1.7802322387695313) ~=-0.2079010009765625*/, -14742ll /* cos(1.7976854960123698) ~=-0.2249450683593750*/, - -15854ll /* cos(1.8151387532552083) ~=-0.2419128417968750*/, -16962ll /* cos(1.8325920104980469) ~=-0.2588195800781250*/, - -18064ll /* cos(1.8500452677408854) ~=-0.2756347656250000*/, -19161ll /* cos(1.8674985249837239) ~=-0.2923736572265625*/, - -20252ll /* cos(1.8849517822265625) ~=-0.3090209960937500*/, -21336ll /* cos(1.9024050394694010) ~=-0.3255615234375000*/, - -22414ll /* cos(1.9198582967122395) ~=-0.3420104980468750*/, -23486ll /* cos(1.9373115539550780) ~=-0.3583679199218750*/, - -24550ll /* cos(1.9547648111979166) ~=-0.3746032714843750*/, -25607ll /* cos(1.9722180684407553) ~=-0.3907318115234375*/, - -26656ll /* cos(1.9896713256835938) ~=-0.4067382812500000*/, -27696ll /* cos(2.0071245829264321) ~=-0.4226074218750000*/, - -28729ll /* cos(2.0245778401692709) ~=-0.4383697509765625*/, -29752ll /* cos(2.0420310974121092) ~=-0.4539794921875000*/, - -30767ll /* cos(2.0594843546549479) ~=-0.4694671630859375*/, -31772ll /* cos(2.0769376118977863) ~=-0.4848022460937500*/, - -32768ll /* cos(2.0943908691406250) ~=-0.5000000000000000*/, -33753ll /* cos(2.1118441263834637) ~=-0.5150299072265625*/, - -34729ll /* cos(2.1292973836263021) ~=-0.5299224853515625*/, -35693ll /* cos(2.1467506408691408) ~=-0.5446319580078125*/, - -36647ll /* cos(2.1642038981119791) ~=-0.5591888427734375*/, -37590ll /* cos(2.1816571553548179) ~=-0.5735778808593750*/, - -38521ll /* cos(2.1991104125976562) ~=-0.5877838134765625*/, -39440ll /* cos(2.2165636698404949) ~=-0.6018066406250000*/, - -40348ll /* cos(2.2340169270833332) ~=-0.6156616210937500*/, -41243ll /* cos(2.2514701843261720) ~=-0.6293182373046875*/, - -42125ll /* cos(2.2689234415690103) ~=-0.6427764892578125*/, -42995ll /* cos(2.2863766988118490) ~=-0.6560516357421875*/, - -43852ll /* cos(2.3038299560546873) ~=-0.6691284179687500*/, -44695ll /* cos(2.3212832132975261) ~=-0.6819915771484375*/, - -45525ll /* cos(2.3387364705403644) ~=-0.6946563720703125*/, -46341ll /* cos(2.3561897277832031) ~=-0.7071075439453125*/, - -47142ll /* cos(2.3736429850260419) ~=-0.7193298339843750*/, -47930ll /* cos(2.3910962422688802) ~=-0.7313537597656250*/, - -48703ll /* cos(2.4085494995117189) ~=-0.7431488037109375*/, -49460ll /* cos(2.4260027567545572) ~=-0.7546997070312500*/, - -50203ll /* cos(2.4434560139973960) ~=-0.7660369873046875*/, -50931ll /* cos(2.4609092712402343) ~=-0.7771453857421875*/, - -51643ll /* cos(2.4783625284830730) ~=-0.7880096435546875*/, -52339ll /* cos(2.4958157857259113) ~=-0.7986297607421875*/, - -53020ll /* cos(2.5132690429687501) ~=-0.8090209960937500*/, -53684ll /* cos(2.5307223002115884) ~=-0.8191528320312500*/, - -54332ll /* cos(2.5481755574544271) ~=-0.8290405273437500*/, -54963ll /* cos(2.5656288146972654) ~=-0.8386688232421875*/, - -55577ll /* cos(2.5830820719401042) ~=-0.8480377197265625*/, -56175ll /* cos(2.6005353291829425) ~=-0.8571624755859375*/, - -56756ll /* cos(2.6179885864257812) ~=-0.8660278320312500*/, -57319ll /* cos(2.6354418436686200) ~=-0.8746185302734375*/, - -57865ll /* cos(2.6528951009114583) ~=-0.8829498291015625*/, -58393ll /* cos(2.6703483581542971) ~=-0.8910064697265625*/, - -58903ll /* cos(2.6878016153971354) ~=-0.8987884521484375*/, -59396ll /* cos(2.7052548726399741) ~=-0.9063110351562500*/, - -59870ll /* cos(2.7227081298828124) ~=-0.9135437011718750*/, -60326ll /* cos(2.7401613871256512) ~=-0.9205017089843750*/, - -60764ll /* cos(2.7576146443684895) ~=-0.9271850585937500*/, -61183ll /* cos(2.7750679016113282) ~=-0.9335784912109375*/, - -61584ll /* cos(2.7925211588541665) ~=-0.9396972656250000*/, -61965ll /* cos(2.8099744160970053) ~=-0.9455108642578125*/, - -62328ll /* cos(2.8274276733398436) ~=-0.9510498046875000*/, -62672ll /* cos(2.8448809305826823) ~=-0.9562988281250000*/, - -62997ll /* cos(2.8623341878255206) ~=-0.9612579345703125*/, -63303ll /* cos(2.8797874450683594) ~=-0.9659271240234375*/, - -63589ll /* cos(2.8972407023111981) ~=-0.9702911376953125*/, -63856ll /* cos(2.9146939595540364) ~=-0.9743652343750000*/, - -64104ll /* cos(2.9321472167968752) ~=-0.9781494140625000*/, -64332ll /* cos(2.9496004740397135) ~=-0.9816284179687500*/, - -64540ll /* cos(2.9670537312825522) ~=-0.9848022460937500*/, -64729ll /* cos(2.9845069885253905) ~=-0.9876861572265625*/, - -64898ll /* cos(3.0019602457682293) ~=-0.9902648925781250*/, -65047ll /* cos(3.0194135030110676) ~=-0.9925384521484375*/, - -65177ll /* cos(3.0368667602539063) ~=-0.9945220947265625*/, -65287ll /* cos(3.0543200174967446) ~=-0.9962005615234375*/, - -65376ll /* cos(3.0717732747395834) ~=-0.9975585937500000*/, -65446ll /* cos(3.0892265319824217) ~=-0.9986267089843750*/, - -65496ll /* cos(3.1066797892252604) ~=-0.9993896484375000*/, -65526ll /* cos(3.1241330464680988) ~=-0.9998474121093750*/, - -65536ll /* cos(3.1415863037109375) ~=-1.0000000000000000*/, -65526ll /* cos(3.1590395609537762) ~=-0.9998474121093750*/, - -65496ll /* cos(3.1764928181966146) ~=-0.9993896484375000*/, -65446ll /* cos(3.1939460754394533) ~=-0.9986267089843750*/, - -65376ll /* cos(3.2113993326822916) ~=-0.9975585937500000*/, -65287ll /* cos(3.2288525899251304) ~=-0.9962005615234375*/, - -65177ll /* cos(3.2463058471679687) ~=-0.9945220947265625*/, -65048ll /* cos(3.2637591044108074) ~=-0.9925537109375000*/, - -64898ll /* cos(3.2812123616536457) ~=-0.9902648925781250*/, -64729ll /* cos(3.2986656188964845) ~=-0.9876861572265625*/, - -64540ll /* cos(3.3161188761393228) ~=-0.9848022460937500*/, -64332ll /* cos(3.3335721333821615) ~=-0.9816284179687500*/, - -64104ll /* cos(3.3510253906249998) ~=-0.9781494140625000*/, -63856ll /* cos(3.3684786478678386) ~=-0.9743652343750000*/, - -63589ll /* cos(3.3859319051106769) ~=-0.9702911376953125*/, -63303ll /* cos(3.4033851623535156) ~=-0.9659271240234375*/, - -62997ll /* cos(3.4208384195963544) ~=-0.9612579345703125*/, -62673ll /* cos(3.4382916768391927) ~=-0.9563140869140625*/, - -62329ll /* cos(3.4557449340820314) ~=-0.9510650634765625*/, -61966ll /* cos(3.4731981913248697) ~=-0.9455261230468750*/, - -61584ll /* cos(3.4906514485677085) ~=-0.9396972656250000*/, -61183ll /* cos(3.5081047058105468) ~=-0.9335784912109375*/, - -60764ll /* cos(3.5255579630533855) ~=-0.9271850585937500*/, -60326ll /* cos(3.5430112202962238) ~=-0.9205017089843750*/, - -59870ll /* cos(3.5604644775390626) ~=-0.9135437011718750*/, -59396ll /* cos(3.5779177347819009) ~=-0.9063110351562500*/, - -58904ll /* cos(3.5953709920247396) ~=-0.8988037109375000*/, -58393ll /* cos(3.6128242492675779) ~=-0.8910064697265625*/, - -57865ll /* cos(3.6302775065104167) ~=-0.8829498291015625*/, -57319ll /* cos(3.6477307637532550) ~=-0.8746185302734375*/, - -56756ll /* cos(3.6651840209960938) ~=-0.8660278320312500*/, -56176ll /* cos(3.6826372782389325) ~=-0.8571777343750000*/, - -55578ll /* cos(3.7000905354817708) ~=-0.8480529785156250*/, -54963ll /* cos(3.7175437927246096) ~=-0.8386688232421875*/, - -54332ll /* cos(3.7349970499674479) ~=-0.8290405273437500*/, -53684ll /* cos(3.7524503072102866) ~=-0.8191528320312500*/, - -53020ll /* cos(3.7699035644531249) ~=-0.8090209960937500*/, -52340ll /* cos(3.7873568216959637) ~=-0.7986450195312500*/, - -51643ll /* cos(3.8048100789388020) ~=-0.7880096435546875*/, -50931ll /* cos(3.8222633361816407) ~=-0.7771453857421875*/, - -50204ll /* cos(3.8397165934244790) ~=-0.7660522460937500*/, -49461ll /* cos(3.8571698506673178) ~=-0.7547149658203125*/, - -48703ll /* cos(3.8746231079101561) ~=-0.7431488037109375*/, -47930ll /* cos(3.8920763651529948) ~=-0.7313537597656250*/, - -47143ll /* cos(3.9095296223958331) ~=-0.7193450927734375*/, -46341ll /* cos(3.9269828796386719) ~=-0.7071075439453125*/, - -45526ll /* cos(3.9444361368815106) ~=-0.6946716308593750*/, -44696ll /* cos(3.9618893941243489) ~=-0.6820068359375000*/, - -43853ll /* cos(3.9793426513671877) ~=-0.6691436767578125*/, -42996ll /* cos(3.9967959086100260) ~=-0.6560668945312500*/, - -42126ll /* cos(4.0142491658528643) ~=-0.6427917480468750*/, -41244ll /* cos(4.0317024230957035) ~=-0.6293334960937500*/, - -40348ll /* cos(4.0491556803385418) ~=-0.6156616210937500*/, -39441ll /* cos(4.0666089375813801) ~=-0.6018218994140625*/, - -38522ll /* cos(4.0840621948242184) ~=-0.5877990722656250*/, -37590ll /* cos(4.1015154520670576) ~=-0.5735778808593750*/, - -36648ll /* cos(4.1189687093098959) ~=-0.5592041015625000*/, -35694ll /* cos(4.1364219665527342) ~=-0.5446472167968750*/, - -34729ll /* cos(4.1538752237955725) ~=-0.5299224853515625*/, -33754ll /* cos(4.1713284810384117) ~=-0.5150451660156250*/, - -32768ll /* cos(4.1887817382812500) ~=-0.5000000000000000*/, -31773ll /* cos(4.2062349955240883) ~=-0.4848175048828125*/, - -30768ll /* cos(4.2236882527669275) ~=-0.4694824218750000*/, -29753ll /* cos(4.2411415100097658) ~=-0.4539947509765625*/, - -28730ll /* cos(4.2585947672526041) ~=-0.4383850097656250*/, -27697ll /* cos(4.2760480244954424) ~=-0.4226226806640625*/, - -26656ll /* cos(4.2935012817382816) ~=-0.4067382812500000*/, -25607ll /* cos(4.3109545389811199) ~=-0.3907318115234375*/, - -24551ll /* cos(4.3284077962239582) ~=-0.3746185302734375*/, -23487ll /* cos(4.3458610534667965) ~=-0.3583831787109375*/, - -22415ll /* cos(4.3633143107096357) ~=-0.3420257568359375*/, -21337ll /* cos(4.3807675679524740) ~=-0.3255767822265625*/, - -20252ll /* cos(4.3982208251953123) ~=-0.3090209960937500*/, -19161ll /* cos(4.4156740824381506) ~=-0.2923736572265625*/, - -18065ll /* cos(4.4331273396809898) ~=-0.2756500244140625*/, -16963ll /* cos(4.4505805969238281) ~=-0.2588348388671875*/, - -15855ll /* cos(4.4680338541666664) ~=-0.2419281005859375*/, -14743ll /* cos(4.4854871114095056) ~=-0.2249603271484375*/, - -13626ll /* cos(4.5029403686523439) ~=-0.2079162597656250*/, -12505ll /* cos(4.5203936258951822) ~=-0.1908111572265625*/, - -11381ll /* cos(4.5378468831380205) ~=-0.1736602783203125*/, -10253ll /* cos(4.5553001403808597) ~=-0.1564483642578125*/, - -9121ll /* cos(4.5727533976236980) ~=-0.1391754150390625*/, -7987ll /* cos(4.5902066548665363) ~=-0.1218719482421875*/, - -6851ll /* cos(4.6076599121093746) ~=-0.1045379638671875*/, -5712ll /* cos(4.6251131693522138) ~=-0.0871582031250000*/, - -4572ll /* cos(4.6425664265950521) ~=-0.0697631835937500*/, -3431ll /* cos(4.6600196838378904) ~=-0.0523529052734375*/, - -2288ll /* cos(4.6774729410807288) ~=-0.0349121093750000*/, -1144ll /* cos(4.6949261983235679) ~=-0.0174560546875000*/, - -1ll /* cos(4.7123794555664062) ~=-0.0000152587890625*/, 1143ll /* cos(4.7298327128092446) ~=0.0174407958984375*/, - 2287ll /* cos(4.7472859700520837) ~=0.0348968505859375*/, 3429ll /* cos(4.7647392272949221) ~=0.0523223876953125*/, - 4571ll /* cos(4.7821924845377604) ~=0.0697479248046875*/, 5711ll /* cos(4.7996457417805987) ~=0.0871429443359375*/, - 6850ll /* cos(4.8170989990234379) ~=0.1045227050781250*/, 7986ll /* cos(4.8345522562662762) ~=0.1218566894531250*/, - 9120ll /* cos(4.8520055135091145) ~=0.1391601562500000*/, 10251ll /* cos(4.8694587707519528) ~=0.1564178466796875*/, - 11380ll /* cos(4.8869120279947920) ~=0.1736450195312500*/, 12504ll /* cos(4.9043652852376303) ~=0.1907958984375000*/, - 13625ll /* cos(4.9218185424804686) ~=0.2079010009765625*/, 14742ll /* cos(4.9392717997233069) ~=0.2249450683593750*/, - 15854ll /* cos(4.9567250569661461) ~=0.2419128417968750*/, 16961ll /* cos(4.9741783142089844) ~=0.2588043212890625*/, - 18064ll /* cos(4.9916315714518227) ~=0.2756347656250000*/, 19160ll /* cos(5.0090848286946619) ~=0.2923583984375000*/, - 20251ll /* cos(5.0265380859375002) ~=0.3090057373046875*/, 21336ll /* cos(5.0439913431803385) ~=0.3255615234375000*/, - 22414ll /* cos(5.0614446004231768) ~=0.3420104980468750*/, 23485ll /* cos(5.0788978576660160) ~=0.3583526611328125*/, - 24550ll /* cos(5.0963511149088543) ~=0.3746032714843750*/, 25606ll /* cos(5.1138043721516926) ~=0.3907165527343750*/, - 26655ll /* cos(5.1312576293945309) ~=0.4067230224609375*/, 27696ll /* cos(5.1487108866373701) ~=0.4226074218750000*/, - 28728ll /* cos(5.1661641438802084) ~=0.4383544921875000*/, 29752ll /* cos(5.1836174011230467) ~=0.4539794921875000*/, - 30767ll /* cos(5.2010706583658850) ~=0.4694671630859375*/, 31772ll /* cos(5.2185239156087242) ~=0.4848022460937500*/, - 32767ll /* cos(5.2359771728515625) ~=0.4999847412109375*/, 33753ll /* cos(5.2534304300944008) ~=0.5150299072265625*/, - 34728ll /* cos(5.2708836873372400) ~=0.5299072265625000*/, 35693ll /* cos(5.2883369445800783) ~=0.5446319580078125*/, - 36647ll /* cos(5.3057902018229166) ~=0.5591888427734375*/, 37589ll /* cos(5.3232434590657549) ~=0.5735626220703125*/, - 38521ll /* cos(5.3406967163085941) ~=0.5877838134765625*/, 39440ll /* cos(5.3581499735514324) ~=0.6018066406250000*/, - 40347ll /* cos(5.3756032307942707) ~=0.6156463623046875*/, 41243ll /* cos(5.3930564880371090) ~=0.6293182373046875*/, - 42125ll /* cos(5.4105097452799482) ~=0.6427764892578125*/, 42995ll /* cos(5.4279630025227865) ~=0.6560516357421875*/, - 43852ll /* cos(5.4454162597656248) ~=0.6691284179687500*/, 44695ll /* cos(5.4628695170084631) ~=0.6819915771484375*/, - 45525ll /* cos(5.4803227742513023) ~=0.6946563720703125*/, 46340ll /* cos(5.4977760314941406) ~=0.7070922851562500*/, - 47142ll /* cos(5.5152292887369789) ~=0.7193298339843750*/, 47929ll /* cos(5.5326825459798181) ~=0.7313385009765625*/, - 48702ll /* cos(5.5501358032226564) ~=0.7431335449218750*/, 49460ll /* cos(5.5675890604654947) ~=0.7546997070312500*/, - 50203ll /* cos(5.5850423177083330) ~=0.7660369873046875*/, 50931ll /* cos(5.6024955749511722) ~=0.7771453857421875*/, - 51643ll /* cos(5.6199488321940105) ~=0.7880096435546875*/, 52339ll /* cos(5.6374020894368488) ~=0.7986297607421875*/, - 53019ll /* cos(5.6548553466796871) ~=0.8090057373046875*/, 53684ll /* cos(5.6723086039225263) ~=0.8191528320312500*/, - 54331ll /* cos(5.6897618611653646) ~=0.8290252685546875*/, 54963ll /* cos(5.7072151184082029) ~=0.8386688232421875*/, - 55577ll /* cos(5.7246683756510413) ~=0.8480377197265625*/, 56175ll /* cos(5.7421216328938804) ~=0.8571624755859375*/, - 56755ll /* cos(5.7595748901367188) ~=0.8660125732421875*/, 57319ll /* cos(5.7770281473795571) ~=0.8746185302734375*/, - 57864ll /* cos(5.7944814046223962) ~=0.8829345703125000*/, 58393ll /* cos(5.8119346618652346) ~=0.8910064697265625*/, - 58903ll /* cos(5.8293879191080729) ~=0.8987884521484375*/, 59395ll /* cos(5.8468411763509112) ~=0.9062957763671875*/, - 59870ll /* cos(5.8642944335937504) ~=0.9135437011718750*/, 60326ll /* cos(5.8817476908365887) ~=0.9205017089843750*/, - 60764ll /* cos(5.8992009480794270) ~=0.9271850585937500*/, 61183ll /* cos(5.9166542053222653) ~=0.9335784912109375*/, - 61583ll /* cos(5.9341074625651045) ~=0.9396820068359375*/, 61965ll /* cos(5.9515607198079428) ~=0.9455108642578125*/, - 62328ll /* cos(5.9690139770507811) ~=0.9510498046875000*/, 62672ll /* cos(5.9864672342936194) ~=0.9562988281250000*/, - 62997ll /* cos(6.0039204915364586) ~=0.9612579345703125*/, 63303ll /* cos(6.0213737487792969) ~=0.9659271240234375*/, - 63589ll /* cos(6.0388270060221352) ~=0.9702911376953125*/, 63856ll /* cos(6.0562802632649744) ~=0.9743652343750000*/, - 64104ll /* cos(6.0737335205078127) ~=0.9781494140625000*/, 64332ll /* cos(6.0911867777506510) ~=0.9816284179687500*/, - 64540ll /* cos(6.1086400349934893) ~=0.9848022460937500*/, 64729ll /* cos(6.1260932922363285) ~=0.9876861572265625*/, - 64898ll /* cos(6.1435465494791668) ~=0.9902648925781250*/, 65047ll /* cos(6.1609998067220051) ~=0.9925384521484375*/, - 65177ll /* cos(6.1784530639648434) ~=0.9945220947265625*/, 65287ll /* cos(6.1959063212076826) ~=0.9962005615234375*/, - 65376ll /* cos(6.2133595784505209) ~=0.9975585937500000*/, 65446ll /* cos(6.2308128356933592) ~=0.9986267089843750*/, - 65496ll /* cos(6.2482660929361975) ~=0.9993896484375000*/, 65526ll /* cos(6.2657193501790367) ~=0.9998474121093750*/, - 65536ll /* cos(6.2831726074218750) ~=1.0000000000000000*/}; - -fixed_t cos_angle_tab( uint16_t index ) noexcept - { - return as_fixed(cos_angle_table__[index]); - } -} - diff --git a/fixed_lib/src/fixed_math.cc b/fixed_lib/src/fixed_math.cc deleted file mode 100644 index 702fb83..0000000 --- a/fixed_lib/src/fixed_math.cc +++ /dev/null @@ -1,145 +0,0 @@ -// MIT License -// -// Copyright (c) 2020-2021 Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include -#include "square_root_table.h" -#include "tan_table.h" -#include "sin_angle_table.h" -#include "cos_angle_table.h" -#include -#include - -namespace fixedmath -{ - - struct fix_rbit_scan_loop - { - constexpr int operator()( uint32_t value ) const - { - int cx = 0; // if no bit set: default %clz = 2n = 0 - for (int i = 0; i < 32; i++) - { - auto r1 = value << i; - auto r2 = ( r1 & 0x80000000 ); - if( 0 != r2 ) - { - cx = 32 - i; - break; - } - } - return cx; - } - }; - - struct fix_rbit_scan_clz - { - constexpr int operator()( uint32_t value ) const - { - if( value != 0 ) - { - int lb { cxx20::countl_zero(value) }; - return 32 - lb; - } - return 0; - } - }; - - fixed_t sqrt_aprox(fixed_t value) noexcept - { - if( fixed_unlikely(value <= 0_fix) ) - { - if( fixed_unlikely(value < 0_fix) ) - return std::numeric_limits::quiet_NaN(); - return 0_fix; - } - - int cl = fix_rbit_scan_clz()( static_cast( value.v >> 6 ) ) & 0xfe; // make result even --> %cl = 2n - int index = value.v >> cl; // shift value to fall into range 1..127 - value = as_fixed( square_root_tab(index) ); - cl >>= 1; - value.v = value.v << cl; - return as_fixed(value.v >> 4); - } - - fixed_t hypot_aprox (fixed_t lh, fixed_t rh ) noexcept - { - uint64_t u_l = lh.v; - uint64_t u_r = rh.v; - - uint64_t sum = u_l * u_l + u_r * u_r; - - if( sum > 0x3fffffffffffull) - return std::numeric_limits::quiet_NaN(); - - uint32_t hi_sum = static_cast( sum >> 32 ); - uint32_t lo_sum = static_cast( sum & 0xffffffffu ); - - int clz = fix_rbit_scan_clz()( hi_sum ); - if( clz != 0 ) - { - clz = (clz + 2) & 0xfe; - sum = sum >> clz; - uint32_t lo_index = (sum >> 24) & 0xff; - lh = as_fixed( square_root_tab(lo_index)); - - clz = clz >> 1; - lh.v = lh.v << clz; - } - else - { - lo_sum = lo_sum >> 16; - - clz = fix_rbit_scan_clz()( lo_sum >> 6 ) & 0xfe; - uint32_t lo_index = lo_sum >> clz; - lh = as_fixed( square_root_tab(lo_index)); - - clz = clz >> 1; - lh.v = lh.v << clz; - lh.v = lh.v >> 4; - } - - return lh; - } - - //binary search closest value in tan table - fixed_t atan_index_aprox( fixed_t value ) noexcept - { - if( value >= 0_fix ) - { - auto it { std::lower_bound( std::begin(tan_table__), std::next(std::begin(tan_table__),128), value.v ) }; - - fixed_internal index{ std::distance( std::begin(tan_table__), it ) }; - if( index !=0 && (tan_tab(index)-value) > ( value - tan_tab(index-1) ) ) - index = index -1; -// std::cout << '[' << int(index) << ']' << '(' << tan_tab(index) << ')' << '(' << tan_tab(index-1) << ')'; - return as_fixed( fixed_internal(index) << 15); - } - else - { - auto it { std::lower_bound( std::next(std::begin(tan_table__),128), std::next(std::begin(tan_table__),256), value.v ) }; - fixed_internal index{ std::distance( std::begin(tan_table__), it ) }; - if( index !=0 && (tan_tab(index)-value) > ( value - tan_tab(index-1) ) ) - index = index -1; - return -128_fix + as_fixed( fixed_internal(index) << 15); - } - } -} diff --git a/fixed_lib/src/sin_angle_table.h b/fixed_lib/src/sin_angle_table.h deleted file mode 100644 index 0622019..0000000 --- a/fixed_lib/src/sin_angle_table.h +++ /dev/null @@ -1,202 +0,0 @@ -#pragma once -// generated on Jan 11 2021 20:12:50 -#include - -#include -#include -#include -#include - -namespace fixedmath { - -// sine of full circle for input in degrees -static std::array sin_angle_table__ { - - 0ll /* sin(0) ~=0.0000000000000000*/, 1144ll /* sin(0.0174532572428385) ~=0.0174560546875000*/, - 2287ll /* sin(0.0349065144856771) ~=0.0348968505859375*/, 3430ll /* sin(0.0523597717285156) ~=0.0523376464843750*/, - 4572ll /* sin(0.0698130289713542) ~=0.0697631835937500*/, 5712ll /* sin(0.0872662862141927) ~=0.0871582031250000*/, - 6850ll /* sin(0.1047195434570312) ~=0.1045227050781250*/, 7987ll /* sin(0.1221728006998698) ~=0.1218719482421875*/, - 9121ll /* sin(0.1396260579427083) ~=0.1391754150390625*/, 10252ll /* sin(0.1570793151855469) ~=0.1564331054687500*/, - 11380ll /* sin(0.1745325724283854) ~=0.1736450195312500*/, 12505ll /* sin(0.1919858296712240) ~=0.1908111572265625*/, - 13626ll /* sin(0.2094390869140625) ~=0.2079162597656250*/, 14742ll /* sin(0.2268923441569010) ~=0.2249450683593750*/, - 15855ll /* sin(0.2443456013997396) ~=0.2419281005859375*/, 16962ll /* sin(0.2617988586425781) ~=0.2588195800781250*/, - 18064ll /* sin(0.2792521158854167) ~=0.2756347656250000*/, 19161ll /* sin(0.2967053731282552) ~=0.2923736572265625*/, - 20252ll /* sin(0.3141586303710938) ~=0.3090209960937500*/, 21336ll /* sin(0.3316118876139323) ~=0.3255615234375000*/, - 22415ll /* sin(0.3490651448567708) ~=0.3420257568359375*/, 23486ll /* sin(0.3665184020996094) ~=0.3583679199218750*/, - 24550ll /* sin(0.3839716593424479) ~=0.3746032714843750*/, 25607ll /* sin(0.4014249165852865) ~=0.3907318115234375*/, - 26656ll /* sin(0.4188781738281250) ~=0.4067382812500000*/, 27697ll /* sin(0.4363314310709636) ~=0.4226226806640625*/, - 28729ll /* sin(0.4537846883138021) ~=0.4383697509765625*/, 29753ll /* sin(0.4712379455566406) ~=0.4539947509765625*/, - 30767ll /* sin(0.4886912027994791) ~=0.4694671630859375*/, 31772ll /* sin(0.5061444600423177) ~=0.4848022460937500*/, - 32768ll /* sin(0.5235977172851562) ~=0.5000000000000000*/, 33753ll /* sin(0.5410509745279948) ~=0.5150299072265625*/, - 34729ll /* sin(0.5585042317708333) ~=0.5299224853515625*/, 35693ll /* sin(0.5759574890136718) ~=0.5446319580078125*/, - 36647ll /* sin(0.5934107462565105) ~=0.5591888427734375*/, 37590ll /* sin(0.6108640034993490) ~=0.5735778808593750*/, - 38521ll /* sin(0.6283172607421875) ~=0.5877838134765625*/, 39440ll /* sin(0.6457705179850260) ~=0.6018066406250000*/, - 40348ll /* sin(0.6632237752278646) ~=0.6156616210937500*/, 41243ll /* sin(0.6806770324707031) ~=0.6293182373046875*/, - 42126ll /* sin(0.6981302897135416) ~=0.6427917480468750*/, 42995ll /* sin(0.7155835469563802) ~=0.6560516357421875*/, - 43852ll /* sin(0.7330368041992188) ~=0.6691284179687500*/, 44695ll /* sin(0.7504900614420573) ~=0.6819915771484375*/, - 45525ll /* sin(0.7679433186848958) ~=0.6946563720703125*/, 46341ll /* sin(0.7853965759277344) ~=0.7071075439453125*/, - 47143ll /* sin(0.8028498331705729) ~=0.7193450927734375*/, 47930ll /* sin(0.8203030904134114) ~=0.7313537597656250*/, - 48703ll /* sin(0.8377563476562500) ~=0.7431488037109375*/, 49461ll /* sin(0.8552096048990886) ~=0.7547149658203125*/, - 50203ll /* sin(0.8726628621419271) ~=0.7660369873046875*/, 50931ll /* sin(0.8901161193847656) ~=0.7771453857421875*/, - 51643ll /* sin(0.9075693766276042) ~=0.7880096435546875*/, 52339ll /* sin(0.9250226338704427) ~=0.7986297607421875*/, - 53020ll /* sin(0.9424758911132812) ~=0.8090209960937500*/, 53684ll /* sin(0.9599291483561198) ~=0.8191528320312500*/, - 54332ll /* sin(0.9773824055989583) ~=0.8290405273437500*/, 54963ll /* sin(0.9948356628417969) ~=0.8386688232421875*/, - 55578ll /* sin(1.0122889200846354) ~=0.8480529785156250*/, 56175ll /* sin(1.0297421773274740) ~=0.8571624755859375*/, - 56756ll /* sin(1.0471954345703125) ~=0.8660278320312500*/, 57319ll /* sin(1.0646486918131510) ~=0.8746185302734375*/, - 57865ll /* sin(1.0821019490559896) ~=0.8829498291015625*/, 58393ll /* sin(1.0995552062988281) ~=0.8910064697265625*/, - 58903ll /* sin(1.1170084635416666) ~=0.8987884521484375*/, 59396ll /* sin(1.1344617207845051) ~=0.9063110351562500*/, - 59870ll /* sin(1.1519149780273437) ~=0.9135437011718750*/, 60326ll /* sin(1.1693682352701822) ~=0.9205017089843750*/, - 60764ll /* sin(1.1868214925130209) ~=0.9271850585937500*/, 61183ll /* sin(1.2042747497558595) ~=0.9335784912109375*/, - 61584ll /* sin(1.2217280069986980) ~=0.9396972656250000*/, 61965ll /* sin(1.2391812642415365) ~=0.9455108642578125*/, - 62328ll /* sin(1.2566345214843750) ~=0.9510498046875000*/, 62672ll /* sin(1.2740877787272136) ~=0.9562988281250000*/, - 62997ll /* sin(1.2915410359700521) ~=0.9612579345703125*/, 63303ll /* sin(1.3089942932128906) ~=0.9659271240234375*/, - 63589ll /* sin(1.3264475504557292) ~=0.9702911376953125*/, 63856ll /* sin(1.3439008076985677) ~=0.9743652343750000*/, - 64104ll /* sin(1.3613540649414062) ~=0.9781494140625000*/, 64332ll /* sin(1.3788073221842447) ~=0.9816284179687500*/, - 64540ll /* sin(1.3962605794270833) ~=0.9848022460937500*/, 64729ll /* sin(1.4137138366699218) ~=0.9876861572265625*/, - 64898ll /* sin(1.4311670939127603) ~=0.9902648925781250*/, 65047ll /* sin(1.4486203511555991) ~=0.9925384521484375*/, - 65177ll /* sin(1.4660736083984376) ~=0.9945220947265625*/, 65287ll /* sin(1.4835268656412761) ~=0.9962005615234375*/, - 65376ll /* sin(1.5009801228841146) ~=0.9975585937500000*/, 65446ll /* sin(1.5184333801269532) ~=0.9986267089843750*/, - 65496ll /* sin(1.5358866373697917) ~=0.9993896484375000*/, 65526ll /* sin(1.5533398946126302) ~=0.9998474121093750*/, - 65536ll /* sin(1.5707931518554688) ~=1.0000000000000000*/, 65526ll /* sin(1.5882464090983073) ~=0.9998474121093750*/, - 65496ll /* sin(1.6056996663411458) ~=0.9993896484375000*/, 65446ll /* sin(1.6231529235839843) ~=0.9986267089843750*/, - 65376ll /* sin(1.6406061808268229) ~=0.9975585937500000*/, 65287ll /* sin(1.6580594380696614) ~=0.9962005615234375*/, - 65177ll /* sin(1.6755126953124999) ~=0.9945220947265625*/, 65048ll /* sin(1.6929659525553384) ~=0.9925537109375000*/, - 64898ll /* sin(1.7104192097981772) ~=0.9902648925781250*/, 64729ll /* sin(1.7278724670410157) ~=0.9876861572265625*/, - 64540ll /* sin(1.7453257242838542) ~=0.9848022460937500*/, 64332ll /* sin(1.7627789815266928) ~=0.9816284179687500*/, - 64104ll /* sin(1.7802322387695313) ~=0.9781494140625000*/, 63856ll /* sin(1.7976854960123698) ~=0.9743652343750000*/, - 63589ll /* sin(1.8151387532552083) ~=0.9702911376953125*/, 63303ll /* sin(1.8325920104980469) ~=0.9659271240234375*/, - 62997ll /* sin(1.8500452677408854) ~=0.9612579345703125*/, 62672ll /* sin(1.8674985249837239) ~=0.9562988281250000*/, - 62329ll /* sin(1.8849517822265625) ~=0.9510650634765625*/, 61966ll /* sin(1.9024050394694010) ~=0.9455261230468750*/, - 61584ll /* sin(1.9198582967122395) ~=0.9396972656250000*/, 61183ll /* sin(1.9373115539550780) ~=0.9335784912109375*/, - 60764ll /* sin(1.9547648111979166) ~=0.9271850585937500*/, 60326ll /* sin(1.9722180684407553) ~=0.9205017089843750*/, - 59870ll /* sin(1.9896713256835938) ~=0.9135437011718750*/, 59396ll /* sin(2.0071245829264321) ~=0.9063110351562500*/, - 58903ll /* sin(2.0245778401692709) ~=0.8987884521484375*/, 58393ll /* sin(2.0420310974121092) ~=0.8910064697265625*/, - 57865ll /* sin(2.0594843546549479) ~=0.8829498291015625*/, 57319ll /* sin(2.0769376118977863) ~=0.8746185302734375*/, - 56756ll /* sin(2.0943908691406250) ~=0.8660278320312500*/, 56175ll /* sin(2.1118441263834637) ~=0.8571624755859375*/, - 55578ll /* sin(2.1292973836263021) ~=0.8480529785156250*/, 54963ll /* sin(2.1467506408691408) ~=0.8386688232421875*/, - 54332ll /* sin(2.1642038981119791) ~=0.8290405273437500*/, 53684ll /* sin(2.1816571553548179) ~=0.8191528320312500*/, - 53020ll /* sin(2.1991104125976562) ~=0.8090209960937500*/, 52340ll /* sin(2.2165636698404949) ~=0.7986450195312500*/, - 51643ll /* sin(2.2340169270833332) ~=0.7880096435546875*/, 50931ll /* sin(2.2514701843261720) ~=0.7771453857421875*/, - 50204ll /* sin(2.2689234415690103) ~=0.7660522460937500*/, 49461ll /* sin(2.2863766988118490) ~=0.7547149658203125*/, - 48703ll /* sin(2.3038299560546873) ~=0.7431488037109375*/, 47930ll /* sin(2.3212832132975261) ~=0.7313537597656250*/, - 47143ll /* sin(2.3387364705403644) ~=0.7193450927734375*/, 46341ll /* sin(2.3561897277832031) ~=0.7071075439453125*/, - 45525ll /* sin(2.3736429850260419) ~=0.6946563720703125*/, 44696ll /* sin(2.3910962422688802) ~=0.6820068359375000*/, - 43852ll /* sin(2.4085494995117189) ~=0.6691284179687500*/, 42996ll /* sin(2.4260027567545572) ~=0.6560668945312500*/, - 42126ll /* sin(2.4434560139973960) ~=0.6427917480468750*/, 41243ll /* sin(2.4609092712402343) ~=0.6293182373046875*/, - 40348ll /* sin(2.4783625284830730) ~=0.6156616210937500*/, 39441ll /* sin(2.4958157857259113) ~=0.6018218994140625*/, - 38521ll /* sin(2.5132690429687501) ~=0.5877838134765625*/, 37590ll /* sin(2.5307223002115884) ~=0.5735778808593750*/, - 36648ll /* sin(2.5481755574544271) ~=0.5592041015625000*/, 35694ll /* sin(2.5656288146972654) ~=0.5446472167968750*/, - 34729ll /* sin(2.5830820719401042) ~=0.5299224853515625*/, 33754ll /* sin(2.6005353291829425) ~=0.5150451660156250*/, - 32768ll /* sin(2.6179885864257812) ~=0.5000000000000000*/, 31773ll /* sin(2.6354418436686200) ~=0.4848175048828125*/, - 30768ll /* sin(2.6528951009114583) ~=0.4694824218750000*/, 29753ll /* sin(2.6703483581542971) ~=0.4539947509765625*/, - 28729ll /* sin(2.6878016153971354) ~=0.4383697509765625*/, 27697ll /* sin(2.7052548726399741) ~=0.4226226806640625*/, - 26656ll /* sin(2.7227081298828124) ~=0.4067382812500000*/, 25607ll /* sin(2.7401613871256512) ~=0.3907318115234375*/, - 24551ll /* sin(2.7576146443684895) ~=0.3746185302734375*/, 23486ll /* sin(2.7750679016113282) ~=0.3583679199218750*/, - 22415ll /* sin(2.7925211588541665) ~=0.3420257568359375*/, 21337ll /* sin(2.8099744160970053) ~=0.3255767822265625*/, - 20252ll /* sin(2.8274276733398436) ~=0.3090209960937500*/, 19161ll /* sin(2.8448809305826823) ~=0.2923736572265625*/, - 18065ll /* sin(2.8623341878255206) ~=0.2756500244140625*/, 16962ll /* sin(2.8797874450683594) ~=0.2588195800781250*/, - 15855ll /* sin(2.8972407023111981) ~=0.2419281005859375*/, 14743ll /* sin(2.9146939595540364) ~=0.2249603271484375*/, - 13626ll /* sin(2.9321472167968752) ~=0.2079162597656250*/, 12505ll /* sin(2.9496004740397135) ~=0.1908111572265625*/, - 11381ll /* sin(2.9670537312825522) ~=0.1736602783203125*/, 10252ll /* sin(2.9845069885253905) ~=0.1564331054687500*/, - 9121ll /* sin(3.0019602457682293) ~=0.1391754150390625*/, 7987ll /* sin(3.0194135030110676) ~=0.1218719482421875*/, - 6851ll /* sin(3.0368667602539063) ~=0.1045379638671875*/, 5712ll /* sin(3.0543200174967446) ~=0.0871582031250000*/, - 4572ll /* sin(3.0717732747395834) ~=0.0697631835937500*/, 3430ll /* sin(3.0892265319824217) ~=0.0523376464843750*/, - 2288ll /* sin(3.1066797892252604) ~=0.0349121093750000*/, 1144ll /* sin(3.1241330464680988) ~=0.0174560546875000*/, - 0ll /* sin(3.1415863037109375) ~=0.0000000000000000*/, -1143ll /* sin(3.1590395609537762) ~=-0.0174407958984375*/, - -2287ll /* sin(3.1764928181966146) ~=-0.0348968505859375*/, -3429ll /* sin(3.1939460754394533) ~=-0.0523223876953125*/, - -4571ll /* sin(3.2113993326822916) ~=-0.0697479248046875*/, -5711ll /* sin(3.2288525899251304) ~=-0.0871429443359375*/, - -6850ll /* sin(3.2463058471679687) ~=-0.1045227050781250*/, -7986ll /* sin(3.2637591044108074) ~=-0.1218566894531250*/, - -9120ll /* sin(3.2812123616536457) ~=-0.1391601562500000*/, -10252ll /* sin(3.2986656188964845) ~=-0.1564331054687500*/, - -11380ll /* sin(3.3161188761393228) ~=-0.1736450195312500*/, -12504ll /* sin(3.3335721333821615) ~=-0.1907958984375000*/, - -13625ll /* sin(3.3510253906249998) ~=-0.2079010009765625*/, -14742ll /* sin(3.3684786478678386) ~=-0.2249450683593750*/, - -15854ll /* sin(3.3859319051106769) ~=-0.2419128417968750*/, -16962ll /* sin(3.4033851623535156) ~=-0.2588195800781250*/, - -18064ll /* sin(3.4208384195963544) ~=-0.2756347656250000*/, -19160ll /* sin(3.4382916768391927) ~=-0.2923583984375000*/, - -20251ll /* sin(3.4557449340820314) ~=-0.3090057373046875*/, -21336ll /* sin(3.4731981913248697) ~=-0.3255615234375000*/, - -22414ll /* sin(3.4906514485677085) ~=-0.3420104980468750*/, -23486ll /* sin(3.5081047058105468) ~=-0.3583679199218750*/, - -24550ll /* sin(3.5255579630533855) ~=-0.3746032714843750*/, -25607ll /* sin(3.5430112202962238) ~=-0.3907318115234375*/, - -26655ll /* sin(3.5604644775390626) ~=-0.4067230224609375*/, -27696ll /* sin(3.5779177347819009) ~=-0.4226074218750000*/, - -28729ll /* sin(3.5953709920247396) ~=-0.4383697509765625*/, -29752ll /* sin(3.6128242492675779) ~=-0.4539794921875000*/, - -30767ll /* sin(3.6302775065104167) ~=-0.4694671630859375*/, -31772ll /* sin(3.6477307637532550) ~=-0.4848022460937500*/, - -32768ll /* sin(3.6651840209960938) ~=-0.5000000000000000*/, -33753ll /* sin(3.6826372782389325) ~=-0.5150299072265625*/, - -34728ll /* sin(3.7000905354817708) ~=-0.5299072265625000*/, -35693ll /* sin(3.7175437927246096) ~=-0.5446319580078125*/, - -36647ll /* sin(3.7349970499674479) ~=-0.5591888427734375*/, -37589ll /* sin(3.7524503072102866) ~=-0.5735626220703125*/, - -38521ll /* sin(3.7699035644531249) ~=-0.5877838134765625*/, -39440ll /* sin(3.7873568216959637) ~=-0.6018066406250000*/, - -40348ll /* sin(3.8048100789388020) ~=-0.6156616210937500*/, -41243ll /* sin(3.8222633361816407) ~=-0.6293182373046875*/, - -42125ll /* sin(3.8397165934244790) ~=-0.6427764892578125*/, -42995ll /* sin(3.8571698506673178) ~=-0.6560516357421875*/, - -43852ll /* sin(3.8746231079101561) ~=-0.6691284179687500*/, -44695ll /* sin(3.8920763651529948) ~=-0.6819915771484375*/, - -45525ll /* sin(3.9095296223958331) ~=-0.6946563720703125*/, -46341ll /* sin(3.9269828796386719) ~=-0.7071075439453125*/, - -47142ll /* sin(3.9444361368815106) ~=-0.7193298339843750*/, -47930ll /* sin(3.9618893941243489) ~=-0.7313537597656250*/, - -48702ll /* sin(3.9793426513671877) ~=-0.7431335449218750*/, -49460ll /* sin(3.9967959086100260) ~=-0.7546997070312500*/, - -50203ll /* sin(4.0142491658528643) ~=-0.7660369873046875*/, -50931ll /* sin(4.0317024230957035) ~=-0.7771453857421875*/, - -51643ll /* sin(4.0491556803385418) ~=-0.7880096435546875*/, -52339ll /* sin(4.0666089375813801) ~=-0.7986297607421875*/, - -53019ll /* sin(4.0840621948242184) ~=-0.8090057373046875*/, -53684ll /* sin(4.1015154520670576) ~=-0.8191528320312500*/, - -54332ll /* sin(4.1189687093098959) ~=-0.8290405273437500*/, -54963ll /* sin(4.1364219665527342) ~=-0.8386688232421875*/, - -55577ll /* sin(4.1538752237955725) ~=-0.8480377197265625*/, -56175ll /* sin(4.1713284810384117) ~=-0.8571624755859375*/, - -56756ll /* sin(4.1887817382812500) ~=-0.8660278320312500*/, -57319ll /* sin(4.2062349955240883) ~=-0.8746185302734375*/, - -57865ll /* sin(4.2236882527669275) ~=-0.8829498291015625*/, -58393ll /* sin(4.2411415100097658) ~=-0.8910064697265625*/, - -58903ll /* sin(4.2585947672526041) ~=-0.8987884521484375*/, -59396ll /* sin(4.2760480244954424) ~=-0.9063110351562500*/, - -59870ll /* sin(4.2935012817382816) ~=-0.9135437011718750*/, -60326ll /* sin(4.3109545389811199) ~=-0.9205017089843750*/, - -60764ll /* sin(4.3284077962239582) ~=-0.9271850585937500*/, -61183ll /* sin(4.3458610534667965) ~=-0.9335784912109375*/, - -61583ll /* sin(4.3633143107096357) ~=-0.9396820068359375*/, -61965ll /* sin(4.3807675679524740) ~=-0.9455108642578125*/, - -62328ll /* sin(4.3982208251953123) ~=-0.9510498046875000*/, -62672ll /* sin(4.4156740824381506) ~=-0.9562988281250000*/, - -62997ll /* sin(4.4331273396809898) ~=-0.9612579345703125*/, -63303ll /* sin(4.4505805969238281) ~=-0.9659271240234375*/, - -63589ll /* sin(4.4680338541666664) ~=-0.9702911376953125*/, -63856ll /* sin(4.4854871114095056) ~=-0.9743652343750000*/, - -64104ll /* sin(4.5029403686523439) ~=-0.9781494140625000*/, -64332ll /* sin(4.5203936258951822) ~=-0.9816284179687500*/, - -64540ll /* sin(4.5378468831380205) ~=-0.9848022460937500*/, -64729ll /* sin(4.5553001403808597) ~=-0.9876861572265625*/, - -64898ll /* sin(4.5727533976236980) ~=-0.9902648925781250*/, -65047ll /* sin(4.5902066548665363) ~=-0.9925384521484375*/, - -65177ll /* sin(4.6076599121093746) ~=-0.9945220947265625*/, -65287ll /* sin(4.6251131693522138) ~=-0.9962005615234375*/, - -65376ll /* sin(4.6425664265950521) ~=-0.9975585937500000*/, -65446ll /* sin(4.6600196838378904) ~=-0.9986267089843750*/, - -65496ll /* sin(4.6774729410807288) ~=-0.9993896484375000*/, -65526ll /* sin(4.6949261983235679) ~=-0.9998474121093750*/, - -65536ll /* sin(4.7123794555664062) ~=-1.0000000000000000*/, -65526ll /* sin(4.7298327128092446) ~=-0.9998474121093750*/, - -65496ll /* sin(4.7472859700520837) ~=-0.9993896484375000*/, -65446ll /* sin(4.7647392272949221) ~=-0.9986267089843750*/, - -65376ll /* sin(4.7821924845377604) ~=-0.9975585937500000*/, -65287ll /* sin(4.7996457417805987) ~=-0.9962005615234375*/, - -65177ll /* sin(4.8170989990234379) ~=-0.9945220947265625*/, -65048ll /* sin(4.8345522562662762) ~=-0.9925537109375000*/, - -64898ll /* sin(4.8520055135091145) ~=-0.9902648925781250*/, -64729ll /* sin(4.8694587707519528) ~=-0.9876861572265625*/, - -64540ll /* sin(4.8869120279947920) ~=-0.9848022460937500*/, -64332ll /* sin(4.9043652852376303) ~=-0.9816284179687500*/, - -64104ll /* sin(4.9218185424804686) ~=-0.9781494140625000*/, -63856ll /* sin(4.9392717997233069) ~=-0.9743652343750000*/, - -63589ll /* sin(4.9567250569661461) ~=-0.9702911376953125*/, -63303ll /* sin(4.9741783142089844) ~=-0.9659271240234375*/, - -62997ll /* sin(4.9916315714518227) ~=-0.9612579345703125*/, -62673ll /* sin(5.0090848286946619) ~=-0.9563140869140625*/, - -62329ll /* sin(5.0265380859375002) ~=-0.9510650634765625*/, -61966ll /* sin(5.0439913431803385) ~=-0.9455261230468750*/, - -61584ll /* sin(5.0614446004231768) ~=-0.9396972656250000*/, -61183ll /* sin(5.0788978576660160) ~=-0.9335784912109375*/, - -60764ll /* sin(5.0963511149088543) ~=-0.9271850585937500*/, -60326ll /* sin(5.1138043721516926) ~=-0.9205017089843750*/, - -59870ll /* sin(5.1312576293945309) ~=-0.9135437011718750*/, -59396ll /* sin(5.1487108866373701) ~=-0.9063110351562500*/, - -58904ll /* sin(5.1661641438802084) ~=-0.8988037109375000*/, -58393ll /* sin(5.1836174011230467) ~=-0.8910064697265625*/, - -57865ll /* sin(5.2010706583658850) ~=-0.8829498291015625*/, -57319ll /* sin(5.2185239156087242) ~=-0.8746185302734375*/, - -56756ll /* sin(5.2359771728515625) ~=-0.8660278320312500*/, -56176ll /* sin(5.2534304300944008) ~=-0.8571777343750000*/, - -55578ll /* sin(5.2708836873372400) ~=-0.8480529785156250*/, -54963ll /* sin(5.2883369445800783) ~=-0.8386688232421875*/, - -54332ll /* sin(5.3057902018229166) ~=-0.8290405273437500*/, -53684ll /* sin(5.3232434590657549) ~=-0.8191528320312500*/, - -53020ll /* sin(5.3406967163085941) ~=-0.8090209960937500*/, -52340ll /* sin(5.3581499735514324) ~=-0.7986450195312500*/, - -51644ll /* sin(5.3756032307942707) ~=-0.7880249023437500*/, -50931ll /* sin(5.3930564880371090) ~=-0.7771453857421875*/, - -50204ll /* sin(5.4105097452799482) ~=-0.7660522460937500*/, -49461ll /* sin(5.4279630025227865) ~=-0.7547149658203125*/, - -48703ll /* sin(5.4454162597656248) ~=-0.7431488037109375*/, -47930ll /* sin(5.4628695170084631) ~=-0.7313537597656250*/, - -47143ll /* sin(5.4803227742513023) ~=-0.7193450927734375*/, -46341ll /* sin(5.4977760314941406) ~=-0.7071075439453125*/, - -45526ll /* sin(5.5152292887369789) ~=-0.6946716308593750*/, -44696ll /* sin(5.5326825459798181) ~=-0.6820068359375000*/, - -43853ll /* sin(5.5501358032226564) ~=-0.6691436767578125*/, -42996ll /* sin(5.5675890604654947) ~=-0.6560668945312500*/, - -42126ll /* sin(5.5850423177083330) ~=-0.6427917480468750*/, -41244ll /* sin(5.6024955749511722) ~=-0.6293334960937500*/, - -40349ll /* sin(5.6199488321940105) ~=-0.6156768798828125*/, -39441ll /* sin(5.6374020894368488) ~=-0.6018218994140625*/, - -38522ll /* sin(5.6548553466796871) ~=-0.5877990722656250*/, -37591ll /* sin(5.6723086039225263) ~=-0.5735931396484375*/, - -36648ll /* sin(5.6897618611653646) ~=-0.5592041015625000*/, -35694ll /* sin(5.7072151184082029) ~=-0.5446472167968750*/, - -34729ll /* sin(5.7246683756510413) ~=-0.5299224853515625*/, -33754ll /* sin(5.7421216328938804) ~=-0.5150451660156250*/, - -32769ll /* sin(5.7595748901367188) ~=-0.5000152587890625*/, -31773ll /* sin(5.7770281473795571) ~=-0.4848175048828125*/, - -30768ll /* sin(5.7944814046223962) ~=-0.4694824218750000*/, -29753ll /* sin(5.8119346618652346) ~=-0.4539947509765625*/, - -28730ll /* sin(5.8293879191080729) ~=-0.4383850097656250*/, -27697ll /* sin(5.8468411763509112) ~=-0.4226226806640625*/, - -26657ll /* sin(5.8642944335937504) ~=-0.4067535400390625*/, -25608ll /* sin(5.8817476908365887) ~=-0.3907470703125000*/, - -24551ll /* sin(5.8992009480794270) ~=-0.3746185302734375*/, -23487ll /* sin(5.9166542053222653) ~=-0.3583831787109375*/, - -22415ll /* sin(5.9341074625651045) ~=-0.3420257568359375*/, -21337ll /* sin(5.9515607198079428) ~=-0.3255767822265625*/, - -20252ll /* sin(5.9690139770507811) ~=-0.3090209960937500*/, -19162ll /* sin(5.9864672342936194) ~=-0.2923889160156250*/, - -18065ll /* sin(6.0039204915364586) ~=-0.2756500244140625*/, -16963ll /* sin(6.0213737487792969) ~=-0.2588348388671875*/, - -15855ll /* sin(6.0388270060221352) ~=-0.2419281005859375*/, -14743ll /* sin(6.0562802632649744) ~=-0.2249603271484375*/, - -13626ll /* sin(6.0737335205078127) ~=-0.2079162597656250*/, -12506ll /* sin(6.0911867777506510) ~=-0.1908264160156250*/, - -11381ll /* sin(6.1086400349934893) ~=-0.1736602783203125*/, -10253ll /* sin(6.1260932922363285) ~=-0.1564483642578125*/, - -9122ll /* sin(6.1435465494791668) ~=-0.1391906738281250*/, -7988ll /* sin(6.1609998067220051) ~=-0.1218872070312500*/, - -6851ll /* sin(6.1784530639648434) ~=-0.1045379638671875*/, -5713ll /* sin(6.1959063212076826) ~=-0.0871734619140625*/, - -4572ll /* sin(6.2133595784505209) ~=-0.0697631835937500*/, -3431ll /* sin(6.2308128356933592) ~=-0.0523529052734375*/, - -2288ll /* sin(6.2482660929361975) ~=-0.0349121093750000*/, -1145ll /* sin(6.2657193501790367) ~=-0.0174713134765625*/, - -1ll /* sin(6.2831726074218750) ~=-0.0000152587890625*/}; - -fixed_t sin_angle_tab( uint16_t index ) noexcept - { - return as_fixed(sin_angle_table__[index]); - } -} - diff --git a/fixed_lib/src/square_root_table.h b/fixed_lib/src/square_root_table.h deleted file mode 100644 index 42c7f72..0000000 --- a/fixed_lib/src/square_root_table.h +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once -// generated on Jan 5 2021 12:53:44 -#include - -#include -#include -#include -#include - -namespace fixedmath { - -// square root precalculated values -static std::array square_root_table__ { - - 0x2c8 /* sqrt(0.000118256) ~=0.0108642578125000*/, 0x103d /* sqrt(0.0040245056152344) ~=0.0634307861328125*/, - 0x16cc /* sqrt(0.0079307556152344) ~=0.0890502929687500*/, 0x1bda /* sqrt(0.0118370056152344) ~=0.1087951660156250*/, - 0x201f /* sqrt(0.0157432556152344) ~=0.1254730224609375*/, 0x23e2 /* sqrt(0.0196495056152344) ~=0.1401672363281250*/, - 0x274a /* sqrt(0.0235557556152344) ~=0.1534729003906250*/, 0x2a6c /* sqrt(0.0274620056152344) ~=0.1657104492187500*/, - 0x2d57 /* sqrt(0.0313682556152344) ~=0.1771087646484375*/, 0x3014 /* sqrt(0.0352745056152344) ~=0.1878051757812500*/, - 0x32ac /* sqrt(0.0391807556152344) ~=0.1979370117187500*/, 0x3523 /* sqrt(0.0430870056152344) ~=0.2075653076171875*/, - 0x377e /* sqrt(0.0469932556152344) ~=0.2167663574218750*/, 0x39c1 /* sqrt(0.0508995056152344) ~=0.2256011962890625*/, - 0x3bee /* sqrt(0.0548057556152344) ~=0.2341003417968750*/, 0x3e07 /* sqrt(0.0587120056152344) ~=0.2422943115234375*/, - 0x400f /* sqrt(0.0626182556152344) ~=0.2502288818359375*/, 0x4207 /* sqrt(0.0665245056152344) ~=0.2579193115234375*/, - 0x43f0 /* sqrt(0.0704307556152344) ~=0.2653808593750000*/, 0x45cc /* sqrt(0.0743370056152344) ~=0.2726440429687500*/, - 0x479b /* sqrt(0.0782432556152344) ~=0.2797088623046875*/, 0x495f /* sqrt(0.0821495056152344) ~=0.2866058349609375*/, - 0x4b19 /* sqrt(0.0860557556152344) ~=0.2933502197265625*/, 0x4cc8 /* sqrt(0.0899620056152344) ~=0.2999267578125000*/, - 0x4e6e /* sqrt(0.0938682556152344) ~=0.3063659667968750*/, 0x500c /* sqrt(0.0977745056152344) ~=0.3126831054687500*/, - 0x51a1 /* sqrt(0.1016807556152344) ~=0.3188629150390625*/, 0x532f /* sqrt(0.1055870056152344) ~=0.3249359130859375*/, - 0x54b5 /* sqrt(0.1094932556152344) ~=0.3308868408203125*/, 0x5635 /* sqrt(0.1133995056152344) ~=0.3367462158203125*/, - 0x57ae /* sqrt(0.1173057556152344) ~=0.3424987792968750*/, 0x5920 /* sqrt(0.1212120056152344) ~=0.3481445312500000*/, - 0x5a8d /* sqrt(0.1251182556152344) ~=0.3537139892578125*/, 0x5bf4 /* sqrt(0.1290245056152344) ~=0.3591918945312500*/, - 0x5d56 /* sqrt(0.1329307556152344) ~=0.3645935058593750*/, 0x5eb2 /* sqrt(0.1368370056152344) ~=0.3699035644531250*/, - 0x600a /* sqrt(0.1407432556152344) ~=0.3751525878906250*/, 0x615d /* sqrt(0.1446495056152344) ~=0.3803253173828125*/, - 0x62ab /* sqrt(0.1485557556152344) ~=0.3854217529296875*/, 0x63f5 /* sqrt(0.1524620056152344) ~=0.3904571533203125*/, - 0x653b /* sqrt(0.1563682556152344) ~=0.3954315185546875*/, 0x667c /* sqrt(0.1602745056152344) ~=0.4003295898437500*/, - 0x67ba /* sqrt(0.1641807556152344) ~=0.4051818847656250*/, 0x68f4 /* sqrt(0.1680870056152344) ~=0.4099731445312500*/, - 0x6a2b /* sqrt(0.1719932556152344) ~=0.4147186279296875*/, 0x6b5e /* sqrt(0.1758995056152344) ~=0.4194030761718750*/, - 0x6c8d /* sqrt(0.1798057556152344) ~=0.4240264892578125*/, 0x6db9 /* sqrt(0.1837120056152344) ~=0.4286041259765625*/, - 0x6ee2 /* sqrt(0.1876182556152344) ~=0.4331359863281250*/, 0x7008 /* sqrt(0.1915245056152344) ~=0.4376220703125000*/, - 0x712b /* sqrt(0.1954307556152344) ~=0.4420623779296875*/, 0x724c /* sqrt(0.1993370056152344) ~=0.4464721679687500*/, - 0x7369 /* sqrt(0.2032432556152344) ~=0.4508209228515625*/, 0x7483 /* sqrt(0.2071495056152344) ~=0.4551239013671875*/, - 0x759b /* sqrt(0.2110557556152344) ~=0.4593963623046875*/, 0x76b1 /* sqrt(0.2149620056152344) ~=0.4636383056640625*/, - 0x77c4 /* sqrt(0.2188682556152344) ~=0.4678344726562500*/, 0x78d4 /* sqrt(0.2227745056152344) ~=0.4719848632812500*/, - 0x79e2 /* sqrt(0.2266807556152344) ~=0.4761047363281250*/, 0x7aee /* sqrt(0.2305870056152344) ~=0.4801940917968750*/, - 0x7bf7 /* sqrt(0.2344932556152344) ~=0.4842376708984375*/, 0x7cfe /* sqrt(0.2383995056152344) ~=0.4882507324218750*/, - 0x7e03 /* sqrt(0.2423057556152344) ~=0.4922332763671875*/, 0x7f06 /* sqrt(0.2462120056152344) ~=0.4961853027343750*/, - 0x8007 /* sqrt(0.2501182556152344) ~=0.5001068115234375*/, 0x8106 /* sqrt(0.2540245056152344) ~=0.5039978027343750*/, - 0x8203 /* sqrt(0.2579307556152344) ~=0.5078582763671875*/, 0x82fe /* sqrt(0.2618370056152344) ~=0.5116882324218750*/, - 0x83f8 /* sqrt(0.2657432556152344) ~=0.5155029296875000*/, 0x84ef /* sqrt(0.2696495056152344) ~=0.5192718505859375*/, - 0x85e5 /* sqrt(0.2735557556152344) ~=0.5230255126953125*/, 0x86d8 /* sqrt(0.2774620056152344) ~=0.5267333984375000*/, - 0x87cb /* sqrt(0.2813682556152344) ~=0.5304412841796875*/, 0x88bb /* sqrt(0.2852745056152344) ~=0.5341033935546875*/, - 0x89aa /* sqrt(0.2891807556152344) ~=0.5377502441406250*/, 0x8a97 /* sqrt(0.2930870056152344) ~=0.5413665771484375*/, - 0x8b83 /* sqrt(0.2969932556152344) ~=0.5449676513671875*/, 0x8c6d /* sqrt(0.3008995056152344) ~=0.5485382080078125*/, - 0x8d55 /* sqrt(0.3048057556152344) ~=0.5520782470703125*/, 0x8e3d /* sqrt(0.3087120056152344) ~=0.5556182861328125*/, - 0x8f22 /* sqrt(0.3126182556152344) ~=0.5591125488281250*/, 0x9006 /* sqrt(0.3165245056152344) ~=0.5625915527343750*/, - 0x90e9 /* sqrt(0.3204307556152344) ~=0.5660552978515625*/, 0x91cb /* sqrt(0.3243370056152344) ~=0.5695037841796875*/, - 0x92ab /* sqrt(0.3282432556152344) ~=0.5729217529296875*/, 0x938a /* sqrt(0.3321495056152344) ~=0.5763244628906250*/, - 0x9467 /* sqrt(0.3360557556152344) ~=0.5796966552734375*/, 0x9543 /* sqrt(0.3399620056152344) ~=0.5830535888671875*/, - 0x961e /* sqrt(0.3438682556152344) ~=0.5863952636718750*/, 0x96f8 /* sqrt(0.3477745056152344) ~=0.5897216796875000*/, - 0x97d0 /* sqrt(0.3516807556152344) ~=0.5930175781250000*/, 0x98a7 /* sqrt(0.3555870056152344) ~=0.5962982177734375*/, - 0x997d /* sqrt(0.3594932556152344) ~=0.5995635986328125*/, 0x9a52 /* sqrt(0.3633995056152344) ~=0.6028137207031250*/, - 0x9b26 /* sqrt(0.3673057556152344) ~=0.6060485839843750*/, 0x9bf9 /* sqrt(0.3712120056152344) ~=0.6092681884765625*/, - 0x9cca /* sqrt(0.3751182556152344) ~=0.6124572753906250*/, 0x9d9b /* sqrt(0.3790245056152344) ~=0.6156463623046875*/, - 0x9e6a /* sqrt(0.3829307556152344) ~=0.6188049316406250*/, 0x9f38 /* sqrt(0.3868370056152344) ~=0.6219482421875000*/, - 0xa006 /* sqrt(0.3907432556152344) ~=0.6250915527343750*/, 0xa0d2 /* sqrt(0.3946495056152344) ~=0.6282043457031250*/, - 0xa19d /* sqrt(0.3985557556152344) ~=0.6313018798828125*/, 0xa268 /* sqrt(0.4024620056152344) ~=0.6343994140625000*/, - 0xa331 /* sqrt(0.4063682556152344) ~=0.6374664306640625*/, 0xa3f9 /* sqrt(0.4102745056152344) ~=0.6405181884765625*/, - 0xa4c0 /* sqrt(0.4141807556152344) ~=0.6435546875000000*/, 0xa587 /* sqrt(0.4180870056152344) ~=0.6465911865234375*/, - 0xa64c /* sqrt(0.4219932556152344) ~=0.6495971679687500*/, 0xa711 /* sqrt(0.4258995056152344) ~=0.6526031494140625*/, - 0xa7d5 /* sqrt(0.4298057556152344) ~=0.6555938720703125*/, 0xa897 /* sqrt(0.4337120056152344) ~=0.6585540771484375*/, - 0xa959 /* sqrt(0.4376182556152344) ~=0.6615142822265625*/, 0xaa1a /* sqrt(0.4415245056152344) ~=0.6644592285156250*/, - 0xaadb /* sqrt(0.4454307556152344) ~=0.6674041748046875*/, 0xab9a /* sqrt(0.4493370056152344) ~=0.6703186035156250*/, - 0xac59 /* sqrt(0.4532432556152344) ~=0.6732330322265625*/, 0xad16 /* sqrt(0.4571495056152344) ~=0.6761169433593750*/, - 0xadd3 /* sqrt(0.4610557556152344) ~=0.6790008544921875*/, 0xae8f /* sqrt(0.4649620056152344) ~=0.6818695068359375*/, - 0xaf4b /* sqrt(0.4688682556152344) ~=0.6847381591796875*/, 0xb005 /* sqrt(0.4727745056152344) ~=0.6875762939453125*/, - 0xb0bf /* sqrt(0.4766807556152344) ~=0.6904144287109375*/, 0xb178 /* sqrt(0.4805870056152344) ~=0.6932373046875000*/, - 0xb230 /* sqrt(0.4844932556152344) ~=0.6960449218750000*/, 0xb2e8 /* sqrt(0.4883995056152344) ~=0.6988525390625000*/, - 0xb39f /* sqrt(0.4923057556152344) ~=0.7016448974609375*/, 0xb455 /* sqrt(0.4962120056152344) ~=0.7044219970703125*/, - 0xb50a /* sqrt(0.5001182556152344) ~=0.7071838378906250*/, 0xb5bf /* sqrt(0.5040245056152344) ~=0.7099456787109375*/, - 0xb673 /* sqrt(0.5079307556152344) ~=0.7126922607421875*/, 0xb726 /* sqrt(0.5118370056152344) ~=0.7154235839843750*/, - 0xb7d8 /* sqrt(0.5157432556152344) ~=0.7181396484375000*/, 0xb88a /* sqrt(0.5196495056152344) ~=0.7208557128906250*/, - 0xb93c /* sqrt(0.5235557556152344) ~=0.7235717773437500*/, 0xb9ec /* sqrt(0.5274620056152344) ~=0.7262573242187500*/, - 0xba9c /* sqrt(0.5313682556152344) ~=0.7289428710937500*/, 0xbb4b /* sqrt(0.5352745056152344) ~=0.7316131591796875*/, - 0xbbfa /* sqrt(0.5391807556152344) ~=0.7342834472656250*/, 0xbca8 /* sqrt(0.5430870056152344) ~=0.7369384765625000*/, - 0xbd55 /* sqrt(0.5469932556152344) ~=0.7395782470703125*/, 0xbe02 /* sqrt(0.5508995056152344) ~=0.7422180175781250*/, - 0xbeae /* sqrt(0.5548057556152344) ~=0.7448425292968750*/, 0xbf5a /* sqrt(0.5587120056152344) ~=0.7474670410156250*/, - 0xc005 /* sqrt(0.5626182556152344) ~=0.7500762939453125*/, 0xc0af /* sqrt(0.5665245056152344) ~=0.7526702880859375*/, - 0xc159 /* sqrt(0.5704307556152344) ~=0.7552642822265625*/, 0xc202 /* sqrt(0.5743370056152344) ~=0.7578430175781250*/, - 0xc2ab /* sqrt(0.5782432556152344) ~=0.7604217529296875*/, 0xc353 /* sqrt(0.5821495056152344) ~=0.7629852294921875*/, - 0xc3fa /* sqrt(0.5860557556152344) ~=0.7655334472656250*/, 0xc4a1 /* sqrt(0.5899620056152344) ~=0.7680816650390625*/, - 0xc547 /* sqrt(0.5938682556152344) ~=0.7706146240234375*/, 0xc5ed /* sqrt(0.5977745056152344) ~=0.7731475830078125*/, - 0xc693 /* sqrt(0.6016807556152344) ~=0.7756805419921875*/, 0xc737 /* sqrt(0.6055870056152344) ~=0.7781829833984375*/, - 0xc7dc /* sqrt(0.6094932556152344) ~=0.7807006835937500*/, 0xc87f /* sqrt(0.6133995056152344) ~=0.7831878662109375*/, - 0xc922 /* sqrt(0.6173057556152344) ~=0.7856750488281250*/, 0xc9c5 /* sqrt(0.6212120056152344) ~=0.7881622314453125*/, - 0xca67 /* sqrt(0.6251182556152344) ~=0.7906341552734375*/, 0xcb09 /* sqrt(0.6290245056152344) ~=0.7931060791015625*/, - 0xcbaa /* sqrt(0.6329307556152344) ~=0.7955627441406250*/, 0xcc4b /* sqrt(0.6368370056152344) ~=0.7980194091796875*/, - 0xcceb /* sqrt(0.6407432556152344) ~=0.8004608154296875*/, 0xcd8a /* sqrt(0.6446495056152344) ~=0.8028869628906250*/, - 0xce2a /* sqrt(0.6485557556152344) ~=0.8053283691406250*/, 0xcec8 /* sqrt(0.6524620056152344) ~=0.8077392578125000*/, - 0xcf67 /* sqrt(0.6563682556152344) ~=0.8101654052734375*/, 0xd004 /* sqrt(0.6602745056152344) ~=0.8125610351562500*/, - 0xd0a2 /* sqrt(0.6641807556152344) ~=0.8149719238281250*/, 0xd13e /* sqrt(0.6680870056152344) ~=0.8173522949218750*/, - 0xd1db /* sqrt(0.6719932556152344) ~=0.8197479248046875*/, 0xd277 /* sqrt(0.6758995056152344) ~=0.8221282958984375*/, - 0xd312 /* sqrt(0.6798057556152344) ~=0.8244934082031250*/, 0xd3ad /* sqrt(0.6837120056152344) ~=0.8268585205078125*/, - 0xd448 /* sqrt(0.6876182556152344) ~=0.8292236328125000*/, 0xd4e2 /* sqrt(0.6915245056152344) ~=0.8315734863281250*/, - 0xd57c /* sqrt(0.6954307556152344) ~=0.8339233398437500*/, 0xd615 /* sqrt(0.6993370056152344) ~=0.8362579345703125*/, - 0xd6ae /* sqrt(0.7032432556152344) ~=0.8385925292968750*/, 0xd746 /* sqrt(0.7071495056152344) ~=0.8409118652343750*/, - 0xd7de /* sqrt(0.7110557556152344) ~=0.8432312011718750*/, 0xd876 /* sqrt(0.7149620056152344) ~=0.8455505371093750*/, - 0xd90d /* sqrt(0.7188682556152344) ~=0.8478546142578125*/, 0xd9a4 /* sqrt(0.7227745056152344) ~=0.8501586914062500*/, - 0xda3a /* sqrt(0.7266807556152344) ~=0.8524475097656250*/, 0xdad0 /* sqrt(0.7305870056152344) ~=0.8547363281250000*/, - 0xdb66 /* sqrt(0.7344932556152344) ~=0.8570251464843750*/, 0xdbfb /* sqrt(0.7383995056152344) ~=0.8592987060546875*/, - 0xdc90 /* sqrt(0.7423057556152344) ~=0.8615722656250000*/, 0xdd24 /* sqrt(0.7462120056152344) ~=0.8638305664062500*/, - 0xddb8 /* sqrt(0.7501182556152344) ~=0.8660888671875000*/, 0xde4b /* sqrt(0.7540245056152344) ~=0.8683319091796875*/, - 0xdedf /* sqrt(0.7579307556152344) ~=0.8705902099609375*/, 0xdf72 /* sqrt(0.7618370056152344) ~=0.8728332519531250*/, - 0xe004 /* sqrt(0.7657432556152344) ~=0.8750610351562500*/, 0xe096 /* sqrt(0.7696495056152344) ~=0.8772888183593750*/, - 0xe128 /* sqrt(0.7735557556152344) ~=0.8795166015625000*/, 0xe1b9 /* sqrt(0.7774620056152344) ~=0.8817291259765625*/, - 0xe24a /* sqrt(0.7813682556152344) ~=0.8839416503906250*/, 0xe2db /* sqrt(0.7852745056152344) ~=0.8861541748046875*/, - 0xe36b /* sqrt(0.7891807556152344) ~=0.8883514404296875*/, 0xe3fb /* sqrt(0.7930870056152344) ~=0.8905487060546875*/, - 0xe48a /* sqrt(0.7969932556152344) ~=0.8927307128906250*/, 0xe51a /* sqrt(0.8008995056152344) ~=0.8949279785156250*/, - 0xe5a9 /* sqrt(0.8048057556152344) ~=0.8971099853515625*/, 0xe637 /* sqrt(0.8087120056152344) ~=0.8992767333984375*/, - 0xe6c5 /* sqrt(0.8126182556152344) ~=0.9014434814453125*/, 0xe753 /* sqrt(0.8165245056152344) ~=0.9036102294921875*/, - 0xe7e1 /* sqrt(0.8204307556152344) ~=0.9057769775390625*/, 0xe86e /* sqrt(0.8243370056152344) ~=0.9079284667968750*/, - 0xe8fa /* sqrt(0.8282432556152344) ~=0.9100646972656250*/, 0xe987 /* sqrt(0.8321495056152344) ~=0.9122161865234375*/, - 0xea13 /* sqrt(0.8360557556152344) ~=0.9143524169921875*/, 0xea9f /* sqrt(0.8399620056152344) ~=0.9164886474609375*/, - 0xeb2a /* sqrt(0.8438682556152344) ~=0.9186096191406250*/, 0xebb6 /* sqrt(0.8477745056152344) ~=0.9207458496093750*/, - 0xec40 /* sqrt(0.8516807556152344) ~=0.9228515625000000*/, 0xeccb /* sqrt(0.8555870056152344) ~=0.9249725341796875*/, - 0xed55 /* sqrt(0.8594932556152344) ~=0.9270782470703125*/, 0xeddf /* sqrt(0.8633995056152344) ~=0.9291839599609375*/, - 0xee69 /* sqrt(0.8673057556152344) ~=0.9312896728515625*/, 0xeef2 /* sqrt(0.8712120056152344) ~=0.9333801269531250*/, - 0xef7b /* sqrt(0.8751182556152344) ~=0.9354705810546875*/, 0xf004 /* sqrt(0.8790245056152344) ~=0.9375610351562500*/, - 0xf08c /* sqrt(0.8829307556152344) ~=0.9396362304687500*/, 0xf114 /* sqrt(0.8868370056152344) ~=0.9417114257812500*/, - 0xf19c /* sqrt(0.8907432556152344) ~=0.9437866210937500*/, 0xf223 /* sqrt(0.8946495056152344) ~=0.9458465576171875*/, - 0xf2ab /* sqrt(0.8985557556152344) ~=0.9479217529296875*/, 0xf331 /* sqrt(0.9024620056152344) ~=0.9499664306640625*/, - 0xf3b8 /* sqrt(0.9063682556152344) ~=0.9520263671875000*/, 0xf43e /* sqrt(0.9102745056152344) ~=0.9540710449218750*/, - 0xf4c4 /* sqrt(0.9141807556152344) ~=0.9561157226562500*/, 0xf54a /* sqrt(0.9180870056152344) ~=0.9581604003906250*/, - 0xf5d0 /* sqrt(0.9219932556152344) ~=0.9602050781250000*/, 0xf655 /* sqrt(0.9258995056152344) ~=0.9622344970703125*/, - 0xf6da /* sqrt(0.9298057556152344) ~=0.9642639160156250*/, 0xf75e /* sqrt(0.9337120056152344) ~=0.9662780761718750*/, - 0xf7e3 /* sqrt(0.9376182556152344) ~=0.9683074951171875*/, 0xf867 /* sqrt(0.9415245056152344) ~=0.9703216552734375*/, - 0xf8ea /* sqrt(0.9454307556152344) ~=0.9723205566406250*/, 0xf96e /* sqrt(0.9493370056152344) ~=0.9743347167968750*/, - 0xf9f1 /* sqrt(0.9532432556152344) ~=0.9763336181640625*/, 0xfa74 /* sqrt(0.9571495056152344) ~=0.9783325195312500*/, - 0xfaf7 /* sqrt(0.9610557556152344) ~=0.9803314208984375*/, 0xfb79 /* sqrt(0.9649620056152344) ~=0.9823150634765625*/, - 0xfbfb /* sqrt(0.9688682556152344) ~=0.9842987060546875*/, 0xfc7d /* sqrt(0.9727745056152344) ~=0.9862823486328125*/, - 0xfcff /* sqrt(0.9766807556152344) ~=0.9882659912109375*/, 0xfd80 /* sqrt(0.9805870056152344) ~=0.9902343750000000*/, - 0xfe01 /* sqrt(0.9844932556152344) ~=0.9922027587890625*/, 0xfe82 /* sqrt(0.9883995056152344) ~=0.9941711425781250*/, - 0xff03 /* sqrt(0.9923057556152344) ~=0.9961395263671875*/, 0xff83 /* sqrt(0.9962120056152344) ~=0.9980926513671875*/ -}; - -uint16_t square_root_tab( uint8_t index ) noexcept - { - return square_root_table__[index]; - } -} - diff --git a/fixed_lib/src/tan_table.h b/fixed_lib/src/tan_table.h deleted file mode 100644 index 54060cd..0000000 --- a/fixed_lib/src/tan_table.h +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once -// generated on Jan 5 2021 12:53:44 -#include - -#include -#include -#include -#include - -namespace fixedmath { - -// tangets of half of circle 0 .. 127 precalculated values 0 .. phi/2 -static std::array tan_table__ { - - 0ll /* tan(0) ~=0.0000000000000000*/, 804ll /* tan(0.0122717618942261) ~=0.0122680664062500*/, - 1609ll /* tan(0.0245435237884521) ~=0.0245513916015625*/, 2414ll /* tan(0.0368152856826782) ~=0.0368347167968750*/, - 3220ll /* tan(0.0490870475769043) ~=0.0491333007812500*/, 4026ll /* tan(0.0613588094711304) ~=0.0614318847656250*/, - 4834ll /* tan(0.0736305713653564) ~=0.0737609863281250*/, 5644ll /* tan(0.0859023332595825) ~=0.0861206054687500*/, - 6455ll /* tan(0.0981740951538086) ~=0.0984954833984375*/, 7268ll /* tan(0.1104458570480347) ~=0.1109008789062500*/, - 8083ll /* tan(0.1227176189422607) ~=0.1233367919921875*/, 8901ll /* tan(0.1349893808364868) ~=0.1358184814453125*/, - 9721ll /* tan(0.1472611427307129) ~=0.1483306884765625*/, 10545ll /* tan(0.1595329046249390) ~=0.1609039306640625*/, - 11371ll /* tan(0.1718046665191650) ~=0.1735076904296875*/, 12202ll /* tan(0.1840764284133911) ~=0.1861877441406250*/, - 13036ll /* tan(0.1963481903076172) ~=0.1989135742187500*/, 13874ll /* tan(0.2086199522018433) ~=0.2117004394531250*/, - 14716ll /* tan(0.2208917140960693) ~=0.2245483398437500*/, 15564ll /* tan(0.2331634759902954) ~=0.2374877929687500*/, - 16416ll /* tan(0.2454352378845215) ~=0.2504882812500000*/, 17273ll /* tan(0.2577069997787476) ~=0.2635650634765625*/, - 18136ll /* tan(0.2699787616729736) ~=0.2767333984375000*/, 19005ll /* tan(0.2822505235671997) ~=0.2899932861328125*/, - 19880ll /* tan(0.2945222854614258) ~=0.3033447265625000*/, 20762ll /* tan(0.3067940473556519) ~=0.3168029785156250*/, - 21650ll /* tan(0.3190658092498779) ~=0.3303527832031250*/, 22546ll /* tan(0.3313375711441040) ~=0.3440246582031250*/, - 23449ll /* tan(0.3436093330383301) ~=0.3578033447265625*/, 24360ll /* tan(0.3558810949325562) ~=0.3717041015625000*/, - 25280ll /* tan(0.3681528568267822) ~=0.3857421875000000*/, 26208ll /* tan(0.3804246187210083) ~=0.3999023437500000*/, - 27146ll /* tan(0.3926963806152344) ~=0.4142150878906250*/, 28093ll /* tan(0.4049681425094604) ~=0.4286651611328125*/, - 29050ll /* tan(0.4172399044036865) ~=0.4432678222656250*/, 30017ll /* tan(0.4295116662979126) ~=0.4580230712890625*/, - 30996ll /* tan(0.4417834281921387) ~=0.4729614257812500*/, 31986ll /* tan(0.4540551900863647) ~=0.4880676269531250*/, - 32988ll /* tan(0.4663269519805908) ~=0.5033569335937500*/, 34002ll /* tan(0.4785987138748169) ~=0.5188293457031250*/, - 35029ll /* tan(0.4908704757690430) ~=0.5345001220703125*/, 36070ll /* tan(0.5031422376632690) ~=0.5503845214843750*/, - 37125ll /* tan(0.5154139995574951) ~=0.5664825439453125*/, 38195ll /* tan(0.5276857614517212) ~=0.5828094482421875*/, - 39280ll /* tan(0.5399575233459473) ~=0.5993652343750000*/, 40382ll /* tan(0.5522292852401733) ~=0.6161804199218750*/, - 41500ll /* tan(0.5645010471343994) ~=0.6332397460937500*/, 42635ll /* tan(0.5767728090286255) ~=0.6505584716796875*/, - 43789ll /* tan(0.5890445709228516) ~=0.6681671142578125*/, 44962ll /* tan(0.6013163328170776) ~=0.6860656738281250*/, - 46155ll /* tan(0.6135880947113037) ~=0.7042694091796875*/, 47369ll /* tan(0.6258598566055298) ~=0.7227935791015625*/, - 48604ll /* tan(0.6381316184997559) ~=0.7416381835937500*/, 49862ll /* tan(0.6504033803939819) ~=0.7608337402343750*/, - 51144ll /* tan(0.6626751422882080) ~=0.7803955078125000*/, 52451ll /* tan(0.6749469041824341) ~=0.8003387451171875*/, - 53783ll /* tan(0.6872186660766602) ~=0.8206634521484375*/, 55143ll /* tan(0.6994904279708862) ~=0.8414154052734375*/, - 56531ll /* tan(0.7117621898651123) ~=0.8625946044921875*/, 57949ll /* tan(0.7240339517593384) ~=0.8842315673828125*/, - 59398ll /* tan(0.7363057136535645) ~=0.9063415527343750*/, 60879ll /* tan(0.7485774755477905) ~=0.9289398193359375*/, - 62395ll /* tan(0.7608492374420166) ~=0.9520721435546875*/, 63946ll /* tan(0.7731209993362427) ~=0.9757385253906250*/, - 65535ll /* tan(0.7853927612304688) ~=0.9999847412109375*/, 67164ll /* tan(0.7976645231246948) ~=1.0248413085937500*/, - 68834ll /* tan(0.8099362850189209) ~=1.0503234863281250*/, 70547ll /* tan(0.8222080469131470) ~=1.0764617919921875*/, - 72307ll /* tan(0.8344798088073730) ~=1.1033172607421875*/, 74115ll /* tan(0.8467515707015991) ~=1.1309051513671875*/, - 75974ll /* tan(0.8590233325958252) ~=1.1592712402343750*/, 77886ll /* tan(0.8712950944900513) ~=1.1884460449218750*/, - 79855ll /* tan(0.8835668563842773) ~=1.2184906005859375*/, 81884ll /* tan(0.8958386182785034) ~=1.2494506835937500*/, - 83976ll /* tan(0.9081103801727295) ~=1.2813720703125000*/, 86134ll /* tan(0.9203821420669556) ~=1.3143005371093750*/, - 88364ll /* tan(0.9326539039611816) ~=1.3483276367187500*/, 90668ll /* tan(0.9449256658554077) ~=1.3834838867187500*/, - 93053ll /* tan(0.9571974277496338) ~=1.4198760986328125*/, 95521ll /* tan(0.9694691896438599) ~=1.4575347900390625*/, - 98080ll /* tan(0.9817409515380859) ~=1.4965820312500000*/, 100735ll /* tan(0.9940127134323120) ~=1.5370941162109375*/, - 103491ll /* tan(1.0062844753265381) ~=1.5791473388671875*/, 106357ll /* tan(1.0185562372207642) ~=1.6228790283203125*/, - 109338ll /* tan(1.0308279991149902) ~=1.6683654785156250*/, 112445ll /* tan(1.0430997610092163) ~=1.7157745361328125*/, - 115685ll /* tan(1.0553715229034424) ~=1.7652130126953125*/, 119069ll /* tan(1.0676432847976685) ~=1.8168487548828125*/, - 122607ll /* tan(1.0799150466918945) ~=1.8708343505859375*/, 126311ll /* tan(1.0921868085861206) ~=1.9273529052734375*/, - 130195ll /* tan(1.1044585704803467) ~=1.9866180419921875*/, 134273ll /* tan(1.1167303323745728) ~=2.0488433837890625*/, - 138561ll /* tan(1.1290020942687988) ~=2.1142730712890625*/, 143078ll /* tan(1.1412738561630249) ~=2.1831970214843750*/, - 147844ll /* tan(1.1535456180572510) ~=2.2559204101562500*/, 152881ll /* tan(1.1658173799514771) ~=2.3327789306640625*/, - 158214ll /* tan(1.1780891418457031) ~=2.4141540527343750*/, 163874ll /* tan(1.1903609037399292) ~=2.5005187988281250*/, - 169892ll /* tan(1.2026326656341553) ~=2.5923461914062500*/, 176305ll /* tan(1.2149044275283813) ~=2.6902008056640625*/, - 183156ll /* tan(1.2271761894226074) ~=2.7947387695312500*/, 190494ll /* tan(1.2394479513168335) ~=2.9067077636718750*/, - 198375ll /* tan(1.2517197132110596) ~=3.0269622802734375*/, 206863ll /* tan(1.2639914751052856) ~=3.1564788818359375*/, - 216036ll /* tan(1.2762632369995117) ~=3.2964477539062500*/, 225983ll /* tan(1.2885349988937378) ~=3.4482269287109375*/, - 236808ll /* tan(1.3008067607879639) ~=3.6134033203125000*/, 248639ll /* tan(1.3130785226821899) ~=3.7939300537109375*/, - 261624ll /* tan(1.3253502845764160) ~=3.9920654296875000*/, 275948ll /* tan(1.3376220464706421) ~=4.2106323242187500*/, - 291832ll /* tan(1.3498938083648682) ~=4.4530029296875000*/, 309553ll /* tan(1.3621655702590942) ~=4.7234039306640625*/, - 329455ll /* tan(1.3744373321533203) ~=5.0270843505859375*/, 351975ll /* tan(1.3867090940475464) ~=5.3707122802734375*/, - 377672ll /* tan(1.3989808559417725) ~=5.7628173828125000*/, 407280ll /* tan(1.4112526178359985) ~=6.2145996093750000*/, - 441778ll /* tan(1.4235243797302246) ~=6.7409973144531250*/, 482498ll /* tan(1.4357961416244507) ~=7.3623352050781250*/, - 531308ll /* tan(1.4480679035186768) ~=8.1071166992187500*/, 590904ll /* tan(1.4603396654129028) ~=9.0164794921875000*/, - 665329ll /* tan(1.4726114273071289) ~=10.1521148681640625*/, 760939ll /* tan(1.4848831892013550) ~=11.6110076904296875*/, - 888325ll /* tan(1.4971549510955811) ~=13.5547637939453125*/, 1066549ll /* tan(1.5094267129898071) ~=16.2742462158203125*/, - 1333731ll /* tan(1.5216984748840332) ~=20.3511199951171875*/, 1778803ll /* tan(1.5339702367782593) ~=27.1423797607421875*/, - 2668484ll /* tan(1.5462419986724854) ~=40.7178344726562500*/, 5335424ll /* tan(1.5585137605667114) ~=81.4121093750000000*/, - 6065714022ll /* tan(1.5707855224609375) ~=92555.4507751464843750*/, -5344829ll /* tan(1.5830572843551636) ~=-81.5556182861328125*/, - -2670835ll /* tan(1.5953290462493896) ~=-40.7537078857421875*/, -1779849ll /* tan(1.6076008081436157) ~=-27.1583404541015625*/, - -1334319ll /* tan(1.6198725700378418) ~=-20.3600921630859375*/, -1066926ll /* tan(1.6321443319320679) ~=-16.2799987792968750*/, - -888587ll /* tan(1.6444160938262939) ~=-13.5587615966796875*/, -761132ll /* tan(1.6566878557205200) ~=-11.6139526367187500*/, - -665476ll /* tan(1.6689596176147461) ~=-10.1543579101562500*/, -591020ll /* tan(1.6812313795089722) ~=-9.0182495117187500*/, - -531403ll /* tan(1.6935031414031982) ~=-8.1085662841796875*/, -482577ll /* tan(1.7057749032974243) ~=-7.3635406494140625*/, - -441844ll /* tan(1.7180466651916504) ~=-6.7420043945312500*/, -407336ll /* tan(1.7303184270858765) ~=-6.2154541015625000*/, - -377720ll /* tan(1.7425901889801025) ~=-5.7635498046875000*/, -352017ll /* tan(1.7548619508743286) ~=-5.3713531494140625*/, - -329493ll /* tan(1.7671337127685547) ~=-5.0276641845703125*/, -309586ll /* tan(1.7794054746627808) ~=-4.7239074707031250*/, - -291862ll /* tan(1.7916772365570068) ~=-4.4534606933593750*/, -275974ll /* tan(1.8039489984512329) ~=-4.2110290527343750*/, - -261648ll /* tan(1.8162207603454590) ~=-3.9924316406250000*/, -248660ll /* tan(1.8284925222396851) ~=-3.7942504882812500*/, - -236828ll /* tan(1.8407642841339111) ~=-3.6137084960937500*/, -226001ll /* tan(1.8530360460281372) ~=-3.4485015869140625*/, - -216053ll /* tan(1.8653078079223633) ~=-3.2967071533203125*/, -206879ll /* tan(1.8775795698165894) ~=-3.1567230224609375*/, - -198389ll /* tan(1.8898513317108154) ~=-3.0271759033203125*/, -190507ll /* tan(1.9021230936050415) ~=-2.9069061279296875*/, - -183168ll /* tan(1.9143948554992676) ~=-2.7949218750000000*/, -176316ll /* tan(1.9266666173934937) ~=-2.6903686523437500*/, - -169902ll /* tan(1.9389383792877197) ~=-2.5924987792968750*/, -163884ll /* tan(1.9512101411819458) ~=-2.5006713867187500*/, - -158224ll /* tan(1.9634819030761719) ~=-2.4143066406250000*/, -152890ll /* tan(1.9757536649703979) ~=-2.3329162597656250*/, - -147852ll /* tan(1.9880254268646240) ~=-2.2560424804687500*/, -143086ll /* tan(2.0002971887588501) ~=-2.1833190917968750*/, - -138569ll /* tan(2.0125689506530762) ~=-2.1143951416015625*/, -134281ll /* tan(2.0248407125473022) ~=-2.0489654541015625*/, - -130202ll /* tan(2.0371124744415283) ~=-1.9867248535156250*/, -126318ll /* tan(2.0493842363357544) ~=-1.9274597167968750*/, - -122613ll /* tan(2.0616559982299805) ~=-1.8709259033203125*/, -119075ll /* tan(2.0739277601242065) ~=-1.8169403076171875*/, - -115691ll /* tan(2.0861995220184326) ~=-1.7653045654296875*/, -112451ll /* tan(2.0984712839126587) ~=-1.7158660888671875*/, - -109344ll /* tan(2.1107430458068848) ~=-1.6684570312500000*/, -106362ll /* tan(2.1230148077011108) ~=-1.6229553222656250*/, - -103496ll /* tan(2.1352865695953369) ~=-1.5792236328125000*/, -100739ll /* tan(2.1475583314895630) ~=-1.5371551513671875*/, - -98085ll /* tan(2.1598300933837891) ~=-1.4966583251953125*/, -95526ll /* tan(2.1721018552780151) ~=-1.4576110839843750*/, - -93057ll /* tan(2.1843736171722412) ~=-1.4199371337890625*/, -90673ll /* tan(2.1966453790664673) ~=-1.3835601806640625*/, - -88368ll /* tan(2.2089171409606934) ~=-1.3483886718750000*/, -86138ll /* tan(2.2211889028549194) ~=-1.3143615722656250*/, - -83979ll /* tan(2.2334606647491455) ~=-1.2814178466796875*/, -81887ll /* tan(2.2457324266433716) ~=-1.2494964599609375*/, - -79858ll /* tan(2.2580041885375977) ~=-1.2185363769531250*/, -77889ll /* tan(2.2702759504318237) ~=-1.1884918212890625*/, - -75977ll /* tan(2.2825477123260498) ~=-1.1593170166015625*/, -74118ll /* tan(2.2948194742202759) ~=-1.1309509277343750*/, - -72310ll /* tan(2.3070912361145020) ~=-1.1033630371093750*/, -70551ll /* tan(2.3193629980087280) ~=-1.0765228271484375*/, - -68837ll /* tan(2.3316347599029541) ~=-1.0503692626953125*/, -67167ll /* tan(2.3439065217971802) ~=-1.0248870849609375*/, - -65538ll /* tan(2.3561782836914062) ~=-1.0000305175781250*/, -63949ll /* tan(2.3684500455856323) ~=-0.9757843017578125*/, - -62398ll /* tan(2.3807218074798584) ~=-0.9521179199218750*/, -60882ll /* tan(2.3929935693740845) ~=-0.9289855957031250*/, - -59400ll /* tan(2.4052653312683105) ~=-0.9063720703125000*/, -57951ll /* tan(2.4175370931625366) ~=-0.8842620849609375*/, - -56534ll /* tan(2.4298088550567627) ~=-0.8626403808593750*/, -55146ll /* tan(2.4420806169509888) ~=-0.8414611816406250*/, - -53786ll /* tan(2.4543523788452148) ~=-0.8207092285156250*/, -52453ll /* tan(2.4666241407394409) ~=-0.8003692626953125*/, - -51147ll /* tan(2.4788959026336670) ~=-0.7804412841796875*/, -49865ll /* tan(2.4911676645278931) ~=-0.7608795166015625*/, - -48607ll /* tan(2.5034394264221191) ~=-0.7416839599609375*/, -47371ll /* tan(2.5157111883163452) ~=-0.7228240966796875*/, - -46157ll /* tan(2.5279829502105713) ~=-0.7042999267578125*/, -44964ll /* tan(2.5402547121047974) ~=-0.6860961914062500*/, - -43791ll /* tan(2.5525264739990234) ~=-0.6681976318359375*/, -42637ll /* tan(2.5647982358932495) ~=-0.6505889892578125*/, - -41502ll /* tan(2.5770699977874756) ~=-0.6332702636718750*/, -40384ll /* tan(2.5893417596817017) ~=-0.6162109375000000*/, - -39282ll /* tan(2.6016135215759277) ~=-0.5993957519531250*/, -38197ll /* tan(2.6138852834701538) ~=-0.5828399658203125*/, - -37127ll /* tan(2.6261570453643799) ~=-0.5665130615234375*/, -36072ll /* tan(2.6384288072586060) ~=-0.5504150390625000*/, - -35031ll /* tan(2.6507005691528320) ~=-0.5345306396484375*/, -34004ll /* tan(2.6629723310470581) ~=-0.5188598632812500*/, - -32990ll /* tan(2.6752440929412842) ~=-0.5033874511718750*/, -31988ll /* tan(2.6875158548355103) ~=-0.4880981445312500*/, - -30998ll /* tan(2.6997876167297363) ~=-0.4729919433593750*/, -30019ll /* tan(2.7120593786239624) ~=-0.4580535888671875*/, - -29052ll /* tan(2.7243311405181885) ~=-0.4432983398437500*/, -28094ll /* tan(2.7366029024124146) ~=-0.4286804199218750*/, - -27147ll /* tan(2.7488746643066406) ~=-0.4142303466796875*/, -26210ll /* tan(2.7611464262008667) ~=-0.3999328613281250*/, - -25281ll /* tan(2.7734181880950928) ~=-0.3857574462890625*/, -24362ll /* tan(2.7856899499893188) ~=-0.3717346191406250*/, - -23451ll /* tan(2.7979617118835449) ~=-0.3578338623046875*/, -22547ll /* tan(2.8102334737777710) ~=-0.3440399169921875*/, - -21652ll /* tan(2.8225052356719971) ~=-0.3303833007812500*/, -20763ll /* tan(2.8347769975662231) ~=-0.3168182373046875*/, - -19882ll /* tan(2.8470487594604492) ~=-0.3033752441406250*/, -19006ll /* tan(2.8593205213546753) ~=-0.2900085449218750*/, - -18138ll /* tan(2.8715922832489014) ~=-0.2767639160156250*/, -17275ll /* tan(2.8838640451431274) ~=-0.2635955810546875*/, - -16417ll /* tan(2.8961358070373535) ~=-0.2505035400390625*/, -15565ll /* tan(2.9084075689315796) ~=-0.2375030517578125*/, - -14718ll /* tan(2.9206793308258057) ~=-0.2245788574218750*/, -13875ll /* tan(2.9329510927200317) ~=-0.2117156982421875*/, - -13037ll /* tan(2.9452228546142578) ~=-0.1989288330078125*/, -12203ll /* tan(2.9574946165084839) ~=-0.1862030029296875*/, - -11373ll /* tan(2.9697663784027100) ~=-0.1735382080078125*/, -10546ll /* tan(2.9820381402969360) ~=-0.1609191894531250*/, - -9723ll /* tan(2.9943099021911621) ~=-0.1483612060546875*/, -8902ll /* tan(3.0065816640853882) ~=-0.1358337402343750*/, - -8084ll /* tan(3.0188534259796143) ~=-0.1233520507812500*/, -7269ll /* tan(3.0311251878738403) ~=-0.1109161376953125*/, - -6456ll /* tan(3.0433969497680664) ~=-0.0985107421875000*/, -5645ll /* tan(3.0556687116622925) ~=-0.0861358642578125*/, - -4836ll /* tan(3.0679404735565186) ~=-0.0737915039062500*/, -4028ll /* tan(3.0802122354507446) ~=-0.0614624023437500*/, - -3221ll /* tan(3.0924839973449707) ~=-0.0491485595703125*/, -2415ll /* tan(3.1047557592391968) ~=-0.0368499755859375*/, - -1610ll /* tan(3.1170275211334229) ~=-0.0245666503906250*/, -806ll /* tan(3.1292992830276489) ~=-0.0122985839843750*/ -}; - -fixed_t tan_tab( uint8_t index ) noexcept - { - return as_fixed(tan_table__[index]); - } -} - diff --git a/git_tag.sh b/git_tag.sh index a85f1a5..85a8e6b 100755 --- a/git_tag.sh +++ b/git_tag.sh @@ -1,27 +1,24 @@ #!/bin/bash -# Path to the top level CMakeLists.txt file -CMAKE_FILE="CMakeLists.txt" +# Path to the file containing the version string +FILE_PATH="fixed_lib/include/fixedmath/types.h" -# Extract the version number -#VERSION=$(grep "VERSION" $CMAKE_FILE | head -n 1 | awk '{print $2}') -#VERSION=$(grep "VERSION" $CMAKE_FILE | head -n 1 | sed -E 's/.*VERSION ([0-9]+.[0-9]+.[0-9]+).*/\1/') -#VERSION=$(grep "^project(" $CMAKE_FILE | sed -n 's/.*VERSION \([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p') -VERSION=$(tail -n +2 $CMAKE_FILE | grep "VERSION" | head -n 1 | awk '{print $2}') +# Extract the version string from the file +VERSION_STRING=$(grep 'FIXEDMATH_VERSION_STRING' $FILE_PATH | cut -d '"' -f2) -# Check if VERSION is empty -if [ -z "$VERSION" ]; then - echo "Version not found in $CMAKE_FILE" - exit 1 +# Check if the version string was found +if [ -z "$VERSION_STRING" ]; then + echo "Version string not found in $FILE_PATH" + exit 1 fi -# Prefix the version with a 'v' -TAG="v$VERSION" +# Prefix the version string with 'v' +TAG_NAME="v$VERSION_STRING" -# Add a git tag -git tag -a $TAG -m "Release $TAG" +# Create a Git tag with the prefixed version string +git tag -a "$TAG_NAME" -m "Release $TAG_NAME" -# Optional: Push the tag to remote repository -# git push origin $TAG +echo "Git tag $TAG_NAME created successfully." -echo "Tag $TAG created and ready to be pushed." +# Optional: Push the tag to the remote repository +# git push origin "$TAG_NAME" diff --git a/perf_test_suite/perf.cc b/perf_test_suite/perf.cc index 958777d..1118cd6 100644 --- a/perf_test_suite/perf.cc +++ b/perf_test_suite/perf.cc @@ -7,128 +7,178 @@ #include #include #include - -using fixedmath::fixed_t; -using fixedmath::make_fixed; -using std::cout; -using std::endl; using std::chrono::duration_cast; -using std::chrono::steady_clock; using std::chrono::microseconds; using std::chrono::milliseconds; -using fixedmath::sin; -using std::sin; -using fixedmath::asin; +using std::chrono::steady_clock; +using std::cout; +using std::endl; + +using std::string_view; + using std::asin; -using fixedmath::tan; -using std::tan; -using fixedmath::atan; using std::atan; -using std::string_view; -using fixedmath::phi; +using std::tan; +using std::sin; + +using fixedmath::fixed_t; -using limits_ = std::numeric_limits; +using limits_ = std::numeric_limits; -struct tuple_type +struct tuple_type { - fixed_t fx; float f; double d; + fixed_t fx; + float f; + double d; }; - -constexpr auto perf( steady_clock::time_point start, steady_clock::time_point end ) { return duration_cast(end - start).count(); } + +constexpr auto perf(steady_clock::time_point start, steady_clock::time_point end) + { + return duration_cast(end - start).count(); + } template -auto test( std::vector data_fx, test_function fnobj ) +auto test(std::vector data_fx, test_function fnobj) { - size_t test_size { data_fx.size() }; + size_t test_size{data_fx.size()}; std::vector out_data_fx; - out_data_fx.resize( test_size ); + out_data_fx.resize(test_size); auto start = steady_clock::now(); - std::transform( data_fx.begin(), data_fx.end(), out_data_fx.begin(), fnobj ); + std::transform(data_fx.begin(), data_fx.end(), out_data_fx.begin(), fnobj); auto end = steady_clock::now(); - return perf(start,end); + return perf(start, end); } template struct test_executor { - int64_t operator()( string_view info ) + int64_t operator()(string_view info) { - std::random_device rd; //Will be used to obtain a seed for the random number engine - std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() + std::random_device rd; // Will be used to obtain a seed for the random number engine + std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> distrib(1, 256); - size_t test_size { 10000000 }; + size_t test_size{10000000}; - std::vector data_fx; std::vector data_f; std::vector data_d; - data_fx.reserve( test_size );data_f.reserve( test_size );data_d.reserve( test_size ); + std::vector data_fx; + std::vector data_f; + std::vector data_d; + data_fx.reserve(test_size); + data_f.reserve(test_size); + data_d.reserve(test_size); - for(size_t n=0; n(phi/4*value/256) ); - data_d.emplace_back( static_cast(phi/4*value/256) ); + int value{distrib(gen)}; + data_fx.emplace_back(phi / 4 * value / 256); + data_f.emplace_back(static_cast(phi / 4 * value / 256)); + data_d.emplace_back(static_cast(phi / 4 * value / 256)); } - - auto float_perf { test(data_f, test_function{} ) }; - auto double_perf { test(data_d, test_function{} ) }; - auto fix_perf { test(data_fx, test_function{} ) }; - - int64_t noop{ static_cast( std::accumulate(data_fx.begin(),data_fx.end(), fixed_t{} )) } ; - noop += static_cast( std::accumulate(data_f.begin(),data_f.end(), float{} )); - noop += static_cast( std::accumulate(data_d.begin(),data_d.end(), double{} )); - - cout << info << " fixed:"<< fix_perf << "ms float:" << float_perf << " ms double:" << double_perf << " ms "; + + auto float_perf{test(data_f, test_function{})}; + auto double_perf{test(data_d, test_function{})}; + auto fix_perf{test(data_fx, test_function{})}; + + int64_t noop{static_cast(std::accumulate(data_fx.begin(), data_fx.end(), fixed_t{}))}; + noop += static_cast(std::accumulate(data_f.begin(), data_f.end(), float{})); + noop += static_cast(std::accumulate(data_d.begin(), data_d.end(), double{})); + + cout << info << " fixed:" << fix_perf << "ms float:" << float_perf << " ms double:" << double_perf << " ms "; return noop; } }; - -struct sin_test{ + +struct sin_test + { template - auto operator()(value_type const & tp){ return sin(tp); } -}; -struct asin_test{ + auto operator()(value_type const & tp) + { + return sin(tp); + } + }; + +struct asin_test + { template - auto operator()(value_type const & tp){ return asin(tp); } -}; -struct tan_test{ + auto operator()(value_type const & tp) + { + return asin(tp); + } + }; + +struct tan_test + { template - auto operator()(value_type const & tp){ return tan(tp); } -}; -struct atan_test{ + auto operator()(value_type const & tp) + { + return tan(tp); + } + }; + +struct atan_test + { template - auto operator()(value_type const & tp){ return atan(tp); } -}; -struct sqrt_test{ + auto operator()(value_type const & tp) + { + return atan(tp); + } + }; + +struct sqrt_test + { template - auto operator()(value_type const & tp){ return sqrt(tp); } -}; -struct arith_test{ + auto operator()(value_type const & tp) + { + return sqrt(tp); + } + }; + +struct arith_test + { template - auto operator()(value_type const & tp){ return (1+tp*tp)/(1-tp); } -}; -struct add_test{ + auto operator()(value_type const & tp) + { + return (1 + tp * tp) / (1 - tp); + } + }; + +struct add_test + { template - auto operator()(value_type const & tp){ return tp+tp; } -}; -struct mul_test{ + auto operator()(value_type const & tp) + { + return tp + tp; + } + }; + +struct mul_test + { template - auto operator()(value_type const & tp){ return tp*tp; } -}; -struct div_test{ + auto operator()(value_type const & tp) + { + return tp * tp; + } + }; + +struct div_test + { template - auto operator()(value_type const & tp){ return tp/tp; } -}; -int main(int argc, char **argv) -{ -cout << test_executor{}("sin") << endl; -cout << test_executor{}("asin") << endl; -cout << test_executor{}("tan") << endl; -cout << test_executor{}("atan") << endl; -cout << test_executor{}("sqrt") << endl; -cout << test_executor{}("arith_test") << endl; -cout << test_executor{}("add") << endl; -cout << test_executor{}("mul") << endl; -cout << test_executor{}("div") << endl; -return EXIT_SUCCESS; -} + auto operator()(value_type const & tp) + { + return tp / tp; + } + }; + +int main(int argc, char ** argv) + { + cout << test_executor{}("sin") << endl; + cout << test_executor{}("asin") << endl; + cout << test_executor{}("tan") << endl; + cout << test_executor{}("atan") << endl; + cout << test_executor{}("sqrt") << endl; + cout << test_executor{}("arith_test") << endl; + cout << test_executor{}("add") << endl; + cout << test_executor{}("mul") << endl; + cout << test_executor{}("div") << endl; + return EXIT_SUCCESS; + } diff --git a/table_gen/CMakeLists.txt b/table_gen/CMakeLists.txt deleted file mode 100644 index b822bbc..0000000 --- a/table_gen/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_executable(table_gen table_gen.cc) - -install(TARGETS table_gen RUNTIME DESTINATION bin) - -#target_link_libraries( table_gen - #fixed_math ) -target_include_directories( table_gen PRIVATE - $ - ) - -target_compile_definitions( table_gen PRIVATE -DOUTPUT_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../fixed_lib/src" ) diff --git a/table_gen/table_gen.cc b/table_gen/table_gen.cc deleted file mode 100644 index 23d3a17..0000000 --- a/table_gen/table_gen.cc +++ /dev/null @@ -1,192 +0,0 @@ -// MIT License -// -// Copyright (c) 2020 EBASoft Artur Bac -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include -#include -#include -#include -#include -#include - -using namespace fixedmath; - -using limits_ = std::numeric_limits; -using flimits_ = std::numeric_limits; -using dlimits_ = std::numeric_limits; - -using std::endl; - -static fixed_t conv( double value ) - { - return fix_carrier_t( static_cast(value * 65536 + (1./16) ) ); - } - -static void head( std::ostream & out ) - { - out <<"#pragma once"<< endl; - out <<"// generated on " << __DATE__ << " " << __TIME__ << endl; - out <<"#include "<< endl << endl; - out <<"#include "<< endl; - out <<"#include "<< endl; - out <<"#include "<< endl; - out <<"#include "<< endl << endl; - out <<"namespace fixedmath {"<< endl; - out << endl; - } - -static void foot( std::ostream & out ) - { - out <<"}"<< endl; - out << endl; - } - -static void gen_sqrt_tab() - { - std::string filename = OUTPUT_FILE_PATH "/square_root_table.h"; - std::fstream out(filename, out.binary | out.trunc | out.out); - - head( out ); - out <<"// square root precalculated values"<< endl; - out << "static std::array square_root_table__ {"<< endl; - - out << std::hex << std::showbase << endl; - for( int16_t i{0}; i != 256 ; i+=1 ) - { - double fract { static_cast(i) / 256 + 1./(2*8192) + 1./(4*8192) + 1./(8*8192)+ 1./(16*8192) + 1./(32*8192) }; - fixed_t ftab { conv( sqrt( fract )) }; - uint16_t tabvalue{ static_cast(ftab.v) }; - out << " " << tabvalue << " /* sqrt("<< fract<<") ~=" << ftab << "*/"; - if( i != 255 ) - out << ", "; - if( i != 0 && (i+1) % 2 == 0 ) - out << endl; - } - out <<"};"<< endl; - out << endl; - out <<"uint16_t square_root_tab( uint8_t index ) noexcept"<< endl; - out <<" {" << endl; - out <<" return square_root_table__[index];"<< endl; - out <<" }"<< endl; - foot(out); - } - -static void gen_tan_tab() - { - std::string filename = OUTPUT_FILE_PATH "/tan_table.h"; - std::fstream out(filename, out.binary | out.trunc | out.out); - - head( out ); - - - out <<"// tangets of half of circle 0 .. 127 precalculated values 0 .. phi/2"<< endl; - out << "static std::array tan_table__ {"<< endl; - - out << std::dec << endl; - for( int16_t i{0}; i != 256 ; i+=1 ) - { - double fract { static_cast(i) / 128 * (phi/2) }; - fixed_t ftab { floating_point_to_fixed( std::tan( fract ) ) }; - fixed_internal tabvalue{ ftab.v }; - out << " " << tabvalue << "ll /* tan("<< fract<<") ~=" << ftab << "*/"; - if( i != 255 ) - out << ", "; - if( i != 0 && (i+1) % 2 == 0 ) - out << endl; - } - out <<"};"<< endl; - out << endl; - out <<"fixed_t tan_tab( uint8_t index ) noexcept"<< endl; - out <<" {" << endl; - out <<" return as_fixed(tan_table__[index]);"<< endl; - out <<" }"<< endl; - foot(out); - } - -static void gen_cos_angle_tab() - { - std::string filename = OUTPUT_FILE_PATH "/cos_angle_table.h"; - std::fstream out(filename, out.binary | out.trunc | out.out); - - head( out ); - - - out <<"// cosine of full circle for input in degrees"<< endl; - out << "static std::array cos_angle_table__ {"<< endl; - - out << std::dec << endl; - for( int16_t i{0}; i != 361 ; i++ ) - { - double rad { static_cast(i) * phi / 180. }; - fixed_t ftab { floating_point_to_fixed( std::cos( rad ) ) }; - fixed_internal tabvalue{ ftab.v }; - out << " " << tabvalue << "ll /* cos("<< rad <<") ~=" << ftab << "*/"; - if( i != 360 ) - out << ", "; - if( i != 0 && (i+1) % 2 == 0 ) - out << endl; - } - out <<"};"<< endl; - out << endl; - out <<"fixed_t cos_angle_tab( uint16_t index ) noexcept"<< endl; - out <<" {" << endl; - out <<" return as_fixed(cos_angle_table__[index]);"<< endl; - out <<" }"<< endl; - foot(out); - } -static void gen_sin_angle_tab() - { - std::string filename = OUTPUT_FILE_PATH "/sin_angle_table.h"; - std::fstream out(filename, out.binary | out.trunc | out.out); - - head( out ); - - - out <<"// sine of full circle for input in degrees"<< endl; - out << "static std::array sin_angle_table__ {"<< endl; - - out << std::dec << endl; - for( int16_t i{0}; i != 361 ; i++ ) - { - double rad { static_cast(i) * phi / 180. }; - fixed_t ftab { floating_point_to_fixed( std::sin( rad ) ) }; - fixed_internal tabvalue{ ftab.v }; - out << " " << tabvalue << "ll /* sin("<< rad <<") ~=" << ftab << "*/"; - if( i != 360 ) - out << ", "; - if( i != 0 && (i+1) % 2 == 0 ) - out << endl; - } - out <<"};"<< endl; - out << endl; - out <<"fixed_t sin_angle_tab( uint16_t index ) noexcept"<< endl; - out <<" {" << endl; - out <<" return as_fixed(sin_angle_table__[index]);"<< endl; - out <<" }"<< endl; - foot(out); - } -int main(int argc, char **argv) -{ - gen_sqrt_tab(); - gen_tan_tab(); - gen_cos_angle_tab(); - gen_sin_angle_tab(); -} diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt index 210db55..81e08b0 100644 --- a/unit_tests/CMakeLists.txt +++ b/unit_tests/CMakeLists.txt @@ -1,56 +1,64 @@ include(CheckSourceCompiles) +#---------------------------------------------------------------- +# boost-ext/ut +#---------------------------------------------------------------- +CPMAddPackage( + ut + GITHUB_REPOSITORY arturbac/ut-ext + GIT_TAG v2.0.1_5 +) +find_package(ut-ext REQUIRED) -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set( CMAKE_REQUIRED_FLAGS -std=c++20) - check_source_compiles(CXX "int main(void){return 0;}" SUPPORTS_CXX20) -else() - set(SUPPORTS_CXX20 FALSE) -endif() +add_library( fixedmath_ut_core INTERFACE ) + +target_link_libraries( fixedmath_ut_core + INTERFACE + fixed_math + Boost::ut + ) +target_include_directories( fixedmath_ut_core INTERFACE include ) -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set( CMAKE_REQUIRED_FLAGS -std=c++2b) - check_source_compiles(CXX "int main(void){return 0;}" SUPPORTS_CXX23) -else() - set(SUPPORTS_CXX23 FALSE) +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + target_compile_options(fixedmath_ut_core + INTERFACE + -Wno-disabled-macro-expansion + -Wno-used-but-marked-unused + -Wno-global-constructors + -Wno-exit-time-destructors + -Wno-ctad-maybe-unsupported + -Wno-weak-vtables + -fconstexpr-backtrace-limit=0 + -Wno-misleading-indentation + ) endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(fixedmath_ut_core + INTERFACE + -Wno-misleading-indentation + -Wno-attributes + -Wno-unused-parameter + ) +endif() +add_custom_target( unit_tests ) + +function( add_fixedmath_ut name ) + add_executable(${name}) + target_sources(${name} PRIVATE ${name}.cc) + target_link_libraries( ${name} PRIVATE fixedmath_ut_core ) -set( TEST_DEFINITIONS -DFIXEDMATH_ENABLE_SQRT_ABACUS_ALGO ) -function(add_compile_test HEADER_FILE_NAME ) - get_filename_component(TEST_NAME ${HEADER_FILE_NAME} NAME_WE) - set( SOURCE_FILE_NAME test_${TEST_NAME}.cc ) - - set( FIXED_MATH_INCLUDES ${PROJECT_SOURCE_DIR}/fixed_lib/include ) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME} "#include \nint main( int argc, char ** argv ) {return fixedmath::${HEADER_FILE_NAME}_unit_tests() ? EXIT_SUCCESS : EXIT_FAILURE; }\n" ) - add_test(NAME ${TEST_NAME}_cxx17 - COMMAND ${CMAKE_CXX_COMPILER} -std=c++17 ${TEST_DEFINITIONS} -I${FIXED_MATH_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/test_${TEST_NAME}_cxx17.o ) - if( SUPPORTS_CXX20 ) - # using FIXEDMATH_ENABLE_SQRT_ABACUS_ALGO is not required for sqrt with c++20 standard - add_test(NAME ${TEST_NAME}_cxx20 - COMMAND ${CMAKE_CXX_COMPILER} -std=c++20 -I${FIXED_MATH_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/test_${TEST_NAME}_cxx20.o ) - endif() - if( SUPPORTS_CXX20 ) - add_test(NAME ${TEST_NAME}_cxx23 - COMMAND ${CMAKE_CXX_COMPILER} -std=c++2b -I${FIXED_MATH_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/test_${TEST_NAME}_cxx2b.o ) - endif() - if(FIXEDMATH_ENABLE_DEVEL_CODE) - add_executable( ${TEST_NAME}_DEVEL ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_FILE_NAME}) - target_link_libraries( ${TEST_NAME}_DEVEL PRIVATE fixed_math ) - endif() + add_dependencies(unit_tests ${name} ) + add_test( NAME ${name}_test COMMAND ${name} ) endfunction() -add_compile_test( type_traits ) -add_compile_test( integral_type_convertions ) -add_compile_test( floating_point_type_convertions ) -add_compile_test( fixed_construction ) -add_compile_test( addition ) -add_compile_test( substraction ) -add_compile_test( multiplication ) -add_compile_test( division ) -add_compile_test( sqrt ) -add_compile_test( misc_functions ) -add_compile_test( sin ) -add_compile_test( tan ) -add_compile_test( atan ) +add_fixedmath_ut( fixed_construction_ut ) +add_fixedmath_ut( type_convertions_ut ) +add_fixedmath_ut( addition_ut ) +add_fixedmath_ut( subtraction_ut ) +add_fixedmath_ut( sqrt_ut ) +add_fixedmath_ut( multiplication_ut ) +add_fixedmath_ut( division_ut ) +add_fixedmath_ut( misc_functions_ut ) +add_fixedmath_ut( sin_cos_ut ) +add_fixedmath_ut( tan_ut ) +add_fixedmath_ut( atan_ut ) -add_executable( hypot_not_abacus hypot_not_abacus.cc ) -target_link_libraries( hypot_not_abacus fixed_math ) diff --git a/unit_tests/addition_ut.cc b/unit_tests/addition_ut.cc new file mode 100644 index 0000000..d2c1c7b --- /dev/null +++ b/unit_tests/addition_ut.cc @@ -0,0 +1,71 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; + +int main() + { + test_result result; + using F = fixedmath::fixed_internal; + "addition"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(fobj::add(0_fix, 1_fix), 1_fix); + expect_eq(fobj::add(1_fix, 1_fix), 2_fix); + expect_eq(fobj::add(10_fix, 1_fix), 11_fix); + expect_eq(fobj::add(-10_fix, 1_fix), -9_fix); + + expect_eq(0_fix + 1_fix, 1_fix); + expect_eq(1_fix + 1_fix, 2_fix); + expect_eq(10.4_fix + 1_fix, 11.4_fix); + expect_eq(-10_fix + 1_fix, -9_fix); + + expect_eq(0_fix + 1, 1_fix); + expect_eq(1 + 1_fix, 2_fix); + expect_eq(10.4 + 1_fix, 11.4); + expect_eq(10.5_fix + 10.2, 20.7); + expect_eq(-10.5_fix + uint8_t(10), -0.5_fix); + expect_eq(-10.5_fix + uint16_t(10), -0.5_fix); + expect_eq(-10.5_fix + uint32_t(10), -0.5_fix); + expect_eq(-10.5_fix + uint64_t(10), -0.5_fix); + expect_eq(uint8_t(10) + -10.5_fix, -.5_fix); + expect_eq(uint16_t(10) + -10.5_fix, -.5_fix); + expect_eq(uint32_t(10) + -10.5_fix, -.5_fix); + expect_eq(uint64_t(10) + -10.5_fix, -.5_fix); + expect_eq(-10_fix + 1, -9_fix); + expect_eq(10.5_fix + -10., .5); + expect_eq(10.5_fix + -10.f, .5_fix); + expect_lt(limits_::max(), limits_::quiet_NaN()); + expect_neq(limits_::lowest() + 1, limits_::quiet_NaN()); + + expect_neq(as_fixed(limits_::max().v - 65536) + 1_fix, limits_::quiet_NaN()); + + expect( test_resulting_type( int64_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + int64_t(1) ) ); + expect( test_resulting_type( uint64_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + uint64_t(1) ) ); + expect( test_resulting_type( 1_fix + 1_fix ) ); + expect( test_resulting_type( 1 + 1_fix ) ); + expect( test_resulting_type( 1_fix + 1 ) ); + expect( test_resulting_type( int16_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + int16_t(1) ) ); + expect( test_resulting_type( uint16_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + uint16_t(1) ) ); + expect( test_resulting_type( int8_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + int8_t(1) ) ); + expect( test_resulting_type( uint8_t(1) + 1_fix ) ); + expect( test_resulting_type( 1_fix + uint8_t(1) ) ); + expect( test_resulting_type( 1.f + 1_fix ) ); + expect( test_resulting_type( 1_fix + 1.f ) ); + expect( test_resulting_type( 1. + 1_fix ) ); + expect( test_resulting_type( 1_fix + 1. ) ); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } + diff --git a/unit_tests/atan_ut.cc b/unit_tests/atan_ut.cc new file mode 100644 index 0000000..efca937 --- /dev/null +++ b/unit_tests/atan_ut.cc @@ -0,0 +1,390 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +constexpr void + test_atan(fixed_t x, fixed_t expected, fixed_t aprox, source_location const location = source_location::current()) + { + // constexpr double expected_precision = ; //0.000025 + expect_approx(atan(x), expected, aprox, location); + expect_approx(atan(-x), -expected, aprox, location); + } + +constexpr void test_atan2( + fixed_t y, fixed_t x, fixed_t expected, fixed_t aprox, source_location const location = source_location::current() +) + { + // constexpr double expected_precision = 0.00005; //0.000025 + expect_approx(atan2(y, x), expected, aprox, location); + } + +int main() + { + test_result result; + "atan"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_atan(1_fix / 16, 0.062418_fix, 0.000025_fix); + test_atan(3_fix / 16, 0.185347_fix, 0.000025_fix); + test_atan(5_fix / 16, 0.302884_fix, 0.000025_fix); + test_atan(7_fix / 16, 0.412410_fix, 0.000025_fix); + test_atan(8_fix / 16, 0.463647_fix, 0.000025_fix); + test_atan(9_fix / 16, 0.512389_fix, 0.000025_fix); + test_atan(11_fix / 16, 0.602287_fix, 0.000025_fix); + test_atan(13_fix / 16, 0.682316_fix, 0.000025_fix); + test_atan(15_fix / 16, 0.753151_fix, 0.000025_fix); + test_atan(17_fix / 16, 0.815691_fix, 0.000025_fix); + test_atan(19_fix / 16, 0.870903_fix, 0.000025_fix); + test_atan(21_fix / 16, 0.919719_fix, 0.000025_fix); + test_atan(25_fix / 16, 1.001483_fix, 0.000025_fix); + test_atan(37_fix / 16, 1.162647_fix, 0.000025_fix); + test_atan(39_fix / 16, 1.181479_fix, 0.000025_fix); + test_atan(40_fix / 16, 1.190289_fix, 0.00005_fix); + test_atan(45_fix / 16, 1.229180_fix, 0.00005_fix); + + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "atan2"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_atan2(-1 / 2_fix, -1 / 2_fix, -2.3561944901923448_fix, 0.00005_fix); + + // Thise are generated according to representation of fractions in fixed_t then + // std::atan2(static_cast +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +int main() + { + test_result result; + + "division"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(1_fix / 1_fix, 1_fix); + expect_eq(-1_fix / 1_fix, -1_fix); + expect_eq(1_fix / -1_fix, -1_fix); + expect_eq(-1_fix / -1_fix, 1_fix); + expect_eq(1_fix / 1, 1_fix); + expect_eq(100_fix / 10_fix, 10_fix); + expect_eq(100_fix / 10, 10_fix); + expect_eq(-10_fix / 1, -10_fix); + expect_eq(-10_fix / 1_fix, -10_fix); + expect_eq(1_fix / 2_fix, 0.5_fix); + expect_eq(1_fix / 4_fix, 0.25_fix); + expect_eq(-1_fix / 4, -0.25_fix); + + expect_eq(int8_t{1} / -4_fix, -0.25_fix); + expect_eq(int16_t{1} / -4_fix, -0.25_fix); + expect_eq(int32_t{1} / -4_fix, -0.25_fix); + expect_eq(int64_t{1} / -4_fix, -0.25_fix); + expect_eq(float{1} / -4_fix, -0.25_fix); + expect_approx(double{1} / -4_fix, -0.25, 0.0000000001); + + expect_eq(uint8_t{1} / -4_fix, -0.25_fix); + expect_eq(uint16_t{1} / -4_fix, -0.25_fix); + expect_eq(uint32_t{1} / -4_fix, -0.25_fix); + expect_eq(uint64_t{1} / -4_fix, -0.25_fix); + + expect_eq(-1_fix / uint8_t(4), -0.25_fix); + expect_eq(-1_fix / uint16_t(4), -0.25_fix); + expect_eq(-1_fix / uint32_t(4), -0.25_fix); + expect_eq(-1_fix / uint64_t(4), -0.25_fix); + + expect_eq(-1_fix / int8_t(4), -0.25_fix); + expect_eq(-1_fix / int16_t(4), -0.25_fix); + expect_eq(-1_fix / int32_t(4), -0.25_fix); + expect_eq(-1_fix / int64_t(4), -0.25_fix); + + expect_eq(1 / 4_fix, 0.25_fix); + + expect_eq(4 / 1_fix, 4_fix); + expect_eq(4 / 0.5_fix, 8_fix); + + expect_eq(1625.625_fix / 0.625_fix, 2601_fix); + + expect(test_resulting_type(int64_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / int64_t(1))); + expect(test_resulting_type(uint64_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / uint64_t(1))); + expect(test_resulting_type(1_fix / 1_fix)); + expect(test_resulting_type(1 / 1_fix)); + expect(test_resulting_type(1_fix / 1)); + expect(test_resulting_type(int16_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / int16_t(1))); + expect(test_resulting_type(uint16_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / uint16_t(1))); + expect(test_resulting_type(int8_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / int8_t(1))); + expect(test_resulting_type(uint8_t(1) / 1_fix)); + expect(test_resulting_type(1_fix / uint8_t(1))); + expect(test_resulting_type(1.f / 1_fix)); + expect(test_resulting_type(1_fix / 1.f)); + expect(test_resulting_type(1. / 1_fix)); + expect(test_resulting_type(1_fix / 1.)); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/fixed_construction_ut.cc b/unit_tests/fixed_construction_ut.cc new file mode 100644 index 0000000..e38af90 --- /dev/null +++ b/unit_tests/fixed_construction_ut.cc @@ -0,0 +1,128 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using F = fixedmath::fixed_internal; +using namespace fixedmath; + +using concepts::fixed_point; + +static_assert(fixed_point); +static_assert(!fixed_point); +static_assert(!fixed_point); + +using typetraits::is_integral_v; +static_assert(is_integral_v); +static_assert(is_integral_v); +static_assert(is_integral_v); +static_assert(is_integral_v); +static_assert(!is_integral_v); +static_assert(!is_integral_v); + +using typetraits::is_signed_v; +static_assert(is_signed_v); +static_assert(is_signed_v); +static_assert(is_signed_v); +static_assert(is_signed_v); +static_assert(is_signed_v); +static_assert(is_signed_v); +static_assert(!is_signed_v); +static_assert(!is_signed_v); +static_assert(!is_signed_v); +static_assert(!is_signed_v); +static_assert(is_signed_v); + +using typetraits::is_unsigned_v; +static_assert(!is_unsigned_v); +static_assert(!is_unsigned_v); +static_assert(!is_unsigned_v); +static_assert(!is_unsigned_v); +static_assert(!is_unsigned_v); +static_assert(!is_unsigned_v); +static_assert(is_unsigned_v); +static_assert(is_unsigned_v); +static_assert(is_unsigned_v); +static_assert(is_unsigned_v); +static_assert(!is_unsigned_v); + +using concepts::arithmetic; +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); +static_assert(arithmetic); + +using typetraits::is_floating_point_v; + +using typetraits::is_arithmetic_and_not_fixed_v; +static_assert(!is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); +static_assert(is_arithmetic_and_not_fixed_v); + +using typetraits::is_arithmetic_and_one_is_fixed_v; +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(is_arithmetic_and_one_is_fixed_v); +static_assert(!is_arithmetic_and_one_is_fixed_v); +static_assert(!is_arithmetic_and_one_is_fixed_v); + +using typetraits::one_of_is_double_v; +static_assert(!one_of_is_double_v); +static_assert(!one_of_is_double_v); +static_assert(one_of_is_double_v); +static_assert(!one_of_is_double_v); +static_assert(!one_of_is_double_v); +static_assert(one_of_is_double_v); +static_assert(!one_of_is_double_v); +static_assert(!one_of_is_double_v); +static_assert(one_of_is_double_v); + +int main() + { + test_result result; + "fixed construction"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(fixed_t{1}, 1_fix); + expect_eq(fixed_t{1u}, 1_fix); + expect_eq(fixed_t{1lu}, 1_fix); + expect_eq(fixed_t{1llu}, 1_fix); + expect_eq(fixed_t{-1}, -1_fix); + expect_eq(fixed_t{1.f}, 1_fix); + expect_eq(fixed_t{-1.f}, -1_fix); + expect_eq(fixed_t{2}, 2_fix); + expect_eq(fixed_t{-2}, -2_fix); + expect_eq(fixed_t{2.f}, 2_fix); + expect_eq(fixed_t{-2.f}, -2_fix); + expect_eq(fixed_t{4.f}, 4_fix); + expect_eq(fixed_t{-4.f}, -4_fix); + + expect_eq(fixed_t{4096ll}, 4096_fix); + expect_eq(fixed_t{-4096ll}, -4096_fix); + expect_eq(fixed_t{4096llu}, 4096_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/hypot_not_abacus.cc b/unit_tests/hypot_not_abacus.cc index acc8079..2e1d57f 100644 --- a/unit_tests/hypot_not_abacus.cc +++ b/unit_tests/hypot_not_abacus.cc @@ -6,7 +6,7 @@ namespace fixedmath { -fixed_t nhypot(fixed_t lh, fixed_t rh ) noexcept +static fixed_t nhypot(fixed_t lh, fixed_t rh ) noexcept { constexpr int prec_ = 16; //sqrt(X^2+Y^2) = sqrt( (X/D)^2+(Y/D)^2) * D @@ -29,7 +29,7 @@ fixed_t nhypot(fixed_t lh, fixed_t rh ) noexcept int llbits{ cxx20::countl_zero( ulo ) }; int lrbits{ cxx20::countr_zero( ulo ) }; - if( fixed_unlikely(uhi == 0) ) + if( uhi == 0 ) return 0_fix; //check hi for overflow and shift right with d else if( uhi >= (1ull<<30) ) @@ -37,7 +37,7 @@ fixed_t nhypot(fixed_t lh, fixed_t rh ) noexcept int rshbits{ std::min(cxx20::countr_zero( uhi ),cxx20::countr_zero( ulo )) }; uhi >>= rshbits; ulo >>= rshbits; - return as_fixed(sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_ ) ).v << rshbits) ; + return as_fixed(sqrt( as_fixed( fixed_internal((uhi*uhi+ulo*ulo)>>prec_) ) ).v << rshbits) ; } //else check lo for underflow and shift left with d else if( ulo < (1<<16) ) @@ -52,10 +52,10 @@ fixed_t nhypot(fixed_t lh, fixed_t rh ) noexcept uhi <<= lshbits; ulo <<= lshbits; - return as_fixed( fixedmath::sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_) ).v >> lshbits); + return as_fixed( fixedmath::sqrt( as_fixed( fixed_internal((uhi*uhi+ulo*ulo)>>prec_)) ).v >> lshbits); } else - return sqrt( as_fixed( (uhi*uhi+ulo*ulo)>>prec_ ) ); + return sqrt( as_fixed( fixed_internal((uhi*uhi+ulo*ulo)>>prec_) ) ); } inline void test_hypot( fixed_t x, fixed_t y, fixed_t expected ) { @@ -66,6 +66,7 @@ inline void test_hypot( fixed_t x, fixed_t y, fixed_t expected ) } } +using FX = fixedmath::fixed_internal; int main( int argc, char ** argv ) { using namespace fixedmath; @@ -82,7 +83,7 @@ int main( int argc, char ** argv ) ( test_hypot(-0.774933_fix,-4.295090_fix, 4.3644377251651436_fix)); test_hypot(-20.245346_fix,-0.909424_fix, 20.265762_fix); // d20.2657614997891855 h20.2657470703125000 ex20.2657623291015625 - ( test_hypot(as_fixed(1ul<<32),as_fixed(1ul<<31), 73270_fix)); + ( test_hypot(as_fixed(FX(1ul<<32)),as_fixed(FX(1ul<<31)), 73270_fix)); ( test_hypot(as_fixed(1ul<<30),as_fixed(1<<0ul), 16384_fix) ); ( test_hypot(as_fixed(1ul<<33),as_fixed(1ul<<31), 135104_fix) ); ( test_hypot(as_fixed(1ul<<31),as_fixed(1ul<<31), 46340_fix)); diff --git a/unit_tests/include/atan.h b/unit_tests/include/atan.h new file mode 100644 index 0000000..182b75a --- /dev/null +++ b/unit_tests/include/atan.h @@ -0,0 +1,23 @@ +#pragma once + +#include "unit_test_common.h" + +namespace fixedmath +{ + + + +[[nodiscard]] +constexpr bool atan_unit_tests() noexcept + { + //------------------------------------------------------------------------------------------------------ + // + // atan + // + + + return true; + } + + static_assert(atan_unit_tests()); +} diff --git a/unit_tests/include/boost_ut.h b/unit_tests/include/boost_ut.h new file mode 100644 index 0000000..3c8386f --- /dev/null +++ b/unit_tests/include/boost_ut.h @@ -0,0 +1,14 @@ +#pragma once + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wextra-semi" +#pragma clang diagnostic ignored "-Wreserved-identifier" +#endif + +#include + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif diff --git a/unit_tests/include/type_traits.h b/unit_tests/include/type_traits.h new file mode 100644 index 0000000..601851d --- /dev/null +++ b/unit_tests/include/type_traits.h @@ -0,0 +1,25 @@ +#pragma once + +#include "unit_test_common.h" + +namespace fixedmath +{ + +using detail::limits_; +using detail::flimits_; +using detail::dlimits_; +[[nodiscard]] +constexpr bool type_traits_unit_tests() noexcept + { + //------------------------------------------------------------------------------------------------------ + // + // type traits + // + + + return true; + } + + static_assert(type_traits_unit_tests()); +} + diff --git a/unit_tests/include/unit_test_common.h b/unit_tests/include/unit_test_common.h new file mode 100644 index 0000000..dd50ab7 --- /dev/null +++ b/unit_tests/include/unit_test_common.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace fixedmath + { +using detail::dlimits_; +using detail::flimits_; +using detail::limits_; + +#define make_const_value(x) const_val +#define static_assert_equal(x, y) static_assert(assert_equal_t::eq()) + +template +struct const_val + { + static constexpr T value{val}; + consteval const_val() = default; + + consteval const_val(T) {} + }; + +template +consteval bool test_resulting_type(input) + { + return std::is_same::value; + } + +template +consteval value_type ut_abs(value_type value) + { + return value > value_type{0} ? value : -value; + } + } // namespace fixedmath diff --git a/unit_tests/include/unit_test_core.h b/unit_tests/include/unit_test_core.h new file mode 100644 index 0000000..1c0aa36 --- /dev/null +++ b/unit_tests/include/unit_test_core.h @@ -0,0 +1,614 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace metatests + { +using boost::ut::reflection::source_location; + +struct test_result + { + enum struct value_type : uint8_t + { + succeed, + failed + }; + using enum value_type; + value_type value_{}; + + explicit constexpr operator bool() const noexcept { return value_ == succeed; } + + constexpr test_result() noexcept = default; + + explicit constexpr test_result(bool value) noexcept : value_{value ? succeed : failed} {} + + explicit constexpr test_result(value_type value) noexcept : value_{value} {} + + constexpr test_result & operator|=(test_result rh) noexcept + { + value_ = value_ == failed || rh.value_ == failed ? failed : succeed; + return *this; + } + + constexpr test_result operator|(test_result rh) noexcept + { + return test_result{value_ == failed || rh.value_ == failed ? failed : succeed}; + } + }; + +template +concept is_any_of = (std::same_as || ...); + +template +concept compatibile_test_result = is_any_of; + +template +constexpr auto + expect(test_result_type expression, source_location const location = source_location::current()) -> test_result + { + if(std::is_constant_evaluated()) + { + if(!expression) + throw; + return test_result{expression}; + } + else + { + boost::ut::expect(static_cast(expression), location); + return test_result{expression}; + } + } + +template U> +constexpr auto + expect_eq(T const & left, U const & right, source_location const location = source_location::current()) -> test_result + { + if(std::is_constant_evaluated()) + { + if(left != right) + throw; + return test_result{left == right}; + } + else + { + boost::ut::expect(boost::ut::eq(left, right), location); + return test_result{left == right}; + } + } + +template U> +constexpr auto expect_neq(T const & left, U const & right, source_location const location = source_location::current()) + -> test_result + { + if(std::is_constant_evaluated()) + { + if(left == right) + throw; + return test_result{left != right}; + } + else + { + boost::ut::expect(boost::ut::neq(left, right), location); + return test_result{left != right}; + } + } + +template U> +constexpr auto + expect_gt(T const & left, U const & right, source_location const location = source_location::current()) -> test_result + { + if(std::is_constant_evaluated()) + { + if(left <= right) + throw; + return test_result{left > right}; + } + else + { + boost::ut::expect(boost::ut::gt(left, right), location); + return test_result{left > right}; + } + } + +template U> +constexpr auto + expect_lt(T const & left, U const & right, source_location const location = source_location::current()) -> test_result + { + if(std::is_constant_evaluated()) + { + if(left >= right) + throw; + return test_result{left < right}; + } + else + { + boost::ut::expect(boost::ut::lt(left, right), location); + return test_result{left < right}; + } + } +template + requires requires(T const & t, U const & u, X const & x) { + { t - u } -> std::three_way_comparable_with; + } +constexpr auto expect_approx( + T const & left, U const & right, X const & approx, source_location const location = source_location::current() +) -> test_result + { + if(std::is_constant_evaluated()) + { + using sub_res_type = decltype(left - right); + sub_res_type diff{left - right}; + if(diff < sub_res_type(0)) + diff = -diff; + if(diff >= approx) + throw; + return test_result{diff < approx}; + } + else + { + boost::ut::expect(boost::ut::approx(left, right, approx), location); + return test_result{boost::ut::approx(left, right, approx)}; + } + } + +template +test_result require_throw(test_type const & test) noexcept + { + try + { + test(); + } + catch(except const &) + { + return test_result{}; + } + catch(...) + { + return test_result{false}; + } + return test_result{false}; + } + +template +test_result require_throw(test_type const & test) noexcept + { + try + { + test(); + } + catch(...) + { + return test_result{}; + } + return test_result{false}; + } + +template +[[maybe_unused]] +constexpr test_result + run_runtime_test(unit_test const & test, source_location const location = source_location::current()) + { + return expect(test(), location); + } + +template +[[maybe_unused]] +consteval test_result + run_consteval_test(unit_test const & test, source_location const location = source_location::current()) + { + return expect(test(), location); + } + +namespace detail + { + template + struct infer_type + { + using type = T; + using next_elem = infer_type; + }; + + template + struct infer_type + { + using type = T; + using next_elem = void; + }; + } // namespace detail + +template +struct type_list + { + using type_iterator = detail::infer_type; + }; + +namespace detail + { + template + struct test_invoke + { + template + constexpr static test_result constexpr_run(unit_test const & test) + { + return test_invoke::do_run(test); + } + + template + consteval static test_result consteval_run(unit_test const & test) + { + return test_invoke::do_run(test); + } + + template + constexpr static test_result do_run(unit_test const & test) + { + using test_type = typename templ_list::type; + using next_test = typename templ_list::next_elem; + using ptr_type = test_type const *; + test_result res = test(ptr_type{}); + if constexpr(!std::is_same_v) + res |= test_invoke::do_run(test); + return res; + } + }; + + } // namespace detail + +template +[[maybe_unused]] +constexpr test_result + run_runtime_test(unit_test const & test, source_location const location = source_location::current()) + { + return expect(detail::test_invoke::constexpr_run(test), location); + } + +template +[[maybe_unused]] +consteval test_result + run_consteval_test(unit_test const & test, source_location const location = source_location::current()) + { +#ifndef DISABLE_CONSTEVAL_TESTING + // same gcc can fail building consteval complicated code, ex on ubuntu it reports nonsense while on gentoo there is no + // problem at all + return expect(detail::test_invoke::consteval_run(test), location); +#else + return test_result{}; +#endif + } + +consteval test_result test() + { + using traits_test_list = metatests::type_list; + int counter{}; + auto test_fn = [&counter](value_type const *) -> test_result + { + counter++; + return test_result{}; + }; + + auto res = run_runtime_test(test_fn); + return res | test_result{counter == 4}; + } + +static_assert(test()); + +namespace detail + { + template + struct test_invoke_dual + { + template + constexpr static test_result constexpr_run(unit_test const & test) + { + return test_invoke_dual::do_run(test); + } + + template + consteval static test_result consteval_run(unit_test const & test) + { + return test_invoke_dual::do_run(test); + } + + template + constexpr static test_result do_run(unit_test const & test) + { + using test_type = typename templ_list::type; + using next_test = typename templ_list::next_elem; + + test_result res = do_run_sec(test); + if constexpr(!std::is_same_v) + res |= test_invoke_dual::do_run(test); + return res; + } + + template + constexpr static test_result do_run_sec(unit_test const & test) + { + using test_type2 = typename templ_list2::type; + using next_test = typename templ_list2::next_elem; + + using ptr_type1 = test_type1 const *; + using ptr_type2 = test_type2 const *; + test_result res = test(ptr_type1{}, ptr_type2{}); + if constexpr(!std::is_same_v) + res |= test_invoke_dual::template do_run_sec(test); + return res; + } + }; + } // namespace detail + +template +[[maybe_unused]] +constexpr test_result + run_constexpr_test_dual(unit_test const & test, source_location const location = source_location::current()) + { + return expect(detail::test_invoke_dual::constexpr_run(test), location); + } + +template +[[maybe_unused]] +consteval test_result + run_consteval_test_dual(unit_test const & test, source_location const location = source_location::current()) + { + return expect(detail::test_invoke_dual::consteval_run(test), location); + } + +consteval test_result test_dual() + { + using traits_test_list = metatests::type_list; + using traits_test_list2 = metatests::type_list; + int counter{}; + auto test_fn + = [&counter](value_type const *, value_type2 const *) -> test_result + { + counter++; + return test_result{}; + }; + + auto res = run_constexpr_test_dual(test_fn); + return res | test_result{counter == 12}; + } + +static_assert(test_dual()); + } // namespace metatests + +void dump(auto const & result) + { + for(auto el: result) + std::cout << el << ","; + std::cout << std::endl; + } + +struct non_trivial + { + int value_; + + constexpr non_trivial() noexcept : value_{0x1fff'ffff} {} + + constexpr non_trivial(int value) noexcept : value_{value} {} + + constexpr non_trivial(non_trivial && r) noexcept : value_{std::exchange(r.value_, 0x1fff'ffff)} {} + + constexpr non_trivial(non_trivial const & r) noexcept : value_{r.value_} {} + + constexpr non_trivial & operator=(non_trivial && r) noexcept + { + value_ = std::exchange(r.value_, 0x1fff'ffff); + return *this; + } + + constexpr non_trivial & operator=(non_trivial const & r) noexcept + { + value_ = r.value_; + return *this; + } + + constexpr non_trivial & operator++() noexcept + { + ++value_; + return *this; + } + + constexpr ~non_trivial() {} + + constexpr bool operator==(non_trivial const & r) const noexcept = default; + + constexpr bool operator==(int r) const noexcept { return value_ == r; } + + void swap(non_trivial & r) noexcept { std::swap(value_, r.value_); } + }; + +inline std::ostream & operator<<(std::ostream & stream, non_trivial const & v) + { + stream << v.value_; + return stream; + } + +struct non_trivial_ptr + { + int * value_; + + constexpr non_trivial_ptr() noexcept : value_{} {} + + constexpr non_trivial_ptr(int value) noexcept : value_{new int{value}} {} + + constexpr non_trivial_ptr(non_trivial_ptr && r) noexcept : value_{std::exchange(r.value_, nullptr)} {} + + constexpr non_trivial_ptr(non_trivial_ptr const & r) noexcept : value_{} + { + if(r.value_ != nullptr) + value_ = new int(*r.value_); + } + + constexpr non_trivial_ptr & operator=(non_trivial_ptr && r) noexcept + { + if(value_ != nullptr) + delete value_; + + value_ = std::exchange(r.value_, nullptr); + return *this; + } + + constexpr non_trivial_ptr & operator=(non_trivial_ptr const & r) noexcept + { + if(value_ != nullptr) + { + delete value_; + value_ = nullptr; + } + if(r.value_ != nullptr) + value_ = new int(*r.value_); + return *this; + } + + constexpr non_trivial_ptr & operator++() noexcept + { + assert(value_ != nullptr); + ++*value_; + return *this; + } + + constexpr ~non_trivial_ptr() + { + if(value_ != nullptr) + delete value_; + } + + constexpr bool operator==(non_trivial_ptr const & r) const noexcept + { + if(value_ != nullptr && r.value_ != nullptr) + return *value_ == *r.value_; + + return value_ == nullptr && r.value_ == nullptr; + } + + constexpr bool operator==(int r) const noexcept + { + if(value_ != nullptr) + return *value_ == r; + return false; + } + + constexpr int value() const noexcept { return *value_; } + + constexpr void swap(non_trivial_ptr & r) noexcept { std::swap(value_, r.value_); } + }; + +struct non_trivial_ptr_except + { + non_trivial_ptr obj; + constexpr non_trivial_ptr_except() noexcept(false) = default; + + constexpr non_trivial_ptr_except(int value) noexcept(false) : obj{value} {} + + constexpr non_trivial_ptr_except(non_trivial_ptr_except && r) noexcept(false) = default; + constexpr non_trivial_ptr_except(non_trivial_ptr_except const & r) noexcept(false) = default; + constexpr non_trivial_ptr_except & operator=(non_trivial_ptr_except && r) noexcept(false) = default; + constexpr non_trivial_ptr_except & operator=(non_trivial_ptr_except const & r) noexcept(false) = default; + constexpr ~non_trivial_ptr_except() = default; + + constexpr non_trivial_ptr_except & operator++() noexcept + { + ++obj; + return *this; + } + + constexpr bool operator==(non_trivial_ptr_except const &) const noexcept = default; + + constexpr int value() const noexcept(false) { return obj.value(); } + + constexpr void swap(non_trivial_ptr_except & r) { std::swap(obj, r.obj); } + }; + +struct non_trivial_ptr_except_copy + { + non_trivial_ptr obj; + constexpr non_trivial_ptr_except_copy() noexcept(false) = default; + + constexpr non_trivial_ptr_except_copy(int value) noexcept(false) : obj{value} {} + + constexpr non_trivial_ptr_except_copy(non_trivial_ptr_except_copy const & r) noexcept(false) = default; + constexpr non_trivial_ptr_except_copy & operator=(non_trivial_ptr_except_copy const & r) noexcept(false) = default; + constexpr ~non_trivial_ptr_except_copy() = default; + + constexpr non_trivial_ptr_except_copy & operator++() noexcept + { + ++obj; + return *this; + } + + constexpr bool operator==(non_trivial_ptr_except_copy const &) const noexcept = default; + }; + +// for testing strong exception guarantee +template +struct non_trivial_throwing_tmpl : public Super + { + using super_type = Super; + constexpr non_trivial_throwing_tmpl() noexcept(std::is_nothrow_default_constructible_v) = default; + + constexpr non_trivial_throwing_tmpl(int value) noexcept(std::is_nothrow_constructible_v) : + super_type{value} + { + } + + constexpr non_trivial_throwing_tmpl(non_trivial_throwing_tmpl const & r) : super_type{r} + { + if constexpr(not noexcept(super_type{r})) + if(operator==(throw_at_value)) + throw std::runtime_error{""}; + } + + constexpr non_trivial_throwing_tmpl(non_trivial_throwing_tmpl && r) noexcept(noexcept(super_type{std::move(r)})) : + super_type{std::move(r)} + { + if constexpr(not noexcept(super_type{std::move(r)})) + if(operator==(throw_at_value)) + throw std::runtime_error{""}; + } + + using super_type::operator==; + using super_type::operator++; + + void set_value(int value) { super_type::operator=(value); } + + constexpr non_trivial_throwing_tmpl & operator=(non_trivial_throwing_tmpl const & r) + { + super_type::operator=(r); + if constexpr(not noexcept(super_type::operator=(r))) + if(operator==(throw_at_value)) + throw std::runtime_error{""}; + return *this; + } + + constexpr non_trivial_throwing_tmpl & operator=(non_trivial_throwing_tmpl && r + ) noexcept(noexcept(super_type::operator=(std::move(r)))) + { + super_type::operator=(r); + if constexpr(not noexcept(super_type::operator=(std::move(r)))) + if(operator==(throw_at_value)) + throw std::runtime_error{""}; + return *this; + } + + constexpr ~non_trivial_throwing_tmpl() = default; + }; + +template +using non_trivial_throwing = non_trivial_throwing_tmpl; + +template +using non_trivial_throwing_copy = non_trivial_throwing_tmpl; + +std::ostream & operator<<(std::ostream & stream, non_trivial_ptr const & v); +std::ostream & operator<<(std::ostream & stream, non_trivial_ptr_except const & v); +std::ostream & operator<<(std::ostream & stream, non_trivial_ptr_except_copy const & v); diff --git a/unit_tests/misc_functions_ut.cc b/unit_tests/misc_functions_ut.cc new file mode 100644 index 0000000..480776c --- /dev/null +++ b/unit_tests/misc_functions_ut.cc @@ -0,0 +1,64 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +int main() + { + test_result result; + + "ceil"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(ceil(-0.25_fix), 0_fix); + expect_eq(ceil(-1.25_fix), -1_fix); + expect_eq(ceil(-10.25_fix), -10_fix); + expect_eq(ceil(-10.95_fix), -10_fix); + expect_eq(ceil(0.25_fix), 1_fix); + expect_eq(ceil(0.75_fix), 1_fix); + expect_eq(ceil(as_fixed(fixed_internal(1ul))), 1_fix); + expect_eq(ceil(5.25_fix), 6_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "floor"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(fixed_to_arithmetic(floor(0.25_fix)), 0); + expect_eq(floor(-1_fix + limits_::epsilon()), -1_fix); // + expect_eq(floor(-1_fix - limits_::epsilon()), -2_fix); // + expect_eq(floor(-0.25_fix), -1_fix); + expect_eq(floor(0.25_fix), 0_fix); + expect_eq(floor(0.95_fix), 0_fix); + expect_eq(floor(1.25_fix), 1_fix); + expect_eq(floor(-1.25_fix), -2_fix); + + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "angle_to_radians"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(angle_to_radians(0), 0_fix); + expect_eq(angle_to_radians(180), 3.1415926536_fix); + expect_eq(angle_to_radians(180), phi); + expect_eq(angle_to_radians(90), phi / 2); + expect_eq(angle_to_radians(45), phi / 4); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/multiplication_ut.cc b/unit_tests/multiplication_ut.cc new file mode 100644 index 0000000..3c8db57 --- /dev/null +++ b/unit_tests/multiplication_ut.cc @@ -0,0 +1,67 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +int main() + { + test_result result; + using F = fixedmath::fixed_internal; + "multiplication"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(1_fix * 1_fix, 1_fix); + expect_eq(10_fix * 0.5_fix, 5_fix); + + expect_approx(0.8_fix * 0.2_fix, 0.16000_fix, 0.0001_fix); + expect_approx(0.8_fix * -0.2_fix, -0.16000_fix, 0.0001_fix); + + expect_eq(-1.25_fix * int8_t(4), -5_fix); + expect_eq(-1.25_fix * int16_t(4), -5_fix); + expect_eq(-1.25_fix * int32_t(4), -5_fix); + expect_eq(-1.25_fix * int64_t(4), -5_fix); + + expect_eq(-1.25_fix * uint8_t(4), -5_fix); + expect_eq(-1.25_fix * uint16_t(4), -5_fix); + expect_eq(-1.25_fix * uint32_t(4), -5_fix); + expect_eq(-1.25_fix * uint64_t(4), -5_fix); + + expect_eq(int8_t(4) * -1.25_fix, -5_fix); + expect_eq(int16_t(4) * -1.25_fix, -5_fix); + expect_eq(int32_t(4) * -1.25_fix, -5_fix); + expect_eq(int64_t(4) * -1.25_fix, -5_fix); + + expect_eq(uint8_t(4) * -1.25_fix, -5_fix); + expect_eq(uint16_t(4) * -1.25_fix, -5_fix); + expect_eq(uint32_t(4) * -1.25_fix, -5_fix); + expect_eq(uint64_t(4) * -1.25_fix, -5_fix); + + expect(test_resulting_type(int64_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * int64_t(1))); + expect(test_resulting_type(uint64_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * uint64_t(1))); + expect(test_resulting_type(1_fix * 1_fix)); + expect(test_resulting_type(1 * 1_fix)); + expect(test_resulting_type(1_fix * 1)); + expect(test_resulting_type(int16_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * int16_t(1))); + expect(test_resulting_type(uint16_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * uint16_t(1))); + expect(test_resulting_type(int8_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * int8_t(1))); + expect(test_resulting_type(uint8_t(1) * 1_fix)); + expect(test_resulting_type(1_fix * uint8_t(1))); + expect(test_resulting_type(1.f * 1_fix)); + expect(test_resulting_type(1_fix * 1.f)); + expect(test_resulting_type(1. * 1_fix)); + expect(test_resulting_type(1_fix * 1.)); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/sin_cos_ut.cc b/unit_tests/sin_cos_ut.cc new file mode 100644 index 0000000..07a47fc --- /dev/null +++ b/unit_tests/sin_cos_ut.cc @@ -0,0 +1,104 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +constexpr void + test_sin(fixed_t x, fixed_t expected, fixed_t aprox, source_location const location = source_location::current()) + { + expect_approx(sin(x), expected, aprox, location); + expect_approx(sin(x + 2 * phi), expected, aprox, location); + expect_approx(sin(x - 2 * phi), expected, aprox, location); + expect_approx(sin(x + 4 * phi), expected, aprox, location); + } + +constexpr void + test_cos(fixed_t x, fixed_t expected, fixed_t aprox, source_location const location = source_location::current()) + { + expect_approx(cos(x), expected, aprox, location); + expect_approx(cos(x + 2 * phi), expected, aprox, location); + expect_approx(cos(x - 2 * phi), expected, aprox, location); + expect_approx(cos(x + 4 * phi), expected, aprox, location); + } + +int main() + { + test_result result; + "sin"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_sin(phi + phi / 2, -0.99986_fix, 0.0001_fix); + test_sin(phi + phi / 4, -0.7071_fix, 0.0001_fix); + test_sin(phi, 0_fix, 0.0001_fix); + test_sin(0_fix, 0_fix, 0.0001_fix); + test_sin(phi / 2 + phi / 4, 0.7071_fix, 0.0001_fix); + + test_sin(phi / 2_fix, 0.99984_fix, 0.0001_fix); + test_sin(phi / 4_fix, 0.70709_fix, 0.0001_fix); + test_sin(phi / 5_fix, 0.58778_fix, 0.0001_fix); + test_sin(phi / 8_fix, 0.38265_fix, 0.0001_fix); + test_sin(phi / 16_fix, 0.19506_fix, 0.0001_fix); + test_sin(-phi / 16_fix, -0.19508_fix, 0.0001_fix); + test_sin(phi / -8_fix, -0.38267_fix, 0.0001_fix); + test_sin(phi / -5_fix, -0.58779_fix, 0.0001_fix); + test_sin(phi / -4_fix, -0.7071_fix, 0.0001_fix); + test_sin(phi / -2_fix, -0.99986_fix, 0.0001_fix); + + test_sin(phi + phi + phi / 2, 0.99984_fix, 0.0001_fix); + test_sin(phi + phi + phi / 4, 0.70709_fix, 0.0001_fix); + test_sin(phi + phi, 0_fix, 0.0001_fix); + test_sin(phi + phi / 2 + phi / 4, -0.70712_fix, 0.0001_fix); + test_sin(2 * phi + phi + phi / 2, -0.99986_fix, 0.0001_fix); + test_sin(2 * phi + phi + phi / 4, -0.7071_fix, 0.0001_fix); + test_sin(2 * phi + phi, 0_fix, 0.0001_fix); + test_sin(2 * phi + phi / 2 + phi / 4, 0.7071_fix, 0.0001_fix); + + test_sin(-phi - phi / 16, 0.19506_fix, 0.0001_fix); + test_sin(-phi - phi / 8, 0.38265_fix, 0.0001_fix); + test_sin(-phi - phi / 5, 0.58778_fix, 0.0001_fix); + test_sin(-phi - phi / 4, 0.70709_fix, 0.0001_fix); + test_sin(-phi - phi / 2, 0.99984_fix, 0.0001_fix); + + test_sin(-6 * phi + -95 * phi / 180, -0.99612_fix, 0.0001_fix); + test_sin(-4 * phi + -95 * phi / 180, -0.99612_fix, 0.0001_fix); + test_sin(-2 * phi + -95 * phi / 180, -0.99612_fix, 0.0001_fix); + test_sin(-95 * phi / 180, -0.99612_fix, 0.0001_fix); + test_sin(-90 * phi / 180, -0.99986_fix, 0.0001_fix); + test_sin(-85 * phi / 180, -0.99610_fix, 0.0001_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "cos"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_cos(2 * phi, 0.9998_fix, 0.0001_fix); + test_cos(phi, -0.9998_fix, 0.0001_fix); + test_cos(phi / 2 + phi / 4, -0.7071_fix, 0.0001_fix); + test_cos(phi / 2, 0_fix, 0.0001_fix); + test_cos(phi / 3, 0.49998_fix, 0.0001_fix); + test_cos(phi / 4, 0.7071_fix, 0.0001_fix); + test_cos(phi / 16, 0.98072_fix, 0.0001_fix); + test_cos(0_fix, 0.99984_fix, 0.0001_fix); + test_cos(-phi / 16, 0.98074_fix, 0.0001_fix); + test_cos(-phi / 4, 0.7071_fix, 0.0001_fix); + test_cos(-phi / 3, 0.5_fix, 0.0001_fix); + test_cos(-phi / 2, 0.0001_fix, 0.00014_fix); + test_cos(-phi / 2 + -phi / 4, -0.70709_fix, 0.0001_fix); + test_cos(-phi, -0.99986_fix, 0.0001_fix); + test_cos(2 * -phi, 0.99984_fix, 0.0001_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } + +// diff --git a/unit_tests/sqrt_ut.cc b/unit_tests/sqrt_ut.cc new file mode 100644 index 0000000..8083b61 --- /dev/null +++ b/unit_tests/sqrt_ut.cc @@ -0,0 +1,79 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +constexpr void test_hypot( + fixed_t x, fixed_t y, fixed_t expected, fixed_t aprox, source_location const location = source_location::current() +) + { + expect_approx(hypot(x, y), expected, aprox, location); + expect_approx(hypot(-x, y), expected, aprox, location); + expect_approx(hypot(x, -y), expected, aprox, location); + expect_approx(hypot(-x, -y), expected, aprox, location); + } + +template +constexpr auto asfix(T const v) + { + return as_fixed(fixedmath::fixed_internal(v)); + } + +int main() + { + test_result result; + using F = fixedmath::fixed_internal; + "sqrt"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_approx(sqrt(1.4111175537109375_fix), 1.1878_fix, 0.001_fix); + expect_approx(sqrt(2.0000000000000000_fix), 1.4141_fix, 0.001_fix); + expect_approx(sqrt(2.0124969482421875_fix), 1.4186_fix, 0.001_fix); + expect_approx(sqrt(3.3333282470703125_fix), 1.8257_fix, 0.001_fix); + expect_approx(sqrt(4.0000000000000000_fix), 2_fix, 0.001_fix); + expect_approx(sqrt(3331.0000000000000000_fix), 57.7148_fix, 0.001_fix); + expect_approx(sqrt(33331.0000000000000000_fix), 182.5677_fix, 0.001_fix); + expect_approx(sqrt(333331.1000061035156250_fix), 577.3483_fix, 0.001_fix); + expect_approx(sqrt(3333331.0215148925781250_fix), 1825.7412_fix, 0.001_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "hypot"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_hypot(-14.991608_fix, -0.837158_fix, 15.01495_fix, 0.0001_fix); + test_hypot(-14.991608_fix, -0.837158_fix, 15.01495_fix, 0.0001_fix); + test_hypot(-0.774933_fix, -4.295090_fix, 4.364425_fix, 0.0001_fix); + test_hypot(-20.245346_fix, -0.909424_fix, 20.26574_fix, 0.0001_fix); + test_hypot(14.9916076660156250_fix, 0_fix, 14.99160_fix, 0.0001_fix); + test_hypot(0_fix, 14.9916076660156250_fix, 14.99160_fix, 0.0001_fix); + + test_hypot(asfix(1ul << 30), asfix(1u << 0), 16384_fix, 0.0001_fix); + test_hypot(asfix(1ul << 33), asfix(1ul << 31), 135104_fix, 0.0001_fix); + test_hypot(asfix(1ul << 32), asfix(1ul << 31), 73271_fix, 1.1_fix); + test_hypot(asfix(1ul << 31), asfix(1ul << 31), 46340_fix, 1.1_fix); + test_hypot(asfix(1ul << 32), asfix(1ul), 65536_fix, 0.0001_fix); + test_hypot(asfix(1ul << 30), asfix(1u << 30), 23170_fix, 1_fix); + test_hypot(asfix((1ul << 30) - 1), asfix((1ul << 30) - 1), 23170.47497_fix, 0.0001_fix); + + test_hypot(asfix(1u), asfix(1u), 0.000015_fix, 0.00001_fix); + test_hypot(asfix(2u), asfix(2u), 0.000030_fix, 0.00001_fix); + test_hypot(asfix(1u), asfix(3u), 0.000045_fix, 0.00001_fix); + test_hypot(asfix(2u), asfix(3u), 0.000045_fix, 0.00001_fix); + test_hypot(0.0125_fix, 0.125_fix, 0.125610_fix, 0.00001_fix); + test_hypot(1_fix, 1_fix, 1.41419_fix, 0.0001_fix); + test_hypot(0.5_fix, 0.25_fix, 0.559005_fix, 0.0001_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/subtraction_ut.cc b/unit_tests/subtraction_ut.cc new file mode 100644 index 0000000..37d603b --- /dev/null +++ b/unit_tests/subtraction_ut.cc @@ -0,0 +1,61 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; + +int main() + { + test_result result; + using F = fixedmath::fixed_internal; + "addition"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(0.2_fix - 1.2_fix, -1_fix); + expect_eq(3.2_fix - 1.2_fix, 2_fix); + expect_eq(-4.2_fix - 1.2_fix, -5.4_fix); + expect_eq(-4.2_fix + 1.2_fix, -3_fix); + + static constexpr auto approx{std::numeric_limits::epsilon()}; + expect_approx(1_fix - 1., 1. - 1., approx); + expect_approx(2_fix - 1., 2. - 1., approx); + expect_approx(-2_fix - 1., -2. - 1., approx); + expect_approx(-2_fix + 1., -2. + 1., approx); + + expect_eq(-10.5_fix - uint8_t(10), -20.5_fix); + expect_eq(-10.5_fix - uint16_t(10), -20.5_fix); + expect_eq(-10.5_fix - uint32_t(10), -20.5_fix); + expect_eq(-10.5_fix - uint64_t(10), -20.5_fix); + expect_eq(uint8_t(10) - 10.5_fix, -.5_fix); + expect_eq(uint16_t(10) - 10.5_fix, -.5_fix); + expect_eq(uint32_t(10) - 10.5_fix, -.5_fix); + expect_eq(uint64_t(10) - 10.5_fix, -.5_fix); + expect_neq(limits_::max() - 1, limits_::quiet_NaN()); + + expect(test_resulting_type(int64_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - int64_t(1))); + expect(test_resulting_type(uint64_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - uint64_t(1))); + expect(test_resulting_type(1_fix - 1_fix)); + expect(test_resulting_type(1 - 1_fix)); + expect(test_resulting_type(1_fix - 1)); + expect(test_resulting_type(int16_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - int16_t(1))); + expect(test_resulting_type(uint16_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - uint16_t(1))); + expect(test_resulting_type(int8_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - int8_t(1))); + expect(test_resulting_type(uint8_t(1) - 1_fix)); + expect(test_resulting_type(1_fix - uint8_t(1))); + expect(test_resulting_type(1.f - 1_fix)); + expect(test_resulting_type(1_fix - 1.f)); + expect(test_resulting_type(1. - 1_fix)); + expect(test_resulting_type(1_fix - 1.)); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } diff --git a/unit_tests/tan_ut.cc b/unit_tests/tan_ut.cc new file mode 100644 index 0000000..a1f8538 --- /dev/null +++ b/unit_tests/tan_ut.cc @@ -0,0 +1,37 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +using namespace fixedmath::func; + +constexpr void + test_tan(fixed_t x, fixed_t expected, fixed_t aprox, source_location const location = source_location::current()) + { + expect_approx(tan(x), expected, aprox, location); + expect_approx(tan(-x), -expected, aprox, location); + } + +int main() + { + test_result result; + "tan"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + test_tan(phi / 2 + phi / 32, -10.155854941143394_fix, 0.0001_fix); + test_tan(phi / 3, 1.73204_fix, 0.0001_fix); + test_tan(phi / 4, 0.99997_fix, 0.0001_fix); + test_tan(phi / 5, 0.72653_fix, 0.0001_fix); + test_tan(phi / 8, 0.41419_fix, 0.0001_fix); + test_tan(phi / 16, 0.19889_fix, 0.0001_fix); + test_tan(0_fix, 0_fix, 0.0001_fix); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + } + +// 0.0001 diff --git a/unit_tests/type_convertions_ut.cc b/unit_tests/type_convertions_ut.cc new file mode 100644 index 0000000..9e641f0 --- /dev/null +++ b/unit_tests/type_convertions_ut.cc @@ -0,0 +1,128 @@ +#include +#include + +using boost::ut::operator""_test; +using namespace metatests; +using namespace fixedmath; +int main() + { + test_result result; + using F = fixedmath::fixed_internal; + + + "arithmetic_to_fixed integrals"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(arithmetic_to_fixed(0), 0_fix); + expect_eq(arithmetic_to_fixed(1), limits_::one()); + expect_eq(arithmetic_to_fixed(-1), -limits_::one()); + expect_neq(arithmetic_to_fixed(-1), limits_::one()); + expect_neq(arithmetic_to_fixed(-1), 0_fix); + expect_neq(arithmetic_to_fixed(1), 0_fix); + expect_neq(arithmetic_to_fixed(1), arithmetic_to_fixed(-1)); + expect_eq(arithmetic_to_fixed(1), arithmetic_to_fixed(1)); + + expect_eq(0_fix, fixed_t{}); + expect_eq(1_fix, limits_::one()); + expect_eq(-1_fix, -limits_::one()); + expect_eq(as_fixed(F(0x80000000LL)), 32768_fix); + expect_eq(as_fixed(F(0)), 0_fix); + expect_eq(as_fixed(F(1ll << 32)), 65536_fix); + + // + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "arithmetic_to_fixed floating point"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(arithmetic_to_fixed(0.f), 0_fix); + expect_eq(arithmetic_to_fixed(-1.f), -limits_::one()); + expect_neq(arithmetic_to_fixed(-1.f), limits_::one()); + expect_neq(arithmetic_to_fixed(-1.f), 0_fix); + expect_neq(arithmetic_to_fixed(1.f), 0_fix); + expect_neq(arithmetic_to_fixed(1.f), arithmetic_to_fixed(-1)); + expect_eq(arithmetic_to_fixed(1.f), arithmetic_to_fixed(1)); + expect_eq(arithmetic_to_fixed(0.f), 0_fix); + expect_eq(arithmetic_to_fixed(float(limits_::max_integral())), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(flimits_::max()), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(float(limits_::max_integral() + 1ll)), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(float(limits_::min_integral())), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(float(limits_::min_integral() - 1ll)), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(flimits_::lowest()), limits_::quiet_NaN()); + expect_neq(arithmetic_to_fixed(flimits_::min()), limits_::quiet_NaN()); + + expect_eq(arithmetic_to_fixed(-1.), -limits_::one()); + expect_neq(arithmetic_to_fixed(-1.), limits_::one()); + expect_neq(arithmetic_to_fixed(-1.), 0_fix); + expect_neq(arithmetic_to_fixed(1.), 0_fix); + expect_neq(arithmetic_to_fixed(1.), arithmetic_to_fixed(-1)); + expect_eq(arithmetic_to_fixed(1.), arithmetic_to_fixed(1)); + expect_eq(arithmetic_to_fixed(double(limits_::max_integral())), limits_::quiet_NaN()); + expect_neq(arithmetic_to_fixed(double(limits_::max_integral() - 1ll)), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(double(limits_::max_integral() + 1ll)), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(double(limits_::min_integral())), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(double(limits_::min_integral() - 1ll)), limits_::quiet_NaN()); + expect_neq(arithmetic_to_fixed(double(limits_::min_integral() + 1ll)), limits_::quiet_NaN()); + expect_eq(arithmetic_to_fixed(dlimits_::lowest()), limits_::quiet_NaN()); + expect_neq(arithmetic_to_fixed(dlimits_::min()), limits_::quiet_NaN()); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + + "fixed_to_arithmetic integrals"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + expect_eq(fixed_to_arithmetic(0.25_fix), 0); + expect_eq(fixed_to_arithmetic(1.25_fix), 1); + expect_eq(fixed_to_arithmetic(100.25_fix), 100); + expect_eq(fixed_to_arithmetic(100.55_fix), 100); + expect_eq(fixed_to_arithmetic(100.55_fix), 100u); + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + "fixed_to_arithmetic floating point"_test = [&result] + { + auto fn_tmpl = [] -> metatests::test_result + { + { + static constexpr auto approx{std::numeric_limits::epsilon()}; + + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.f)), 0.f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(1.f)), 1.f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.25f)), 0.25f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.5f)), 0.5f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.75f)), 0.75f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-1.f)), -1.f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.25f)), -0.25f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.5f)), -0.5f, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.75f)), -0.75f, approx); + } + { + static constexpr auto approx{std::numeric_limits::epsilon()}; + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.f)), 0., approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(1.f)), 1., approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.25f)), 0.25, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.5f)), 0.5, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(0.75f)), 0.75, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-1.f)), -1., approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.25f)), -0.25, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.5f)), -0.5, approx); + expect_approx(fixed_to_arithmetic(arithmetic_to_fixed(-0.75f)), -0.75, approx); + } + return {}; + }; + result |= run_runtime_test(fn_tmpl); + result |= run_consteval_test(fn_tmpl); + }; + }