├── .gitignore ├── docs ├── Gemfile ├── _config.yml ├── performance.md ├── accuracy.md └── index.md ├── .appveyor.yml ├── 3rdparty ├── googletest │ ├── CMakeLists.txt │ ├── include │ │ └── gtest │ │ │ ├── internal │ │ │ ├── custom │ │ │ │ ├── README.md │ │ │ │ ├── gtest.h │ │ │ │ ├── gtest-port.h │ │ │ │ └── gtest-printers.h │ │ │ ├── gtest-port-arch.h │ │ │ └── gtest-string.h │ │ │ ├── gtest_prod.h │ │ │ └── gtest-test-part.h │ └── src │ │ ├── gtest_main.cc │ │ ├── gtest-all.cc │ │ ├── gtest-test-part.cc │ │ ├── gtest-typed-test.cc │ │ └── gtest-matchers.cc └── googlebench │ ├── src │ ├── sleep.h │ ├── benchmark_main.cc │ ├── benchmark_register.h │ ├── colorprint.h │ ├── counter.h │ ├── string_util.h │ ├── arraysize.h │ ├── timers.h │ ├── benchmark_api_internal.h │ ├── statistics.h │ ├── log.h │ ├── thread_manager.h │ ├── sleep.cc │ ├── thread_timer.h │ ├── counter.cc │ ├── complexity.h │ ├── check.h │ ├── internal_macros.h │ ├── reporter.cc │ ├── commandlineflags.h │ ├── re.h │ ├── csv_reporter.cc │ ├── mutex.h │ ├── colorprint.cc │ ├── string_util.cc │ ├── statistics.cc │ ├── console_reporter.cc │ └── json_reporter.cc │ └── CMakeLists.txt ├── tests ├── constants.cpp ├── detail.cpp ├── common.hpp ├── arithmetic_int.cpp ├── nearest.cpp ├── arithmetic.cpp ├── manip.cpp ├── basic_math.cpp ├── conversion.cpp ├── customizations.cpp ├── classification.cpp └── trigonometry.cpp ├── benchmarks ├── benchmark.gnuplot ├── benchmark.py ├── arithmetic.cpp ├── trigonometry.cpp └── power.cpp ├── accuracy ├── accuracy.gnuplot └── accuracy.cpp ├── .travis.yml ├── LICENSE ├── CODE_OF_CONDUCT.md ├── README.md └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /.vscode 3 | /build 4 | /CMakeSettings.json 5 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "github-pages" 6 | gem "jekyll-relative-links" 7 | gem "jekyll-github-metadata" 8 | 9 | gem "webrick", "~> 1.8" 10 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | title: FPM 2 | description: C++ header-only fixed-point math library 3 | theme: jekyll-theme-slate 4 | site: 5 | github: 6 | - is_project_page 7 | - repository_url: https://github.com/MikeLankamp/fpm 8 | gems: 9 | - jekyll-relative-links 10 | - jekyll-github-metadata 11 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.1.{build} 2 | 3 | branches: 4 | only: 5 | - master 6 | 7 | image: 8 | - Visual Studio 2017 9 | - Visual Studio 2019 10 | 11 | configuration: 12 | - Debug 13 | - Release 14 | 15 | before_build: 16 | - mkdir build 17 | - cd build 18 | - cmake .. 19 | 20 | build: 21 | project: build/ALL_BUILD.vcxproj 22 | parallel: true 23 | verbosity: minimal 24 | 25 | test_script: 26 | - ctest -C %configuration% 27 | -------------------------------------------------------------------------------- /3rdparty/googletest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Threads REQUIRED) 2 | 3 | add_library(gtest STATIC 4 | src/gtest-all.cc 5 | ) 6 | 7 | target_include_directories(gtest 8 | PUBLIC 9 | include 10 | PRIVATE 11 | . 12 | ) 13 | 14 | target_link_libraries(gtest 15 | PRIVATE 16 | Threads::Threads 17 | ) 18 | 19 | add_library(gtest_main STATIC 20 | src/gtest_main.cc 21 | ) 22 | 23 | target_link_libraries(gtest_main 24 | PUBLIC 25 | gtest 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /tests/constants.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | using P = fpm::fixed_16_16; 4 | 5 | TEST(constants, e) 6 | { 7 | EXPECT_EQ(P(2.7182818284590452353602874713527), P::e()); 8 | } 9 | 10 | TEST(constants, pi) 11 | { 12 | EXPECT_EQ(P(3.1415926535897932384626433832795), P::pi()); 13 | } 14 | 15 | TEST(constants, half_pi) 16 | { 17 | EXPECT_EQ(P(1.5707963267948966192313216916398), P::half_pi()); 18 | } 19 | 20 | TEST(constants, two_pi) 21 | { 22 | EXPECT_EQ(P(6.283185307179586476925286766559), P::two_pi()); 23 | } 24 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/sleep.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_SLEEP_H_ 2 | #define BENCHMARK_SLEEP_H_ 3 | 4 | namespace benchmark { 5 | const int kNumMillisPerSecond = 1000; 6 | const int kNumMicrosPerMilli = 1000; 7 | const int kNumMicrosPerSecond = kNumMillisPerSecond * 1000; 8 | const int kNumNanosPerMicro = 1000; 9 | const int kNumNanosPerSecond = kNumNanosPerMicro * kNumMicrosPerSecond; 10 | 11 | void SleepForMilliseconds(int milliseconds); 12 | void SleepForSeconds(double seconds); 13 | } // end namespace benchmark 14 | 15 | #endif // BENCHMARK_SLEEP_H_ 16 | -------------------------------------------------------------------------------- /benchmarks/benchmark.gnuplot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gnuplot 2 | set terminal png size 860,350 font "Arial,8" 3 | set datafile separator "," 4 | set datafile missing "-" 5 | 6 | set style data histogram 7 | set style fill solid border linecolor black 8 | set style histogram clustered gap 2 9 | set boxwidth 1 10 | 11 | set key left top noenhanced 12 | 13 | set xtics scale 0 14 | set grid ytics 15 | set ylabel "avg. time (ns)" 16 | 17 | DATA_FILE="performance.csv" 18 | set output "performance.png" 19 | 20 | plot for [COL=2:6] DATA_FILE using COL:xtic(1) title columnheader -------------------------------------------------------------------------------- /tests/detail.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(detail, find_highest_bit) 5 | { 6 | EXPECT_EQ(0, fpm::detail::find_highest_bit(1)); 7 | EXPECT_EQ(1, fpm::detail::find_highest_bit(2)); 8 | EXPECT_EQ(12, fpm::detail::find_highest_bit(0x1000)); 9 | EXPECT_EQ(23, fpm::detail::find_highest_bit(0x00FFFFFF)); 10 | EXPECT_EQ(23, fpm::detail::find_highest_bit(0x0087BD54)); 11 | EXPECT_EQ(28, fpm::detail::find_highest_bit(0x10000000)); 12 | EXPECT_EQ(31, fpm::detail::find_highest_bit(0x80000000)); 13 | } 14 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/benchmark_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | 17 | BENCHMARK_MAIN(); 18 | -------------------------------------------------------------------------------- /accuracy/accuracy.gnuplot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gnuplot 2 | set terminal png size 430,300 font "Arial,8" 3 | set datafile separator "," 4 | set datafile missing "-" 5 | set key noenhanced 6 | set key autotitle columnhead 7 | set colors classic 8 | set format y "%g%%" 9 | 10 | SERIES=ARG1 11 | DATA_FILE=SERIES.".csv" 12 | 13 | if (ARG2 eq "trig") { 14 | # Trig functions range from -pi to pi 15 | set xtics pi 16 | set format x '%.0Pπ' 17 | set xrange [-pi:pi] 18 | } 19 | 20 | err(x,real) = (real != 0) ? abs((x - real)/real) * 100 : (x != 0) ? "-" : 0; 21 | 22 | set output "accuracy-".SERIES.".png" 23 | set title 'Δ '.SERIES 24 | 25 | plot DATA_FILE using 1:(err($6,$2)) with linespoints, \ 26 | DATA_FILE using 1:(err($5,$2)) with linespoints, \ 27 | DATA_FILE using 1:(err($7,$2)) with linespoints 28 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/benchmark_register.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_REGISTER_H 2 | #define BENCHMARK_REGISTER_H 3 | 4 | #include 5 | 6 | #include "check.h" 7 | 8 | template 9 | void AddRange(std::vector* dst, T lo, T hi, int mult) { 10 | CHECK_GE(lo, 0); 11 | CHECK_GE(hi, lo); 12 | CHECK_GE(mult, 2); 13 | 14 | // Add "lo" 15 | dst->push_back(lo); 16 | 17 | static const T kmax = std::numeric_limits::max(); 18 | 19 | // Now space out the benchmarks in multiples of "mult" 20 | for (T i = 1; i < kmax / mult; i *= mult) { 21 | if (i >= hi) break; 22 | if (i > lo) { 23 | dst->push_back(i); 24 | } 25 | } 26 | 27 | // Add "hi" (if different from "lo") 28 | if (hi != lo) { 29 | dst->push_back(hi); 30 | } 31 | } 32 | 33 | #endif // BENCHMARK_REGISTER_H 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: xenial 3 | 4 | sudo: false 5 | os: 6 | - linux 7 | 8 | before_install: 9 | - sudo apt-get install -y gnuplot 10 | 11 | matrix: 12 | include: 13 | - os: linux 14 | compiler: gcc 15 | env: CONFIG=Debug 16 | - os: linux 17 | compiler: gcc 18 | env: CONFIG=Release 19 | - os: linux 20 | compiler: clang 21 | env: CONFIG=Debug 22 | - os: linux 23 | compiler: clang 24 | env: CONFIG=Release 25 | 26 | script: 27 | - set -e 28 | - mkdir -p build && cd build 29 | - cmake -DCMAKE_BUILD_TYPE=$CONFIG .. && make -j 30 | - ctest --output-on-failure 31 | - make fpm-accuracy-images -j 32 | 33 | addons: 34 | artifacts: 35 | working_dir: build 36 | paths: 37 | - $(ls accuracy-*.png | tr "\n" ":") 38 | target_paths: 39 | - fpm 40 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/colorprint.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_COLORPRINT_H_ 2 | #define BENCHMARK_COLORPRINT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace benchmark { 9 | enum LogColor { 10 | COLOR_DEFAULT, 11 | COLOR_RED, 12 | COLOR_GREEN, 13 | COLOR_YELLOW, 14 | COLOR_BLUE, 15 | COLOR_MAGENTA, 16 | COLOR_CYAN, 17 | COLOR_WHITE 18 | }; 19 | 20 | std::string FormatString(const char* msg, va_list args); 21 | std::string FormatString(const char* msg, ...); 22 | 23 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, 24 | va_list args); 25 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...); 26 | 27 | // Returns true if stdout appears to be a terminal that supports colored 28 | // output, false otherwise. 29 | bool IsColorTerminal(); 30 | 31 | } // end namespace benchmark 32 | 33 | #endif // BENCHMARK_COLORPRINT_H_ 34 | -------------------------------------------------------------------------------- /tests/common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FPM_TESTS_COMMON_HPP 2 | #define FPM_TESTS_COMMON_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace fpm 10 | { 11 | template 12 | void PrintTo(const fpm::fixed& val, ::std::ostream* os) 13 | { 14 | auto f = os->flags(); 15 | *os << static_cast(val) 16 | << " (0x" << std::hex << std::setw(sizeof(B) * 2) << std::setfill('0') << val.raw_value() << ")"; 17 | os->flags(f); 18 | } 19 | } 20 | 21 | inline ::testing::AssertionResult HasMaximumError(double value, double reference, double max_error) 22 | { 23 | auto diff = std::abs(value - reference); 24 | if (reference < 1e-10 && diff <= max_error) 25 | return ::testing::AssertionSuccess(); 26 | if (std::abs(diff / reference) <= max_error) 27 | return ::testing::AssertionSuccess(); 28 | return ::testing::AssertionFailure() << value << " is not within " << (max_error * 100) << "% of " << reference; 29 | } 30 | 31 | #endif -------------------------------------------------------------------------------- /tests/arithmetic_int.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | TEST(arithmethic_int, addition) 4 | { 5 | using P = fpm::fixed_24_8; 6 | 7 | EXPECT_EQ(P(10.5), P(3.5) + 7); 8 | } 9 | 10 | TEST(arithmethic_int, subtraction) 11 | { 12 | using P = fpm::fixed_24_8; 13 | 14 | EXPECT_EQ(P(-3.5), P(3.5) - 7); 15 | } 16 | 17 | TEST(arithmethic_int, multiplication) 18 | { 19 | using P = fpm::fixed_24_8; 20 | 21 | EXPECT_EQ(P(-24.5), P(3.5) * -7); 22 | } 23 | 24 | TEST(arithmethic_int, division) 25 | { 26 | using P = fpm::fixed_24_8; 27 | 28 | EXPECT_EQ(P(3.5 / 7), P(3.5) / 7); 29 | EXPECT_EQ(P(-3.5 / 7), P(-3.5) / 7); 30 | EXPECT_EQ(P(3.5 / -7), P(3.5) / -7); 31 | EXPECT_EQ(P(-3.5 / -7), P(-3.5) / -7); 32 | 33 | #ifndef NDEBUG 34 | EXPECT_DEATH(P(1) / 0, ""); 35 | #endif 36 | } 37 | 38 | TEST(arithmethic_int, division_range) 39 | { 40 | using P = fpm::fixed; 41 | 42 | // These calculation will overflow and produce 43 | // wrong results without the intermediate type. 44 | EXPECT_EQ(P(32), P(256) / 8); 45 | } -------------------------------------------------------------------------------- /3rdparty/googlebench/src/counter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | 17 | namespace benchmark { 18 | 19 | // these counter-related functions are hidden to reduce API surface. 20 | namespace internal { 21 | void Finish(UserCounters *l, double time, double num_threads); 22 | void Increment(UserCounters *l, UserCounters const& r); 23 | bool SameNames(UserCounters const& l, UserCounters const& r); 24 | } // end namespace internal 25 | 26 | } //end namespace benchmark 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Mike Lankamp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /3rdparty/googlebench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (benchmark) 2 | 3 | add_library(benchmark 4 | src/benchmark.cc 5 | src/benchmark_register.cc 6 | src/colorprint.cc 7 | src/commandlineflags.cc 8 | src/complexity.cc 9 | src/console_reporter.cc 10 | src/counter.cc 11 | src/csv_reporter.cc 12 | src/json_reporter.cc 13 | src/reporter.cc 14 | src/sleep.cc 15 | src/statistics.cc 16 | src/string_util.cc 17 | src/sysinfo.cc 18 | src/timers.cc 19 | ) 20 | target_include_directories(benchmark PUBLIC include) 21 | 22 | # Ensure we have pthreads 23 | find_package(Threads REQUIRED) 24 | 25 | # Link threads. 26 | target_link_libraries(benchmark Threads::Threads) 27 | find_library(LIBRT rt) 28 | if(LIBRT) 29 | target_link_libraries(benchmark ${LIBRT}) 30 | endif() 31 | 32 | # We need extra libraries on Windows 33 | if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 34 | target_compile_definitions(benchmark PRIVATE _CRT_SECURE_NO_WARNINGS) 35 | target_link_libraries(benchmark Shlwapi) 36 | endif() 37 | 38 | # Benchmark main library 39 | add_library(benchmark_main 40 | src/benchmark_main.cc 41 | ) 42 | target_link_libraries(benchmark_main benchmark) -------------------------------------------------------------------------------- /3rdparty/googlebench/src/string_util.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_STRING_UTIL_H_ 2 | #define BENCHMARK_STRING_UTIL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "internal_macros.h" 8 | 9 | namespace benchmark { 10 | 11 | void AppendHumanReadable(int n, std::string* str); 12 | 13 | std::string HumanReadableNumber(double n, double one_k = 1024.0); 14 | 15 | std::string StrFormat(const char* format, ...); 16 | 17 | inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { 18 | return out; 19 | } 20 | 21 | template 22 | inline std::ostream& StrCatImp(std::ostream& out, First&& f, 23 | Rest&&... rest) { 24 | out << std::forward(f); 25 | return StrCatImp(out, std::forward(rest)...); 26 | } 27 | 28 | template 29 | inline std::string StrCat(Args&&... args) { 30 | std::ostringstream ss; 31 | StrCatImp(ss, std::forward(args)...); 32 | return ss.str(); 33 | } 34 | 35 | void ReplaceAll(std::string* str, const std::string& from, 36 | const std::string& to); 37 | 38 | } // end namespace benchmark 39 | 40 | #endif // BENCHMARK_STRING_UTIL_H_ 41 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/arraysize.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_ARRAYSIZE_H_ 2 | #define BENCHMARK_ARRAYSIZE_H_ 3 | 4 | #include "internal_macros.h" 5 | 6 | namespace benchmark { 7 | namespace internal { 8 | // The arraysize(arr) macro returns the # of elements in an array arr. 9 | // The expression is a compile-time constant, and therefore can be 10 | // used in defining new arrays, for example. If you use arraysize on 11 | // a pointer by mistake, you will get a compile-time error. 12 | // 13 | 14 | // This template function declaration is used in defining arraysize. 15 | // Note that the function doesn't need an implementation, as we only 16 | // use its type. 17 | template 18 | char (&ArraySizeHelper(T (&array)[N]))[N]; 19 | 20 | // That gcc wants both of these prototypes seems mysterious. VC, for 21 | // its part, can't decide which to use (another mystery). Matching of 22 | // template overloads: the final frontier. 23 | #ifndef COMPILER_MSVC 24 | template 25 | char (&ArraySizeHelper(const T (&array)[N]))[N]; 26 | #endif 27 | 28 | #define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array))) 29 | 30 | } // end namespace internal 31 | } // end namespace benchmark 32 | 33 | #endif // BENCHMARK_ARRAYSIZE_H_ 34 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/timers.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_TIMERS_H 2 | #define BENCHMARK_TIMERS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace benchmark { 8 | 9 | // Return the CPU usage of the current process 10 | double ProcessCPUUsage(); 11 | 12 | // Return the CPU usage of the children of the current process 13 | double ChildrenCPUUsage(); 14 | 15 | // Return the CPU usage of the current thread 16 | double ThreadCPUUsage(); 17 | 18 | #if defined(HAVE_STEADY_CLOCK) 19 | template 20 | struct ChooseSteadyClock { 21 | typedef std::chrono::high_resolution_clock type; 22 | }; 23 | 24 | template <> 25 | struct ChooseSteadyClock { 26 | typedef std::chrono::steady_clock type; 27 | }; 28 | #endif 29 | 30 | struct ChooseClockType { 31 | #if defined(HAVE_STEADY_CLOCK) 32 | typedef ChooseSteadyClock<>::type type; 33 | #else 34 | typedef std::chrono::high_resolution_clock type; 35 | #endif 36 | }; 37 | 38 | inline double ChronoClockNow() { 39 | typedef ChooseClockType::type ClockType; 40 | using FpSeconds = std::chrono::duration; 41 | return FpSeconds(ClockType::now().time_since_epoch()).count(); 42 | } 43 | 44 | std::string LocalDateTimeString(); 45 | 46 | } // end namespace benchmark 47 | 48 | #endif // BENCHMARK_TIMERS_H 49 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/benchmark_api_internal.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_API_INTERNAL_H 2 | #define BENCHMARK_API_INTERNAL_H 3 | 4 | #include "benchmark/benchmark.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace benchmark { 13 | namespace internal { 14 | 15 | // Information kept per benchmark we may want to run 16 | struct Benchmark::Instance { 17 | std::string name; 18 | Benchmark* benchmark; 19 | ReportMode report_mode; 20 | std::vector arg; 21 | TimeUnit time_unit; 22 | int range_multiplier; 23 | bool use_real_time; 24 | bool use_manual_time; 25 | BigO complexity; 26 | BigOFunc* complexity_lambda; 27 | UserCounters counters; 28 | const std::vector* statistics; 29 | bool last_benchmark_instance; 30 | int repetitions; 31 | double min_time; 32 | size_t iterations; 33 | int threads; // Number of concurrent threads to us 34 | }; 35 | 36 | bool FindBenchmarksInternal(const std::string& re, 37 | std::vector* benchmarks, 38 | std::ostream* Err); 39 | 40 | bool IsZero(double n); 41 | 42 | ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false); 43 | 44 | } // end namespace internal 45 | } // end namespace benchmark 46 | 47 | #endif // BENCHMARK_API_INTERNAL_H 48 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/statistics.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // Copyright 2017 Roman Lebedev. All rights reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #ifndef STATISTICS_H_ 17 | #define STATISTICS_H_ 18 | 19 | #include 20 | 21 | #include "benchmark/benchmark.h" 22 | 23 | namespace benchmark { 24 | 25 | // Return a vector containing the mean, median and standard devation information 26 | // (and any user-specified info) for the specified list of reports. If 'reports' 27 | // contains less than two non-errored runs an empty vector is returned 28 | std::vector ComputeStats( 29 | const std::vector& reports); 30 | 31 | double StatisticsMean(const std::vector& v); 32 | double StatisticsMedian(const std::vector& v); 33 | double StatisticsStdDev(const std::vector& v); 34 | 35 | } // end namespace benchmark 36 | 37 | #endif // STATISTICS_H_ 38 | -------------------------------------------------------------------------------- /docs/performance.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | # Performance 5 | 6 | The image below shows the approximate performance of: 7 | * `fpm` (the `Q16.16` type) 8 | * [libfixmath](https://github.com/PetteriAimonen/libfixmath) (`fix16`), an alternative C library (see [notes](#notes)). 9 | * [Compositional Numeric Library](https://github.com/johnmcfarlane/cnl) (`CNL`), an experimental library that is being developed in C++'s [SG14](https://github.com/WG21-SG14/SG14). 10 | * native FPU operations (`float` and `double`). 11 | 12 | The graph below plots the average number of nanoseconds a single operation takes: lower is better. The data was collected with [Google Benchmark](https://github.com/google/benchmark) on an Intel Core i7-5820K, 3.3GHz. 13 | 14 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/performance.png) 15 | 16 | The results show the following: 17 | * Compared to `libfixmath`, the performance of `fpm` is at least as good, except for `exp`, where it's considerably slower. 18 | * Compared to CNL, `fpm` only matches the performance for `sqrt`. However, CNL does not support the majority of benchmarked functions. 19 | * Compared to native single-precision floating-point operations, `fpm` is slower by up to an order of magnitude for most functions, except for the basic `add`, `sub` and several power or trigonometry functions, where it is faster. 20 | 21 | ## Notes 22 | 23 | For a fair comparison, `libfixmath` was compiled with `FIXMATH_NO_CACHE`. 24 | It should also have been compiled with `FIXMATH_NO_OVERFLOW` (since `fpm` does not detect overflow), but `libfixmath` failed to compile with that option. 25 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/log.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_LOG_H_ 2 | #define BENCHMARK_LOG_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "benchmark/benchmark.h" 8 | 9 | namespace benchmark { 10 | namespace internal { 11 | 12 | typedef std::basic_ostream&(EndLType)(std::basic_ostream&); 13 | 14 | class LogType { 15 | friend LogType& GetNullLogInstance(); 16 | friend LogType& GetErrorLogInstance(); 17 | 18 | // FIXME: Add locking to output. 19 | template 20 | friend LogType& operator<<(LogType&, Tp const&); 21 | friend LogType& operator<<(LogType&, EndLType*); 22 | 23 | private: 24 | LogType(std::ostream* out) : out_(out) {} 25 | std::ostream* out_; 26 | BENCHMARK_DISALLOW_COPY_AND_ASSIGN(LogType); 27 | }; 28 | 29 | template 30 | LogType& operator<<(LogType& log, Tp const& value) { 31 | if (log.out_) { 32 | *log.out_ << value; 33 | } 34 | return log; 35 | } 36 | 37 | inline LogType& operator<<(LogType& log, EndLType* m) { 38 | if (log.out_) { 39 | *log.out_ << m; 40 | } 41 | return log; 42 | } 43 | 44 | inline int& LogLevel() { 45 | static int log_level = 0; 46 | return log_level; 47 | } 48 | 49 | inline LogType& GetNullLogInstance() { 50 | static LogType log(nullptr); 51 | return log; 52 | } 53 | 54 | inline LogType& GetErrorLogInstance() { 55 | static LogType log(&std::clog); 56 | return log; 57 | } 58 | 59 | inline LogType& GetLogInstanceForLevel(int level) { 60 | if (level <= LogLevel()) { 61 | return GetErrorLogInstance(); 62 | } 63 | return GetNullLogInstance(); 64 | } 65 | 66 | } // end namespace internal 67 | } // end namespace benchmark 68 | 69 | #define VLOG(x) \ 70 | (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \ 71 | " ") 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/thread_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_THREAD_MANAGER_H 2 | #define BENCHMARK_THREAD_MANAGER_H 3 | 4 | #include 5 | 6 | #include "benchmark/benchmark.h" 7 | #include "mutex.h" 8 | 9 | namespace benchmark { 10 | namespace internal { 11 | 12 | class ThreadManager { 13 | public: 14 | ThreadManager(int num_threads) 15 | : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} 16 | 17 | Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { 18 | return benchmark_mutex_; 19 | } 20 | 21 | bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { 22 | return start_stop_barrier_.wait(); 23 | } 24 | 25 | void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { 26 | start_stop_barrier_.removeThread(); 27 | if (--alive_threads_ == 0) { 28 | MutexLock lock(end_cond_mutex_); 29 | end_condition_.notify_all(); 30 | } 31 | } 32 | 33 | void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { 34 | MutexLock lock(end_cond_mutex_); 35 | end_condition_.wait(lock.native_handle(), 36 | [this]() { return alive_threads_ == 0; }); 37 | } 38 | 39 | public: 40 | struct Result { 41 | int64_t iterations = 0; 42 | double real_time_used = 0; 43 | double cpu_time_used = 0; 44 | double manual_time_used = 0; 45 | int64_t bytes_processed = 0; 46 | int64_t items_processed = 0; 47 | int64_t complexity_n = 0; 48 | std::string report_label_; 49 | std::string error_message_; 50 | bool has_error_ = false; 51 | UserCounters counters; 52 | }; 53 | GUARDED_BY(GetBenchmarkMutex()) Result results; 54 | 55 | private: 56 | mutable Mutex benchmark_mutex_; 57 | std::atomic alive_threads_; 58 | Barrier start_stop_barrier_; 59 | Mutex end_cond_mutex_; 60 | Condition end_condition_; 61 | }; 62 | 63 | } // namespace internal 64 | } // namespace benchmark 65 | 66 | #endif // BENCHMARK_THREAD_MANAGER_H 67 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/sleep.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "sleep.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "internal_macros.h" 22 | 23 | #ifdef BENCHMARK_OS_WINDOWS 24 | #include 25 | #endif 26 | 27 | namespace benchmark { 28 | #ifdef BENCHMARK_OS_WINDOWS 29 | // Window's Sleep takes milliseconds argument. 30 | void SleepForMilliseconds(int milliseconds) { Sleep(milliseconds); } 31 | void SleepForSeconds(double seconds) { 32 | SleepForMilliseconds(static_cast(kNumMillisPerSecond * seconds)); 33 | } 34 | #else // BENCHMARK_OS_WINDOWS 35 | void SleepForMicroseconds(int microseconds) { 36 | struct timespec sleep_time; 37 | sleep_time.tv_sec = microseconds / kNumMicrosPerSecond; 38 | sleep_time.tv_nsec = (microseconds % kNumMicrosPerSecond) * kNumNanosPerMicro; 39 | while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) 40 | ; // Ignore signals and wait for the full interval to elapse. 41 | } 42 | 43 | void SleepForMilliseconds(int milliseconds) { 44 | SleepForMicroseconds(milliseconds * kNumMicrosPerMilli); 45 | } 46 | 47 | void SleepForSeconds(double seconds) { 48 | SleepForMicroseconds(static_cast(seconds * kNumMicrosPerSecond)); 49 | } 50 | #endif // BENCHMARK_OS_WINDOWS 51 | } // end namespace benchmark 52 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/custom/README.md: -------------------------------------------------------------------------------- 1 | # Customization Points 2 | 3 | The custom directory is an injection point for custom user configurations. 4 | 5 | ## Header `gtest.h` 6 | 7 | ### The following macros can be defined: 8 | 9 | * `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of 10 | `OsStackTraceGetterInterface`. 11 | * `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See 12 | `testing::TempDir` for semantics and signature. 13 | 14 | ## Header `gtest-port.h` 15 | 16 | The following macros can be defined: 17 | 18 | ### Flag related macros: 19 | 20 | * `GTEST_FLAG(flag_name)` 21 | * `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its 22 | own flagfile flag parsing. 23 | * `GTEST_DECLARE_bool_(name)` 24 | * `GTEST_DECLARE_int32_(name)` 25 | * `GTEST_DECLARE_string_(name)` 26 | * `GTEST_DEFINE_bool_(name, default_val, doc)` 27 | * `GTEST_DEFINE_int32_(name, default_val, doc)` 28 | * `GTEST_DEFINE_string_(name, default_val, doc)` 29 | 30 | ### Logging: 31 | 32 | * `GTEST_LOG_(severity)` 33 | * `GTEST_CHECK_(condition)` 34 | * Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too. 35 | 36 | ### Threading: 37 | 38 | * `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided. 39 | * `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal` 40 | are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)` 41 | and `GTEST_DEFINE_STATIC_MUTEX_(mutex)` 42 | * `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)` 43 | * `GTEST_LOCK_EXCLUDED_(locks)` 44 | 45 | ### Underlying library support features 46 | 47 | * `GTEST_HAS_CXXABI_H_` 48 | 49 | ### Exporting API symbols: 50 | 51 | * `GTEST_API_` - Specifier for exported symbols. 52 | 53 | ## Header `gtest-printers.h` 54 | 55 | * See documentation at `gtest/gtest-printers.h` for details on how to define a 56 | custom printer. 57 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/custom/gtest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. See README for details 31 | // 32 | // ** Custom implementation starts here ** 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 35 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 36 | 37 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 38 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/thread_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_THREAD_TIMER_H 2 | #define BENCHMARK_THREAD_TIMER_H 3 | 4 | #include "check.h" 5 | #include "timers.h" 6 | 7 | namespace benchmark { 8 | namespace internal { 9 | 10 | class ThreadTimer { 11 | public: 12 | ThreadTimer() = default; 13 | 14 | // Called by each thread 15 | void StartTimer() { 16 | running_ = true; 17 | start_real_time_ = ChronoClockNow(); 18 | start_cpu_time_ = ThreadCPUUsage(); 19 | } 20 | 21 | // Called by each thread 22 | void StopTimer() { 23 | CHECK(running_); 24 | running_ = false; 25 | real_time_used_ += ChronoClockNow() - start_real_time_; 26 | // Floating point error can result in the subtraction producing a negative 27 | // time. Guard against that. 28 | cpu_time_used_ += std::max(ThreadCPUUsage() - start_cpu_time_, 0); 29 | } 30 | 31 | // Called by each thread 32 | void SetIterationTime(double seconds) { manual_time_used_ += seconds; } 33 | 34 | bool running() const { return running_; } 35 | 36 | // REQUIRES: timer is not running 37 | double real_time_used() { 38 | CHECK(!running_); 39 | return real_time_used_; 40 | } 41 | 42 | // REQUIRES: timer is not running 43 | double cpu_time_used() { 44 | CHECK(!running_); 45 | return cpu_time_used_; 46 | } 47 | 48 | // REQUIRES: timer is not running 49 | double manual_time_used() { 50 | CHECK(!running_); 51 | return manual_time_used_; 52 | } 53 | 54 | private: 55 | bool running_ = false; // Is the timer running 56 | double start_real_time_ = 0; // If running_ 57 | double start_cpu_time_ = 0; // If running_ 58 | 59 | // Accumulated time so far (does not contain current slice if running_) 60 | double real_time_used_ = 0; 61 | double cpu_time_used_ = 0; 62 | // Manually set iteration time. User sets this with SetIterationTime(seconds). 63 | double manual_time_used_ = 0; 64 | }; 65 | 66 | } // namespace internal 67 | } // namespace benchmark 68 | 69 | #endif // BENCHMARK_THREAD_TIMER_H 70 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/custom/gtest-port.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. See README for details 31 | // 32 | // ** Custom implementation starts here ** 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 35 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 36 | 37 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 38 | -------------------------------------------------------------------------------- /tests/nearest.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(nearest, round) 5 | { 6 | using P = fpm::fixed_24_8; 7 | 8 | EXPECT_EQ(P( 2), round(P( 2.3))); 9 | EXPECT_EQ(P( 3), round(P( 2.5))); 10 | EXPECT_EQ(P( 3), round(P( 2.7))); 11 | EXPECT_EQ(P(-2), round(P(-2.3))); 12 | EXPECT_EQ(P(-3), round(P(-2.5))); 13 | EXPECT_EQ(P(-3), round(P(-2.7))); 14 | EXPECT_EQ(P( 0), round(P( 0))); 15 | } 16 | 17 | TEST(nearest, ceil) 18 | { 19 | using P = fpm::fixed_24_8; 20 | 21 | EXPECT_EQ(P( 1), ceil(P( 1))); 22 | EXPECT_EQ(P(-1), ceil(P(-1))); 23 | 24 | EXPECT_EQ(P( 3), ceil(P( 2.4))); 25 | EXPECT_EQ(P(-2), ceil(P(-2.4))); 26 | EXPECT_EQ(P( 0), ceil(P( 0))); 27 | } 28 | 29 | TEST(nearest, floor) 30 | { 31 | using P = fpm::fixed_24_8; 32 | 33 | EXPECT_EQ(P( 1), floor(P( 1))); 34 | EXPECT_EQ(P(-1), floor(P(-1))); 35 | 36 | EXPECT_EQ(P( 2), floor(P( 2.7))); 37 | EXPECT_EQ(P(-3), floor(P(-2.7))); 38 | EXPECT_EQ(P( 0), floor(P( 0))); 39 | } 40 | 41 | TEST(nearest, trunc) 42 | { 43 | using P = fpm::fixed_24_8; 44 | 45 | EXPECT_EQ(P( 1), trunc(P( 1))); 46 | EXPECT_EQ(P(-1), trunc(P(-1))); 47 | 48 | EXPECT_EQ(P( 2), trunc(P( 2.7))); 49 | EXPECT_EQ(P(-2), trunc(P(-2.9))); 50 | EXPECT_EQ(P( 0), trunc(P( 0))); 51 | } 52 | 53 | TEST(nearest, nearbyint) 54 | { 55 | using P = fpm::fixed_24_8; 56 | 57 | EXPECT_EQ(P( 2), nearbyint(P( 2.3))); 58 | EXPECT_EQ(P( 2), nearbyint(P( 2.5))); 59 | EXPECT_EQ(P( 4), nearbyint(P( 3.5))); 60 | EXPECT_EQ(P(-2), nearbyint(P(-2.3))); 61 | EXPECT_EQ(P(-2), nearbyint(P(-2.5))); 62 | EXPECT_EQ(P(-4), nearbyint(P(-3.5))); 63 | EXPECT_EQ(P( 0), nearbyint(P( 0))); 64 | } 65 | 66 | TEST(nearest, rint) 67 | { 68 | using P = fpm::fixed_24_8; 69 | 70 | EXPECT_EQ(P( 2), rint(P( 2.3))); 71 | EXPECT_EQ(P( 2), rint(P( 2.5))); 72 | EXPECT_EQ(P( 4), rint(P( 3.5))); 73 | EXPECT_EQ(P(-2), rint(P(-2.3))); 74 | EXPECT_EQ(P(-2), rint(P(-2.5))); 75 | EXPECT_EQ(P(-4), rint(P(-3.5))); 76 | EXPECT_EQ(P( 0), rint(P( 0))); 77 | } 78 | 79 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/counter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "counter.h" 16 | 17 | namespace benchmark { 18 | namespace internal { 19 | 20 | double Finish(Counter const& c, double cpu_time, double num_threads) { 21 | double v = c.value; 22 | if (c.flags & Counter::kIsRate) { 23 | v /= cpu_time; 24 | } 25 | if (c.flags & Counter::kAvgThreads) { 26 | v /= num_threads; 27 | } 28 | return v; 29 | } 30 | 31 | void Finish(UserCounters *l, double cpu_time, double num_threads) { 32 | for (auto &c : *l) { 33 | c.second.value = Finish(c.second, cpu_time, num_threads); 34 | } 35 | } 36 | 37 | void Increment(UserCounters *l, UserCounters const& r) { 38 | // add counters present in both or just in *l 39 | for (auto &c : *l) { 40 | auto it = r.find(c.first); 41 | if (it != r.end()) { 42 | c.second.value = c.second + it->second; 43 | } 44 | } 45 | // add counters present in r, but not in *l 46 | for (auto const &tc : r) { 47 | auto it = l->find(tc.first); 48 | if (it == l->end()) { 49 | (*l)[tc.first] = tc.second; 50 | } 51 | } 52 | } 53 | 54 | bool SameNames(UserCounters const& l, UserCounters const& r) { 55 | if (&l == &r) return true; 56 | if (l.size() != r.size()) { 57 | return false; 58 | } 59 | for (auto const& c : l) { 60 | if (r.find(c.first) == r.end()) { 61 | return false; 62 | } 63 | } 64 | return true; 65 | } 66 | 67 | } // end namespace internal 68 | } // end namespace benchmark 69 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/complexity.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Source project : https://github.com/ismaelJimenez/cpp.leastsq 16 | // Adapted to be used with google benchmark 17 | 18 | #ifndef COMPLEXITY_H_ 19 | #define COMPLEXITY_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include "benchmark/benchmark.h" 25 | 26 | namespace benchmark { 27 | 28 | // Return a vector containing the bigO and RMS information for the specified 29 | // list of reports. If 'reports.size() < 2' an empty vector is returned. 30 | std::vector ComputeBigO( 31 | const std::vector& reports); 32 | 33 | // This data structure will contain the result returned by MinimalLeastSq 34 | // - coef : Estimated coeficient for the high-order term as 35 | // interpolated from data. 36 | // - rms : Normalized Root Mean Squared Error. 37 | // - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability 38 | // form has been provided to MinimalLeastSq this will return 39 | // the same value. In case BigO::oAuto has been selected, this 40 | // parameter will return the best fitting curve detected. 41 | 42 | struct LeastSq { 43 | LeastSq() : coef(0.0), rms(0.0), complexity(oNone) {} 44 | 45 | double coef; 46 | double rms; 47 | BigO complexity; 48 | }; 49 | 50 | // Function to return an string for the calculated complexity 51 | std::string GetBigOString(BigO complexity); 52 | 53 | } // end namespace benchmark 54 | 55 | #endif // COMPLEXITY_H_ 56 | -------------------------------------------------------------------------------- /tests/arithmetic.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | TEST(arithmethic, negation) 4 | { 5 | using P = fpm::fixed_24_8; 6 | 7 | EXPECT_EQ(P(-13.125), -P( 13.125)); 8 | EXPECT_EQ(P( 13.125), -P(-13.125)); 9 | } 10 | 11 | TEST(arithmethic, addition) 12 | { 13 | using P = fpm::fixed_24_8; 14 | 15 | EXPECT_EQ(P(10.75), P(3.5) + P(7.25)); 16 | } 17 | 18 | TEST(arithmethic, subtraction) 19 | { 20 | using P = fpm::fixed_24_8; 21 | 22 | EXPECT_EQ(P(-3.75), P(3.5) - P(7.25)); 23 | } 24 | 25 | TEST(arithmethic, multiplication) 26 | { 27 | using P = fpm::fixed_24_8; 28 | 29 | EXPECT_EQ(P(-25.375), P(3.5) * P(-7.25)); 30 | } 31 | 32 | TEST(arithmethic, division) 33 | { 34 | using P = fpm::fixed_24_8; 35 | 36 | EXPECT_EQ(P(3.5 / 7.25), P(3.5) / P(7.25)); 37 | EXPECT_EQ(P(-3.5 / 7.25), P(-3.5) / P(7.25)); 38 | EXPECT_EQ(P(3.5 / -7.25), P(3.5) / P(-7.25)); 39 | EXPECT_EQ(P(-3.5 / -7.25), P(-3.5) / P(-7.25)); 40 | 41 | #ifndef NDEBUG 42 | EXPECT_DEATH(P(1) / P(0), ""); 43 | #endif 44 | } 45 | 46 | TEST(arithmethic, division_range) 47 | { 48 | using P = fpm::fixed; 49 | 50 | // These calculation will overflow and produce 51 | // wrong results without the intermediate type. 52 | EXPECT_EQ(P(32), P(256) / P(8)); 53 | } 54 | 55 | TEST(arithmetic, multiplication_rounding) 56 | { 57 | // Using 1 bit of fractional precision to test rounding 58 | using Q_round = fpm::fixed; 59 | using Q = fpm::fixed; 60 | 61 | EXPECT_EQ(Q_round(1.0), Q_round(1.5) * Q_round(0.5)); 62 | EXPECT_EQ(Q_round(0.5), Q_round(0.5) * Q_round(0.5)); 63 | EXPECT_EQ(Q(0.5), Q(1.5) * Q(0.5)); 64 | EXPECT_EQ(Q(0.0), Q(0.5) * Q(0.5)); 65 | } 66 | 67 | TEST(arithmetic, division_rounding) 68 | { 69 | // Using 1 bit of fractional precision to test rounding 70 | using Q_round = fpm::fixed; 71 | using Q = fpm::fixed; 72 | 73 | EXPECT_EQ(Q_round(2.5), Q_round(3.5) / Q_round(1.5)); 74 | EXPECT_EQ(Q_round(0.5), Q_round(1.0) / Q_round(1.5)); 75 | EXPECT_EQ(Q(2.0), Q(3.5) / Q(1.5)); 76 | EXPECT_EQ(Q(0.5), Q(1.0) / Q(1.5)); 77 | } 78 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/custom/gtest-printers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // This file provides an injection point for custom printers in a local 31 | // installation of gTest. 32 | // It will be included from gtest-printers.h and the overrides in this file 33 | // will be visible to everyone. 34 | // 35 | // Injection point for custom user configurations. See README for details 36 | // 37 | // ** Custom implementation starts here ** 38 | 39 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 40 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 41 | 42 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 43 | -------------------------------------------------------------------------------- /3rdparty/googletest/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include "gtest/gtest.h" 32 | 33 | #ifdef ARDUINO 34 | void setup() { 35 | // Since Arduino doesn't have a command line, fake out the argc/argv arguments 36 | int argc = 1; 37 | const auto arg0 = "PlatformIO"; 38 | char* argv0 = const_cast(arg0); 39 | char** argv = &argv0; 40 | 41 | testing::InitGoogleTest(&argc, argv); 42 | } 43 | 44 | void loop() { RUN_ALL_TESTS(); } 45 | 46 | #else 47 | 48 | GTEST_API_ int main(int argc, char **argv) { 49 | printf("Running main() from %s\n", __FILE__); 50 | testing::InitGoogleTest(&argc, argv); 51 | return RUN_ALL_TESTS(); 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /benchmarks/benchmark.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ 3 | Translates google benchmark JSON output to a format expected by gnuplot. 4 | """ 5 | import argparse 6 | import json 7 | import os 8 | import re 9 | import sys 10 | 11 | def sanitize_type(type): 12 | if type == "Fix16": 13 | return "fix16" 14 | if type == "CnlFixed16": 15 | return "cnl::fixed_16_16" 16 | if type.startswith("fpm::fixed"): 17 | return type 18 | return type 19 | 20 | def parse_name(name): 21 | # Expected format: 22 | # test-class "<" float-type ">" "/" operation 23 | result = re.match(r'^(.*)<(.*)>/([a-z0-9_]*)$', name) 24 | if result: 25 | return sanitize_type(result.group(2)), result.group(3) 26 | 27 | 28 | def main(): 29 | parser = argparse.ArgumentParser() 30 | parser.add_argument('INFILE', help="the JSON file to process") 31 | parser.add_argument('OUTFILE', help="the file to write GnuPlot data to") 32 | args = parser.parse_args() 33 | 34 | operation_data = {} 35 | operations = [] 36 | types = [] 37 | with open(args.INFILE) as infile: 38 | data = json.load(infile) 39 | for entry in data['benchmarks']: 40 | if entry['time_unit'] != 'ns': 41 | raise ValueError("time_unit not in nanoseconds") 42 | 43 | result = parse_name(entry['name']) 44 | if result: 45 | float_type, operation_name = result 46 | if not operation_name in operations: 47 | operations.append(operation_name) 48 | if not float_type in types: 49 | types.append(float_type) 50 | 51 | d = operation_data.get(operation_name, {}) 52 | d[float_type] = entry['cpu_time'] 53 | operation_data[operation_name] = d 54 | 55 | with open(args.OUTFILE, 'w') as outfile: 56 | outfile.write("operation,{}\n".format(",".join(types))) 57 | for operation_name in operations: 58 | d = operation_data[operation_name] 59 | data = [] 60 | for type in types: 61 | data.append(str(d.get(type, "-"))) 62 | outfile.write("{},{}\n".format(operation_name, ",".join(data))) 63 | 64 | return 0 65 | 66 | if __name__== "__main__": 67 | sys.exit(main()) -------------------------------------------------------------------------------- /3rdparty/googletest/src/gtest-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // Google C++ Testing and Mocking Framework (Google Test) 32 | // 33 | // Sometimes it's desirable to build Google Test by compiling a single file. 34 | // This file serves this purpose. 35 | 36 | // This line ensures that gtest.h can be compiled on its own, even 37 | // when it's fused. 38 | #include "gtest/gtest.h" 39 | 40 | // The following lines pull in the real gtest *.cc files. 41 | #include "src/gtest.cc" 42 | #include "src/gtest-death-test.cc" 43 | #include "src/gtest-filepath.cc" 44 | #include "src/gtest-matchers.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /tests/manip.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(manipulation, copysign) 5 | { 6 | using P = fpm::fixed_24_8; 7 | 8 | EXPECT_EQ(P(-13.125), copysign(P(-13.125), P(-7.25))); 9 | EXPECT_EQ(P(-13.125), copysign(P( 13.125), P(-7.25))); 10 | EXPECT_EQ(P( 13.125), copysign(P(-13.125), P( 7.25))); 11 | EXPECT_EQ(P( 13.125), copysign(P( 13.125), P( 7.25))); 12 | 13 | EXPECT_EQ(P(-13), copysign(P(-13), P(-7))); 14 | EXPECT_EQ(P(-13), copysign(P( 13), P(-7))); 15 | EXPECT_EQ(P( 13), copysign(P(-13), P( 7))); 16 | EXPECT_EQ(P( 13), copysign(P( 13), P( 7))); 17 | } 18 | 19 | TEST(manipulation, nextafter) 20 | { 21 | using P = fpm::fixed_16_16; 22 | 23 | EXPECT_EQ(P(2.5), nextafter(P(2.5), P(2.5))); 24 | EXPECT_EQ(P(-2.5), nextafter(P(-2.5), P(-2.5))); 25 | 26 | EXPECT_EQ(P::from_raw_value(1), nextafter(P(0), std::numeric_limits

::max())); 27 | EXPECT_EQ(P::from_raw_value(0x10001), nextafter(P(1), P(10))); 28 | EXPECT_EQ(P::from_raw_value(-0x0ffff), nextafter(P(-1), P(10))); 29 | 30 | EXPECT_EQ(P::from_raw_value(-1), nextafter(P(0), std::numeric_limits

::min())); 31 | EXPECT_EQ(P::from_raw_value(0x0ffff), nextafter(P(1), P(-10))); 32 | EXPECT_EQ(P::from_raw_value(-0x10001), nextafter(P(-1), P(-10))); 33 | } 34 | 35 | TEST(manipulation, nexttoward) 36 | { 37 | using P = fpm::fixed_16_16; 38 | 39 | EXPECT_EQ(P(2.5), nexttoward(P(2.5), P(2.5))); 40 | EXPECT_EQ(P(-2.5), nexttoward(P(-2.5), P(-2.5))); 41 | 42 | EXPECT_EQ(P::from_raw_value(1), nexttoward(P(0), std::numeric_limits

::max())); 43 | EXPECT_EQ(P::from_raw_value(0x10001), nexttoward(P(1), P(10))); 44 | EXPECT_EQ(P::from_raw_value(-0x0ffff), nexttoward(P(-1), P(10))); 45 | 46 | EXPECT_EQ(P::from_raw_value(-1), nexttoward(P(0), std::numeric_limits

::min())); 47 | EXPECT_EQ(P::from_raw_value(0x0ffff), nexttoward(P(1), P(-10))); 48 | EXPECT_EQ(P::from_raw_value(-0x10001), nexttoward(P(-1), P(-10))); 49 | } 50 | 51 | TEST(manipulation, modf) 52 | { 53 | using P = fpm::fixed_16_16; 54 | 55 | P integral; 56 | EXPECT_EQ(P(0), modf(P(0), &integral)); 57 | EXPECT_EQ(P(0), integral); 58 | 59 | EXPECT_EQ(P(0.25), modf(P(12.25), &integral)); 60 | EXPECT_EQ(P(12), integral); 61 | 62 | EXPECT_EQ(P(-0.25), modf(P(-12.25), &integral)); 63 | EXPECT_EQ(P(-12), integral); 64 | } 65 | -------------------------------------------------------------------------------- /docs/accuracy.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | # Accuracy 5 | 6 | The images below compare the accuracy (versus the real result) of: 7 | * `fpm` (the `Q8.24` and `Q16.16` types) 8 | * [libfixmath](https://github.com/PetteriAimonen/libfixmath) (`fix16`), an alternative C library. 9 | 10 | The accuracy of `Q24.8` was not shown since it was wildly inaccurate. It's advised to use at least 16 bits of fraction for reasonable accuracy for trigonometric operations (as in these tests). 11 | 12 | Plotted is the relative error (`(result - real) / real`). Closer to 0 is better. 13 | 14 | ## Trigonometry functions 15 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-cos.png) 16 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-sin.png) 17 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-tan.png) 18 | 19 | The results show that `fpm`'s trigonometric functions have better worst-case accuracy than `libfixmath`, although the latter has better overall accuracy except for certain domains where it has very large error. 20 | 21 | ## Inverse trigonometry functions 22 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-acos.png) 23 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-asin.png) 24 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-atan.png) 25 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-atan2.png) 26 | 27 | The results show that `fpm`'s inverse trigonometric functions have better accuracy then `libfixmath`. 28 | 29 | ## Power functions 30 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-sqrt.png) 31 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-cbrt.png) 32 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-exp.png) 33 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-log.png) 34 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-exp2.png) 35 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-log2.png) 36 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-pow.png) 37 | ![](http://mikelankampgithub.s3-website-eu-west-1.amazonaws.com/fpm/accuracy-log10.png) 38 | 39 | The results show that for those power functions that `libfixmath` supports, `fpm` is less accurate. However, the relative error of all power functions is well below 0.1% in the tested cases, and even less some functions. 40 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/check.h: -------------------------------------------------------------------------------- 1 | #ifndef CHECK_H_ 2 | #define CHECK_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "internal_macros.h" 9 | #include "log.h" 10 | 11 | namespace benchmark { 12 | namespace internal { 13 | 14 | typedef void(AbortHandlerT)(); 15 | 16 | inline AbortHandlerT*& GetAbortHandler() { 17 | static AbortHandlerT* handler = &std::abort; 18 | return handler; 19 | } 20 | 21 | BENCHMARK_NORETURN inline void CallAbortHandler() { 22 | GetAbortHandler()(); 23 | std::abort(); // fallback to enforce noreturn 24 | } 25 | 26 | // CheckHandler is the class constructed by failing CHECK macros. CheckHandler 27 | // will log information about the failures and abort when it is destructed. 28 | class CheckHandler { 29 | public: 30 | CheckHandler(const char* check, const char* file, const char* func, int line) 31 | : log_(GetErrorLogInstance()) { 32 | log_ << file << ":" << line << ": " << func << ": Check `" << check 33 | << "' failed. "; 34 | } 35 | 36 | LogType& GetLog() { return log_; } 37 | 38 | BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) { 39 | log_ << std::endl; 40 | CallAbortHandler(); 41 | } 42 | 43 | CheckHandler& operator=(const CheckHandler&) = delete; 44 | CheckHandler(const CheckHandler&) = delete; 45 | CheckHandler() = delete; 46 | 47 | private: 48 | LogType& log_; 49 | }; 50 | 51 | } // end namespace internal 52 | } // end namespace benchmark 53 | 54 | // The CHECK macro returns a std::ostream object that can have extra information 55 | // written to it. 56 | #ifndef NDEBUG 57 | #define CHECK(b) \ 58 | (b ? ::benchmark::internal::GetNullLogInstance() \ 59 | : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \ 60 | .GetLog()) 61 | #else 62 | #define CHECK(b) ::benchmark::internal::GetNullLogInstance() 63 | #endif 64 | 65 | #define CHECK_EQ(a, b) CHECK((a) == (b)) 66 | #define CHECK_NE(a, b) CHECK((a) != (b)) 67 | #define CHECK_GE(a, b) CHECK((a) >= (b)) 68 | #define CHECK_LE(a, b) CHECK((a) <= (b)) 69 | #define CHECK_GT(a, b) CHECK((a) > (b)) 70 | #define CHECK_LT(a, b) CHECK((a) < (b)) 71 | 72 | #define CHECK_FLOAT_EQ(a, b, eps) CHECK(std::fabs((a) - (b)) < (eps)) 73 | #define CHECK_FLOAT_NE(a, b, eps) CHECK(std::fabs((a) - (b)) >= (eps)) 74 | #define CHECK_FLOAT_GE(a, b, eps) CHECK((a) - (b) > -(eps)) 75 | #define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps)) 76 | #define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) > (eps)) 77 | #define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) > (eps)) 78 | 79 | #endif // CHECK_H_ 80 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/internal_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_INTERNAL_MACROS_H_ 2 | #define BENCHMARK_INTERNAL_MACROS_H_ 3 | 4 | #include "benchmark/benchmark.h" 5 | 6 | #ifndef __has_feature 7 | #define __has_feature(x) 0 8 | #endif 9 | #ifndef __has_builtin 10 | #define __has_builtin(x) 0 11 | #endif 12 | 13 | #if defined(__clang__) 14 | #if !defined(COMPILER_CLANG) 15 | #define COMPILER_CLANG 16 | #endif 17 | #elif defined(_MSC_VER) 18 | #if !defined(COMPILER_MSVC) 19 | #define COMPILER_MSVC 20 | #endif 21 | #elif defined(__GNUC__) 22 | #if !defined(COMPILER_GCC) 23 | #define COMPILER_GCC 24 | #endif 25 | #endif 26 | 27 | #if __has_feature(cxx_attributes) 28 | #define BENCHMARK_NORETURN [[noreturn]] 29 | #elif defined(__GNUC__) 30 | #define BENCHMARK_NORETURN __attribute__((noreturn)) 31 | #elif defined(COMPILER_MSVC) 32 | #define BENCHMARK_NORETURN __declspec(noreturn) 33 | #else 34 | #define BENCHMARK_NORETURN 35 | #endif 36 | 37 | #if defined(__CYGWIN__) 38 | #define BENCHMARK_OS_CYGWIN 1 39 | #elif defined(_WIN32) 40 | #define BENCHMARK_OS_WINDOWS 1 41 | #elif defined(__APPLE__) 42 | #define BENCHMARK_OS_APPLE 1 43 | #include "TargetConditionals.h" 44 | #if defined(TARGET_OS_MAC) 45 | #define BENCHMARK_OS_MACOSX 1 46 | #if defined(TARGET_OS_IPHONE) 47 | #define BENCHMARK_OS_IOS 1 48 | #endif 49 | #endif 50 | #elif defined(__FreeBSD__) 51 | #define BENCHMARK_OS_FREEBSD 1 52 | #elif defined(__NetBSD__) 53 | #define BENCHMARK_OS_NETBSD 1 54 | #elif defined(__OpenBSD__) 55 | #define BENCHMARK_OS_OPENBSD 1 56 | #elif defined(__linux__) 57 | #define BENCHMARK_OS_LINUX 1 58 | #elif defined(__native_client__) 59 | #define BENCHMARK_OS_NACL 1 60 | #elif defined(__EMSCRIPTEN__) 61 | #define BENCHMARK_OS_EMSCRIPTEN 1 62 | #elif defined(__rtems__) 63 | #define BENCHMARK_OS_RTEMS 1 64 | #elif defined(__Fuchsia__) 65 | #define BENCHMARK_OS_FUCHSIA 1 66 | #elif defined (__SVR4) && defined (__sun) 67 | #define BENCHMARK_OS_SOLARIS 1 68 | #endif 69 | 70 | #if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ 71 | && !defined(__EXCEPTIONS) 72 | #define BENCHMARK_HAS_NO_EXCEPTIONS 73 | #endif 74 | 75 | #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) 76 | #define BENCHMARK_MAYBE_UNUSED __attribute__((unused)) 77 | #else 78 | #define BENCHMARK_MAYBE_UNUSED 79 | #endif 80 | 81 | #if defined(COMPILER_GCC) || __has_builtin(__builtin_unreachable) 82 | #define BENCHMARK_UNREACHABLE() __builtin_unreachable() 83 | #elif defined(COMPILER_MSVC) 84 | #define BENCHMARK_UNREACHABLE() __assume(false) 85 | #else 86 | #define BENCHMARK_UNREACHABLE() ((void)0) 87 | #endif 88 | 89 | #endif // BENCHMARK_INTERNAL_MACROS_H_ 90 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Attribution 56 | 57 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org). -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fpm 2 | A C++ header-only fixed-point math library. "fpm" stands for "fixed-point math". 3 | 4 | It is designed to serve as a drop-in replacement for floating-point types and aims to provide as much of the standard library's functionality as possible with exclusively integers. `fpm` requires C++11 or higher. 5 | 6 | [![Build Status](https://travis-ci.org/MikeLankamp/fpm.svg?branch=master)](https://travis-ci.org/MikeLankamp/fpm) 7 | [![Build status](https://ci.appveyor.com/api/projects/status/0velpwqk38spu412?svg=true)](https://ci.appveyor.com/project/MikeLankamp/fpm) 8 | 9 | `fpm` is designed to guard against accidental conversion to and from floats and supports many of the standard C++ maths functions, including trigonometry, power and logarithmic functions, with performance and accuracy generally comparable to alternative libraries. 10 | 11 | ## Why use fixed-point math? 12 | There are several reasons why you can not or choose not to use floating-point math, but still want a similar type: 13 | * Your target platform lacks an FPU, does not support floating-point operations or its floating-point operations are 14 | considerably slower than fixed-point integer operations. 15 | * You require deterministic calculations. 16 | 17 | If any of these reasons apply for you, and your problem domain has a clearly outlined range and required resolution, 18 | then fixed-point numbers might be a solution for you. 19 | 20 | ## Quick Start 21 | To use `fpm`, include its header `` and use the `fpm::fixed_16_16`, `fpm::fixed_24_8` or `fpm::fixed_8_24` 22 | types as if they were native floating-pointer types: 23 | ```c++ 24 | #include // For fpm::fixed_16_16 25 | #include // For fpm::cos 26 | #include // For fpm::operator<< 27 | #include // For std::cin, std::cout 28 | 29 | int main() { 30 | std::cout << "Please input a number: "; 31 | fpm::fixed_16_16 x; 32 | std::cin >> x; 33 | std::cout << "The cosine of " << x << " radians is: " << cos(x) << std::endl; 34 | return 0; 35 | } 36 | ``` 37 | 38 | To use the fixed-point equivalents of the `` functions such as `sqrt`, `sin` and `log`, include the header ``. 39 | To stream fixed-point values to or from streams, include the header ``. 40 | 41 | ## Documentation 42 | Please refer to the [documentation](docs/index.md) for detailed information how to use `fpm`, or skip straight to the [performance](docs/performance.md) or [accuracy](docs/accuracy.md) results. 43 | 44 | ## Contributions 45 | This library is a work-in-progress. We welcome any contributions that improve the functional coverage or the performance or accuracy of the mathematical functions. 46 | 47 | ## License 48 | See the [LICENSE](LICENSE) file 49 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // Google C++ Testing and Mocking Framework definitions useful in production code. 32 | // GOOGLETEST_CM0003 DO NOT DELETE 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void PrivateMethod(); 44 | // FRIEND_TEST(MyClassTest, PrivateMethodWorks); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, PrivateMethodWorks) { 52 | // // Can call MyClass::PrivateMethod() here. 53 | // } 54 | // 55 | // Note: The test class must be in the same namespace as the class being tested. 56 | // For example, putting MyClassTest in an anonymous namespace will not work. 57 | 58 | #define FRIEND_TEST(test_case_name, test_name)\ 59 | friend class test_case_name##_##test_name##_Test 60 | 61 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 62 | -------------------------------------------------------------------------------- /benchmarks/arithmetic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #define BENCHMARK_TEMPLATE1_CAPTURE(func, test_case_name, a, ...) \ 8 | BENCHMARK_PRIVATE_DECLARE(func) = \ 9 | (::benchmark::internal::RegisterBenchmarkInternal( \ 10 | new ::benchmark::internal::FunctionBenchmark( \ 11 | #func "<" #a ">/" #test_case_name, \ 12 | [](::benchmark::State& st) { func(st, __VA_ARGS__); }))) 13 | 14 | // Constants for our arithmetic operands. 15 | // Stored as volatile to force the compiler to read them and 16 | // not optimize the entire expression into a constant. 17 | static volatile int16_t s_x = 1543; 18 | static volatile int16_t s_y = 2552; 19 | 20 | template 21 | static void arithmetic(benchmark::State& state, TValue (*func)(TValue, TValue)) 22 | { 23 | for (auto _ : state) 24 | { 25 | TValue x{ static_cast(static_cast(s_x)) }, y{ static_cast(static_cast(s_y)) }; 26 | benchmark::DoNotOptimize(func(x, y)); 27 | } 28 | } 29 | 30 | #define FUNC(TYPE, OP) \ 31 | [](TYPE x, TYPE y) -> TYPE { return x OP y; } 32 | 33 | using CnlFixed16 = cnl::fixed_point; 34 | 35 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, add, float, FUNC(float, +)); 36 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, sub, float, FUNC(float, -)); 37 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, mul, float, FUNC(float, *)); 38 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, div, float, FUNC(float, /)); 39 | 40 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, add, double, FUNC(double, +)); 41 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, sub, double, FUNC(double, -)); 42 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, mul, double, FUNC(double, *)); 43 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, div, double, FUNC(double, /)); 44 | 45 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, add, fpm::fixed_16_16, FUNC(fpm::fixed_16_16, +)); 46 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, sub, fpm::fixed_16_16, FUNC(fpm::fixed_16_16, -)); 47 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, mul, fpm::fixed_16_16, FUNC(fpm::fixed_16_16, *)); 48 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, div, fpm::fixed_16_16, FUNC(fpm::fixed_16_16, /)); 49 | 50 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, add, Fix16, FUNC(Fix16, +)); 51 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, sub, Fix16, FUNC(Fix16, -)); 52 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, mul, Fix16, FUNC(Fix16, *)); 53 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, div, Fix16, FUNC(Fix16, /)); 54 | 55 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, add, CnlFixed16, FUNC(CnlFixed16, +)); 56 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, sub, CnlFixed16, FUNC(CnlFixed16, -)); 57 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, mul, CnlFixed16, FUNC(CnlFixed16, *)); 58 | BENCHMARK_TEMPLATE1_CAPTURE(arithmetic, div, CnlFixed16, FUNC(CnlFixed16, /)); 59 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "timers.h" 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "check.h" 25 | 26 | namespace benchmark { 27 | 28 | BenchmarkReporter::BenchmarkReporter() 29 | : output_stream_(&std::cout), error_stream_(&std::cerr) {} 30 | 31 | BenchmarkReporter::~BenchmarkReporter() {} 32 | 33 | void BenchmarkReporter::PrintBasicContext(std::ostream *out, 34 | Context const &context) { 35 | CHECK(out) << "cannot be null"; 36 | auto &Out = *out; 37 | 38 | Out << LocalDateTimeString() << "\n"; 39 | 40 | if (context.executable_name) 41 | Out << "Running " << context.executable_name << "\n"; 42 | 43 | const CPUInfo &info = context.cpu_info; 44 | Out << "Run on (" << info.num_cpus << " X " 45 | << (info.cycles_per_second / 1000000.0) << " MHz CPU " 46 | << ((info.num_cpus > 1) ? "s" : "") << ")\n"; 47 | if (info.caches.size() != 0) { 48 | Out << "CPU Caches:\n"; 49 | for (auto &CInfo : info.caches) { 50 | Out << " L" << CInfo.level << " " << CInfo.type << " " 51 | << (CInfo.size / 1000) << "K"; 52 | if (CInfo.num_sharing != 0) 53 | Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")"; 54 | Out << "\n"; 55 | } 56 | } 57 | 58 | if (info.scaling_enabled) { 59 | Out << "***WARNING*** CPU scaling is enabled, the benchmark " 60 | "real time measurements may be noisy and will incur extra " 61 | "overhead.\n"; 62 | } 63 | 64 | #ifndef NDEBUG 65 | Out << "***WARNING*** Library was built as DEBUG. Timings may be " 66 | "affected.\n"; 67 | #endif 68 | } 69 | 70 | // No initializer because it's already initialized to NULL. 71 | const char* BenchmarkReporter::Context::executable_name; 72 | 73 | BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {} 74 | 75 | double BenchmarkReporter::Run::GetAdjustedRealTime() const { 76 | double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit); 77 | if (iterations != 0) new_time /= static_cast(iterations); 78 | return new_time; 79 | } 80 | 81 | double BenchmarkReporter::Run::GetAdjustedCPUTime() const { 82 | double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit); 83 | if (iterations != 0) new_time /= static_cast(iterations); 84 | return new_time; 85 | } 86 | 87 | } // end namespace benchmark 88 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/commandlineflags.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_COMMANDLINEFLAGS_H_ 2 | #define BENCHMARK_COMMANDLINEFLAGS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Macro for referencing flags. 8 | #define FLAG(name) FLAGS_##name 9 | 10 | // Macros for declaring flags. 11 | #define DECLARE_bool(name) extern bool FLAG(name) 12 | #define DECLARE_int32(name) extern int32_t FLAG(name) 13 | #define DECLARE_int64(name) extern int64_t FLAG(name) 14 | #define DECLARE_double(name) extern double FLAG(name) 15 | #define DECLARE_string(name) extern std::string FLAG(name) 16 | 17 | // Macros for defining flags. 18 | #define DEFINE_bool(name, default_val, doc) bool FLAG(name) = (default_val) 19 | #define DEFINE_int32(name, default_val, doc) int32_t FLAG(name) = (default_val) 20 | #define DEFINE_int64(name, default_val, doc) int64_t FLAG(name) = (default_val) 21 | #define DEFINE_double(name, default_val, doc) double FLAG(name) = (default_val) 22 | #define DEFINE_string(name, default_val, doc) \ 23 | std::string FLAG(name) = (default_val) 24 | 25 | namespace benchmark { 26 | // Parses 'str' for a 32-bit signed integer. If successful, writes the result 27 | // to *value and returns true; otherwise leaves *value unchanged and returns 28 | // false. 29 | bool ParseInt32(const std::string& src_text, const char* str, int32_t* value); 30 | 31 | // Parses a bool/Int32/string from the environment variable 32 | // corresponding to the given Google Test flag. 33 | bool BoolFromEnv(const char* flag, bool default_val); 34 | int32_t Int32FromEnv(const char* flag, int32_t default_val); 35 | double DoubleFromEnv(const char* flag, double default_val); 36 | const char* StringFromEnv(const char* flag, const char* default_val); 37 | 38 | // Parses a string for a bool flag, in the form of either 39 | // "--flag=value" or "--flag". 40 | // 41 | // In the former case, the value is taken as true if it passes IsTruthyValue(). 42 | // 43 | // In the latter case, the value is taken as true. 44 | // 45 | // On success, stores the value of the flag in *value, and returns 46 | // true. On failure, returns false without changing *value. 47 | bool ParseBoolFlag(const char* str, const char* flag, bool* value); 48 | 49 | // Parses a string for an Int32 flag, in the form of 50 | // "--flag=value". 51 | // 52 | // On success, stores the value of the flag in *value, and returns 53 | // true. On failure, returns false without changing *value. 54 | bool ParseInt32Flag(const char* str, const char* flag, int32_t* value); 55 | 56 | // Parses a string for a Double flag, in the form of 57 | // "--flag=value". 58 | // 59 | // On success, stores the value of the flag in *value, and returns 60 | // true. On failure, returns false without changing *value. 61 | bool ParseDoubleFlag(const char* str, const char* flag, double* value); 62 | 63 | // Parses a string for a string flag, in the form of 64 | // "--flag=value". 65 | // 66 | // On success, stores the value of the flag in *value, and returns 67 | // true. On failure, returns false without changing *value. 68 | bool ParseStringFlag(const char* str, const char* flag, std::string* value); 69 | 70 | // Returns true if the string matches the flag. 71 | bool IsFlag(const char* str, const char* flag); 72 | 73 | // Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or 74 | // some non-alphanumeric character. As a special case, also returns true if 75 | // value is the empty string. 76 | bool IsTruthyFlagValue(const std::string& value); 77 | } // end namespace benchmark 78 | 79 | #endif // BENCHMARK_COMMANDLINEFLAGS_H_ 80 | -------------------------------------------------------------------------------- /benchmarks/trigonometry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BENCHMARK_TEMPLATE1_CAPTURE(func, test_case_name, a, ...) \ 7 | BENCHMARK_PRIVATE_DECLARE(func) = \ 8 | (::benchmark::internal::RegisterBenchmarkInternal( \ 9 | new ::benchmark::internal::FunctionBenchmark( \ 10 | #func "<" #a ">/" #test_case_name, \ 11 | [](::benchmark::State& st) { func(st, __VA_ARGS__); }))) 12 | 13 | template 14 | static Fix16 fix16_func1(Fix16 f) 15 | { 16 | return (f.*func)(); 17 | } 18 | 19 | template 20 | static Fix16 fix16_func2(Fix16 f, Fix16 y) 21 | { 22 | return (f.*func)(y); 23 | } 24 | 25 | // Constant for our trigonometry function argument. 26 | // Stored as volatile to force the compiler to read them and 27 | // not optimize the entire expression into a constant. 28 | static volatile int16_t s_x = 174; 29 | 30 | template 31 | static void trigonometry(benchmark::State& state, TValue (*func)(TValue)) 32 | { 33 | for (auto _ : state) 34 | { 35 | TValue x{ static_cast(s_x / 256.0) }; 36 | benchmark::DoNotOptimize(func(x)); 37 | } 38 | } 39 | 40 | template 41 | static TValue func2_proxy(TValue value) 42 | { 43 | // Add a 'random' offset for the second argument 44 | return func(value, value + 2); 45 | } 46 | 47 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, sin, float, &std::sin); 48 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, cos, float, &std::cos); 49 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, tan, float, &std::tan); 50 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, asin, float, &std::asin); 51 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, acos, float, &std::acos); 52 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan, float, &std::atan); 53 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan2, float, &func2_proxy); 54 | 55 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, sin, double, &std::sin); 56 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, cos, double, &std::cos); 57 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, tan, double, &std::tan); 58 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, asin, double, &std::asin); 59 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, acos, double, &std::acos); 60 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan, double, &std::atan); 61 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan2, double, &func2_proxy); 62 | 63 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, sin, fpm::fixed_16_16, &fpm::sin); 64 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, cos, fpm::fixed_16_16, &fpm::cos); 65 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, tan, fpm::fixed_16_16, &fpm::tan); 66 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, asin, fpm::fixed_16_16, &fpm::asin); 67 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, acos, fpm::fixed_16_16, &fpm::acos); 68 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan, fpm::fixed_16_16, &fpm::atan); 69 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan2, fpm::fixed_16_16, &func2_proxy); 70 | 71 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, sin, Fix16, fix16_func1<&Fix16::sin>); 72 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, cos, Fix16, fix16_func1<&Fix16::cos>); 73 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, tan, Fix16, fix16_func1<&Fix16::tan>); 74 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, asin, Fix16, fix16_func1<&Fix16::asin>); 75 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, acos, Fix16, fix16_func1<&Fix16::acos>); 76 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan, Fix16, fix16_func1<&Fix16::atan>); 77 | BENCHMARK_TEMPLATE1_CAPTURE(trigonometry, atan2, Fix16, &func2_proxy>); 78 | 79 | -------------------------------------------------------------------------------- /benchmarks/power.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define BENCHMARK_TEMPLATE1_CAPTURE(func, test_case_name, a, ...) \ 8 | BENCHMARK_PRIVATE_DECLARE(func) = \ 9 | (::benchmark::internal::RegisterBenchmarkInternal( \ 10 | new ::benchmark::internal::FunctionBenchmark( \ 11 | #func "<" #a ">/" #test_case_name, \ 12 | [](::benchmark::State& st) { func(st, __VA_ARGS__); }))) 13 | 14 | template 15 | static Fix16 fix16_func(Fix16 f) 16 | { 17 | return (*func)(f); 18 | } 19 | 20 | // Constants for our power function arguments. 21 | // Stored as volatile to force the compiler to read them and 22 | // not optimize the entire expression into a constant. 23 | static volatile int16_t s_x = 2734; 24 | static volatile int16_t s_y = 174; 25 | 26 | template 27 | static void power1(benchmark::State& state, TValue (*func)(TValue)) 28 | { 29 | for (auto _ : state) 30 | { 31 | TValue x{ static_cast(s_x / 256.0) }; 32 | benchmark::DoNotOptimize(func(x)); 33 | } 34 | } 35 | 36 | template 37 | static void power1(benchmark::State& state, TValue (*func)(const TValue&)) 38 | { 39 | for (auto _ : state) 40 | { 41 | TValue x{ static_cast(s_x / 256.0) }; 42 | benchmark::DoNotOptimize(func(x)); 43 | } 44 | } 45 | 46 | template 47 | static void power2(benchmark::State& state, TValue (*func)(TValue, TValue)) 48 | { 49 | for (auto _ : state) 50 | { 51 | TValue x{ static_cast(s_x / 256.0) }; 52 | TValue y{ static_cast(s_y / 256.0) }; 53 | benchmark::DoNotOptimize(func(x, y)); 54 | } 55 | } 56 | 57 | using CnlFixed16 = cnl::fixed_point; 58 | 59 | BENCHMARK_TEMPLATE1_CAPTURE(power1, sqrt, float, &std::sqrt); 60 | BENCHMARK_TEMPLATE1_CAPTURE(power1, sqrt, double, &std::sqrt); 61 | BENCHMARK_TEMPLATE1_CAPTURE(power1, sqrt, fpm::fixed_16_16, &fpm::sqrt); 62 | BENCHMARK_TEMPLATE1_CAPTURE(power1, sqrt, Fix16, fix16_func<&fix16_sqrt>); 63 | BENCHMARK_TEMPLATE1_CAPTURE(power1, sqrt, CnlFixed16, &cnl::sqrt); 64 | 65 | BENCHMARK_TEMPLATE1_CAPTURE(power1, cbrt, float, &std::cbrt); 66 | BENCHMARK_TEMPLATE1_CAPTURE(power1, cbrt, double, &std::cbrt); 67 | BENCHMARK_TEMPLATE1_CAPTURE(power1, cbrt, fpm::fixed_16_16, &fpm::cbrt); 68 | 69 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log, float, &std::log); 70 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log, double, &std::log); 71 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log, fpm::fixed_16_16, &fpm::log); 72 | 73 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log2, float, &std::log2); 74 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log2, double, &std::log2); 75 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log2, fpm::fixed_16_16, &fpm::log2); 76 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log2, Fix16, fix16_func<&fix16_log2>); 77 | 78 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log10, float, &std::log10); 79 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log10, double, &std::log10); 80 | BENCHMARK_TEMPLATE1_CAPTURE(power1, log10, fpm::fixed_16_16, &fpm::log10); 81 | 82 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp, float, &std::exp); 83 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp, double, &std::exp); 84 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp, fpm::fixed_16_16, &fpm::exp); 85 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp, Fix16, fix16_func<&fix16_exp>); 86 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp, CnlFixed16, &cnl::exp); 87 | 88 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp2, float, &std::exp2); 89 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp2, double, &std::exp2); 90 | BENCHMARK_TEMPLATE1_CAPTURE(power1, exp2, fpm::fixed_16_16, &fpm::exp2); 91 | 92 | BENCHMARK_TEMPLATE1_CAPTURE(power2, pow, float, &std::pow); 93 | BENCHMARK_TEMPLATE1_CAPTURE(power2, pow, double, &std::pow); 94 | BENCHMARK_TEMPLATE1_CAPTURE(power2, pow, fpm::fixed_16_16, &fpm::pow); 95 | -------------------------------------------------------------------------------- /tests/basic_math.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(basic_math, abs) 5 | { 6 | using P = fpm::fixed_24_8; 7 | 8 | EXPECT_EQ(P(13.125), abs(P(-13.125))); 9 | EXPECT_EQ(P(13.125), abs(P(13.125))); 10 | EXPECT_EQ(P(1), abs(P(-1))); 11 | EXPECT_EQ(P(1), abs(P(1))); 12 | } 13 | 14 | TEST(basic_math, fmod) 15 | { 16 | using P = fpm::fixed_24_8; 17 | 18 | EXPECT_EQ(P( 1.5), fmod(P( 9.5), P( 2))); 19 | EXPECT_EQ(P(-1.5), fmod(P(-9.5), P( 2))); 20 | EXPECT_EQ(P( 1.5), fmod(P( 9.5), P(-2))); 21 | EXPECT_EQ(P(-1.5), fmod(P(-9.5), P(-2))); 22 | } 23 | 24 | TEST(basic_math, remainder) 25 | { 26 | using P = fpm::fixed_24_8; 27 | 28 | EXPECT_EQ(P(-0.5), remainder(P( 9.5), P( 2))); 29 | EXPECT_EQ(P( 0.5), remainder(P(-9.5), P( 2))); 30 | EXPECT_EQ(P(-0.5), remainder(P( 9.5), P(-2))); 31 | EXPECT_EQ(P( 0.5), remainder(P(-9.5), P(-2))); 32 | 33 | EXPECT_EQ(P( 1), remainder(P( 9), P( 2))); 34 | EXPECT_EQ(P(-1), remainder(P(-9), P( 2))); 35 | EXPECT_EQ(P( 1), remainder(P( 9), P(-2))); 36 | EXPECT_EQ(P(-1), remainder(P(-9), P(-2))); 37 | 38 | EXPECT_EQ(P(-1), remainder(P( 11), P( 2))); 39 | EXPECT_EQ(P( 1), remainder(P(-11), P( 2))); 40 | EXPECT_EQ(P(-1), remainder(P( 11), P(-2))); 41 | EXPECT_EQ(P( 1), remainder(P(-11), P(-2))); 42 | 43 | EXPECT_EQ(P(-0.9), remainder(P( 5.1), P( 3))); 44 | EXPECT_EQ(P( 0.9), remainder(P(-5.1), P( 3))); 45 | EXPECT_EQ(P(-0.9), remainder(P( 5.1), P(-3))); 46 | EXPECT_EQ(P( 0.9), remainder(P(-5.1), P(-3))); 47 | 48 | EXPECT_EQ(P(0), remainder(P(0), P(1))); 49 | } 50 | 51 | TEST(basic_math, remquo) 52 | { 53 | // remquo must return at least 3 bits of quotient 54 | constexpr int QUO_MIN_SIZE = 1 << 3; 55 | 56 | using P = fpm::fixed_16_16; 57 | 58 | int quo = 999999; 59 | EXPECT_EQ(P( 1.5), remquo(P( 9.5), P( 2), &quo)); 60 | EXPECT_EQ( 4, quo % QUO_MIN_SIZE); 61 | EXPECT_EQ(P(-1.5), remquo(P(-9.5), P( 2), &quo)); 62 | EXPECT_EQ(-4, quo % QUO_MIN_SIZE); 63 | EXPECT_EQ(P( 1.5), remquo(P( 9.5), P(-2), &quo)); 64 | EXPECT_EQ(-4, quo % QUO_MIN_SIZE); 65 | EXPECT_EQ(P(-1.5), remquo(P(-9.5), P(-2), &quo)); 66 | EXPECT_EQ( 4, quo % QUO_MIN_SIZE); 67 | 68 | EXPECT_EQ(P( 1), remquo(P( 9), P( 2), &quo)); 69 | EXPECT_EQ( 4, quo % QUO_MIN_SIZE); 70 | EXPECT_EQ(P(-1), remquo(P(-9), P( 2), &quo)); 71 | EXPECT_EQ(-4, quo % QUO_MIN_SIZE); 72 | EXPECT_EQ(P( 1), remquo(P( 9), P(-2), &quo)); 73 | EXPECT_EQ(-4, quo % QUO_MIN_SIZE); 74 | EXPECT_EQ(P(-1), remquo(P(-9), P(-2), &quo)); 75 | EXPECT_EQ( 4, quo % QUO_MIN_SIZE); 76 | 77 | EXPECT_EQ(P( 1), remquo(P( 11), P( 2), &quo)); 78 | EXPECT_EQ( 5, quo % QUO_MIN_SIZE); 79 | EXPECT_EQ(P(-1), remquo(P(-11), P( 2), &quo)); 80 | EXPECT_EQ(-5, quo % QUO_MIN_SIZE); 81 | EXPECT_EQ(P( 1), remquo(P( 11), P(-2), &quo)); 82 | EXPECT_EQ(-5, quo % QUO_MIN_SIZE); 83 | EXPECT_EQ(P(-1), remquo(P(-11), P(-2), &quo)); 84 | EXPECT_EQ( 5, quo % QUO_MIN_SIZE); 85 | 86 | EXPECT_EQ(P( 2.1), remquo(P( 5.1), P( 3), &quo)); 87 | EXPECT_EQ( 1, quo % QUO_MIN_SIZE); 88 | EXPECT_EQ(P(-2.1), remquo(P(-5.1), P( 3), &quo)); 89 | EXPECT_EQ(-1, quo % QUO_MIN_SIZE); 90 | EXPECT_EQ(P( 2.1), remquo(P( 5.1), P(-3), &quo)); 91 | EXPECT_EQ(-1, quo % QUO_MIN_SIZE); 92 | EXPECT_EQ(P(-2.1), remquo(P(-5.1), P(-3), &quo)); 93 | EXPECT_EQ( 1, quo % QUO_MIN_SIZE); 94 | 95 | EXPECT_EQ(P( 3.375), remquo(P( 97.125), P( 3.75), &quo)); 96 | EXPECT_EQ( 1, quo % QUO_MIN_SIZE); 97 | EXPECT_EQ(P(-3.375), remquo(P(-97.125), P( 3.75), &quo)); 98 | EXPECT_EQ(-1, quo % QUO_MIN_SIZE); 99 | EXPECT_EQ(P( 3.375), remquo(P( 97.125), P(-3.75), &quo)); 100 | EXPECT_EQ(-1, quo % QUO_MIN_SIZE); 101 | EXPECT_EQ(P(-3.375), remquo(P(-97.125), P(-3.75), &quo)); 102 | EXPECT_EQ( 1, quo % QUO_MIN_SIZE); 103 | 104 | EXPECT_EQ(P(0), remquo(P(0), P(1), &quo)); 105 | EXPECT_EQ(0, quo % QUO_MIN_SIZE); 106 | } 107 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/gtest-port-arch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This header file defines the GTEST_OS_* macro. 33 | // It is separate from gtest-port.h so that custom/gtest-port.h can include it. 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 36 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 37 | 38 | // Determines the platform on which Google Test is compiled. 39 | #ifdef __CYGWIN__ 40 | # define GTEST_OS_CYGWIN 1 41 | # elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__) 42 | # define GTEST_OS_WINDOWS_MINGW 1 43 | # define GTEST_OS_WINDOWS 1 44 | #elif defined _WIN32 45 | # define GTEST_OS_WINDOWS 1 46 | # ifdef _WIN32_WCE 47 | # define GTEST_OS_WINDOWS_MOBILE 1 48 | # elif defined(WINAPI_FAMILY) 49 | # include 50 | # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 51 | # define GTEST_OS_WINDOWS_DESKTOP 1 52 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 53 | # define GTEST_OS_WINDOWS_PHONE 1 54 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 55 | # define GTEST_OS_WINDOWS_RT 1 56 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE) 57 | # define GTEST_OS_WINDOWS_PHONE 1 58 | # define GTEST_OS_WINDOWS_TV_TITLE 1 59 | # else 60 | // WINAPI_FAMILY defined but no known partition matched. 61 | // Default to desktop. 62 | # define GTEST_OS_WINDOWS_DESKTOP 1 63 | # endif 64 | # else 65 | # define GTEST_OS_WINDOWS_DESKTOP 1 66 | # endif // _WIN32_WCE 67 | #elif defined __OS2__ 68 | # define GTEST_OS_OS2 1 69 | #elif defined __APPLE__ 70 | # define GTEST_OS_MAC 1 71 | # if TARGET_OS_IPHONE 72 | # define GTEST_OS_IOS 1 73 | # endif 74 | #elif defined __FreeBSD__ 75 | # define GTEST_OS_FREEBSD 1 76 | #elif defined __Fuchsia__ 77 | # define GTEST_OS_FUCHSIA 1 78 | #elif defined __linux__ 79 | # define GTEST_OS_LINUX 1 80 | # if defined __ANDROID__ 81 | # define GTEST_OS_LINUX_ANDROID 1 82 | # endif 83 | #elif defined __MVS__ 84 | # define GTEST_OS_ZOS 1 85 | #elif defined(__sun) && defined(__SVR4) 86 | # define GTEST_OS_SOLARIS 1 87 | #elif defined(_AIX) 88 | # define GTEST_OS_AIX 1 89 | #elif defined(__hpux) 90 | # define GTEST_OS_HPUX 1 91 | #elif defined __native_client__ 92 | # define GTEST_OS_NACL 1 93 | #elif defined __NetBSD__ 94 | # define GTEST_OS_NETBSD 1 95 | #elif defined __OpenBSD__ 96 | # define GTEST_OS_OPENBSD 1 97 | #elif defined __QNX__ 98 | # define GTEST_OS_QNX 1 99 | #endif // __CYGWIN__ 100 | 101 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 102 | -------------------------------------------------------------------------------- /3rdparty/googletest/src/gtest-test-part.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // The Google C++ Testing and Mocking Framework (Google Test) 32 | 33 | #include "gtest/gtest-test-part.h" 34 | #include "src/gtest-internal-inl.h" 35 | 36 | namespace testing { 37 | 38 | using internal::GetUnitTestImpl; 39 | 40 | // Gets the summary of the failure message by omitting the stack trace 41 | // in it. 42 | std::string TestPartResult::ExtractSummary(const char* message) { 43 | const char* const stack_trace = strstr(message, internal::kStackTraceMarker); 44 | return stack_trace == nullptr ? message : std::string(message, stack_trace); 45 | } 46 | 47 | // Prints a TestPartResult object. 48 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { 49 | return os << result.file_name() << ":" << result.line_number() << ": " 50 | << (result.type() == TestPartResult::kSuccess 51 | ? "Success" 52 | : result.type() == TestPartResult::kSkip 53 | ? "Skipped" 54 | : result.type() == TestPartResult::kFatalFailure 55 | ? "Fatal failure" 56 | : "Non-fatal failure") 57 | << ":\n" 58 | << result.message() << std::endl; 59 | } 60 | 61 | // Appends a TestPartResult to the array. 62 | void TestPartResultArray::Append(const TestPartResult& result) { 63 | array_.push_back(result); 64 | } 65 | 66 | // Returns the TestPartResult at the given index (0-based). 67 | const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { 68 | if (index < 0 || index >= size()) { 69 | printf("\nInvalid index (%d) into TestPartResultArray.\n", index); 70 | internal::posix::Abort(); 71 | } 72 | 73 | return array_[index]; 74 | } 75 | 76 | // Returns the number of TestPartResult objects in the array. 77 | int TestPartResultArray::size() const { 78 | return static_cast(array_.size()); 79 | } 80 | 81 | namespace internal { 82 | 83 | HasNewFatalFailureHelper::HasNewFatalFailureHelper() 84 | : has_new_fatal_failure_(false), 85 | original_reporter_(GetUnitTestImpl()-> 86 | GetTestPartResultReporterForCurrentThread()) { 87 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); 88 | } 89 | 90 | HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { 91 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( 92 | original_reporter_); 93 | } 94 | 95 | void HasNewFatalFailureHelper::ReportTestPartResult( 96 | const TestPartResult& result) { 97 | if (result.fatally_failed()) 98 | has_new_fatal_failure_ = true; 99 | original_reporter_->ReportTestPartResult(result); 100 | } 101 | 102 | } // namespace internal 103 | 104 | } // namespace testing 105 | -------------------------------------------------------------------------------- /3rdparty/googletest/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | #include "gtest/gtest-typed-test.h" 32 | 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | static std::vector SplitIntoTestNames(const char* src) { 49 | std::vector name_vec; 50 | src = SkipSpaces(src); 51 | for (; src != nullptr; src = SkipComma(src)) { 52 | name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); 53 | } 54 | return name_vec; 55 | } 56 | 57 | // Verifies that registered_tests match the test names in 58 | // registered_tests_; returns registered_tests if successful, or 59 | // aborts the program otherwise. 60 | const char* TypedTestSuitePState::VerifyRegisteredTestNames( 61 | const char* file, int line, const char* registered_tests) { 62 | typedef RegisteredTestsMap::const_iterator RegisteredTestIter; 63 | registered_ = true; 64 | 65 | std::vector name_vec = SplitIntoTestNames(registered_tests); 66 | 67 | Message errors; 68 | 69 | std::set tests; 70 | for (std::vector::const_iterator name_it = name_vec.begin(); 71 | name_it != name_vec.end(); ++name_it) { 72 | const std::string& name = *name_it; 73 | if (tests.count(name) != 0) { 74 | errors << "Test " << name << " is listed more than once.\n"; 75 | continue; 76 | } 77 | 78 | bool found = false; 79 | for (RegisteredTestIter it = registered_tests_.begin(); 80 | it != registered_tests_.end(); 81 | ++it) { 82 | if (name == it->first) { 83 | found = true; 84 | break; 85 | } 86 | } 87 | 88 | if (found) { 89 | tests.insert(name); 90 | } else { 91 | errors << "No test named " << name 92 | << " can be found in this test suite.\n"; 93 | } 94 | } 95 | 96 | for (RegisteredTestIter it = registered_tests_.begin(); 97 | it != registered_tests_.end(); 98 | ++it) { 99 | if (tests.count(it->first) == 0) { 100 | errors << "You forgot to list test " << it->first << ".\n"; 101 | } 102 | } 103 | 104 | const std::string& errors_str = errors.GetString(); 105 | if (errors_str != "") { 106 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 107 | errors_str.c_str()); 108 | fflush(stderr); 109 | posix::Abort(); 110 | } 111 | 112 | return registered_tests; 113 | } 114 | 115 | #endif // GTEST_HAS_TYPED_TEST_P 116 | 117 | } // namespace internal 118 | } // namespace testing 119 | -------------------------------------------------------------------------------- /tests/conversion.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | using P = fpm::fixed_16_16; 5 | using Q = fpm::fixed_24_8; 6 | 7 | TEST(conversion, construction) 8 | { 9 | P x; 10 | } 11 | 12 | TEST(conversion, copy) 13 | { 14 | const P x(12); 15 | 16 | // Copy ctor 17 | P y(x); 18 | EXPECT_EQ(P(12), y); 19 | 20 | // Copy assignment 21 | P z = x; 22 | EXPECT_EQ(P(12), y); 23 | } 24 | 25 | TEST(conversion, move) 26 | { 27 | const P x(12); 28 | 29 | // Move ctor 30 | P y(std::move(x)); 31 | EXPECT_EQ(P(12), y); 32 | 33 | // Move assignment 34 | P z = std::move(x); 35 | EXPECT_EQ(P(12), y); 36 | } 37 | 38 | TEST(conversion, floats) 39 | { 40 | EXPECT_EQ(1.125, static_cast(P{1.125f})); 41 | EXPECT_EQ(1.125, static_cast(P{1.125})); 42 | } 43 | 44 | TEST(conversion, float_rounding) 45 | { 46 | // Small number of fraction bits to test rounding 47 | using Q = fpm::fixed; 48 | 49 | EXPECT_EQ(1.25, static_cast(Q{1.125})); 50 | EXPECT_EQ(1.5, static_cast(Q{1.375})); 51 | EXPECT_EQ(-1.25, static_cast(Q{-1.125})); 52 | EXPECT_EQ(-1.5, static_cast(Q{-1.375})); 53 | } 54 | 55 | TEST(conversion, float_no_rounding) 56 | { 57 | // Small number of fraction bits to test no rounding 58 | using Q = fpm::fixed; 59 | 60 | EXPECT_EQ(1.0, static_cast(Q{1.125})); 61 | EXPECT_EQ(1.25, static_cast(Q{1.375})); 62 | EXPECT_EQ(1.25, static_cast(Q{1.499})); 63 | EXPECT_EQ(-1.0, static_cast(Q{-1.125})); 64 | EXPECT_EQ(-1.0, static_cast(Q{-1.249})); 65 | EXPECT_EQ(-1.25, static_cast(Q{-1.375})); 66 | } 67 | 68 | TEST(conversion, ints) 69 | { 70 | EXPECT_EQ(-125, static_cast(P{-125})); 71 | EXPECT_EQ(-125l, static_cast(P{-125l})); 72 | EXPECT_EQ(-125ll, static_cast(P{-125ll})); 73 | 74 | EXPECT_EQ(125u, static_cast(P{125u})); 75 | EXPECT_EQ(125lu, static_cast(P{125lu})); 76 | EXPECT_EQ(125llu, static_cast(P{125llu})); 77 | } 78 | 79 | TEST(conversion, fixed_point) 80 | { 81 | EXPECT_EQ(P(-1), P::from_fixed_point<0>(-1)); 82 | EXPECT_EQ(P(1), P::from_fixed_point<0>(1)); 83 | 84 | EXPECT_EQ(P(-1.125), P::from_fixed_point<4>(-18)); 85 | EXPECT_EQ(P(1.125), P::from_fixed_point<4>(18)); 86 | 87 | // This should round up to 1 88 | EXPECT_EQ(P(-1), P::from_fixed_point<20>(-1048575)); 89 | EXPECT_EQ(P(1), P::from_fixed_point<20>(1048575)); 90 | } 91 | 92 | TEST(conversion, fixed_point_no_rounding) 93 | { 94 | using P = fpm::fixed; 95 | constexpr P epsilon = std::numeric_limits

::epsilon(); 96 | 97 | EXPECT_EQ(P(-1), P::from_fixed_point<0>(-1)); 98 | EXPECT_EQ(P(1), P::from_fixed_point<0>(1)); 99 | 100 | EXPECT_EQ(P(-1.125), P::from_fixed_point<4>(-18)); 101 | EXPECT_EQ(P(1.125), P::from_fixed_point<4>(18)); 102 | 103 | // This should NOT round up to 1: there will be a truncation error equal to epsilon 104 | EXPECT_EQ(P(-1 + epsilon), P::from_fixed_point<20>(-1048575)); 105 | EXPECT_EQ(P(1 - epsilon), P::from_fixed_point<20>(1048575)); 106 | } 107 | 108 | TEST(conversion, fixed_to_fixed) 109 | { 110 | EXPECT_EQ(Q(1), Q(P(1))); 111 | EXPECT_EQ(Q(1), Q(P(1))); 112 | 113 | // Conversion to fewer fraction bits should round 114 | EXPECT_EQ(Q::from_raw_value(0x13), Q(P::from_raw_value(0x12ff))); 115 | EXPECT_EQ(Q::from_raw_value(0x12), Q(P::from_raw_value(0x127f))); 116 | EXPECT_EQ(Q::from_raw_value(-0x13), Q(P::from_raw_value(-0x12ff))); 117 | EXPECT_EQ(Q::from_raw_value(-0x12), Q(P::from_raw_value(-0x127f))); 118 | 119 | // Conversion to more fraction bits should zero-extend 120 | EXPECT_EQ(P::from_raw_value(0x1200), P(Q::from_raw_value(0x12))); 121 | EXPECT_EQ(P::from_raw_value(-0x1200), P(Q::from_raw_value(-0x12))); 122 | 123 | { 124 | // Assignment requires explicit conversion via construction 125 | P p(1); 126 | Q q = Q(p); 127 | EXPECT_EQ(Q(1), q); 128 | } 129 | 130 | // Conversion to a smaller base type should truncate the upper bits 131 | using S1 = fpm::fixed; 132 | EXPECT_EQ(0x56, S1(P::from_raw_value(0x79AB1000)).raw_value()); 133 | EXPECT_EQ(-0x56, S1(P::from_raw_value(-0x79AB1000)).raw_value()); 134 | } 135 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/re.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef BENCHMARK_RE_H_ 16 | #define BENCHMARK_RE_H_ 17 | 18 | #include "internal_macros.h" 19 | 20 | #if !defined(HAVE_STD_REGEX) && \ 21 | !defined(HAVE_GNU_POSIX_REGEX) && \ 22 | !defined(HAVE_POSIX_REGEX) 23 | // No explicit regex selection; detect based on builtin hints. 24 | #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE) 25 | #define HAVE_POSIX_REGEX 1 26 | #elif __cplusplus >= 199711L 27 | #define HAVE_STD_REGEX 1 28 | #endif 29 | #endif 30 | 31 | // Prefer C regex libraries when compiling w/o exceptions so that we can 32 | // correctly report errors. 33 | #if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \ 34 | defined(BENCHMARK_HAVE_STD_REGEX) && \ 35 | (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX)) 36 | #undef HAVE_STD_REGEX 37 | #endif 38 | 39 | #if defined(HAVE_STD_REGEX) 40 | #include 41 | #elif defined(HAVE_GNU_POSIX_REGEX) 42 | #include 43 | #elif defined(HAVE_POSIX_REGEX) 44 | #include 45 | #else 46 | #error No regular expression backend was found! 47 | #endif 48 | #include 49 | 50 | #include "check.h" 51 | 52 | namespace benchmark { 53 | 54 | // A wrapper around the POSIX regular expression API that provides automatic 55 | // cleanup 56 | class Regex { 57 | public: 58 | Regex() : init_(false) {} 59 | 60 | ~Regex(); 61 | 62 | // Compile a regular expression matcher from spec. Returns true on success. 63 | // 64 | // On failure (and if error is not nullptr), error is populated with a human 65 | // readable error message if an error occurs. 66 | bool Init(const std::string& spec, std::string* error); 67 | 68 | // Returns whether str matches the compiled regular expression. 69 | bool Match(const std::string& str); 70 | 71 | private: 72 | bool init_; 73 | // Underlying regular expression object 74 | #if defined(HAVE_STD_REGEX) 75 | std::regex re_; 76 | #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX) 77 | regex_t re_; 78 | #else 79 | #error No regular expression backend implementation available 80 | #endif 81 | }; 82 | 83 | #if defined(HAVE_STD_REGEX) 84 | 85 | inline bool Regex::Init(const std::string& spec, std::string* error) { 86 | #ifdef BENCHMARK_HAS_NO_EXCEPTIONS 87 | ((void)error); // suppress unused warning 88 | #else 89 | try { 90 | #endif 91 | re_ = std::regex(spec, std::regex_constants::extended); 92 | init_ = true; 93 | #ifndef BENCHMARK_HAS_NO_EXCEPTIONS 94 | } catch (const std::regex_error& e) { 95 | if (error) { 96 | *error = e.what(); 97 | } 98 | } 99 | #endif 100 | return init_; 101 | } 102 | 103 | inline Regex::~Regex() {} 104 | 105 | inline bool Regex::Match(const std::string& str) { 106 | if (!init_) { 107 | return false; 108 | } 109 | return std::regex_search(str, re_); 110 | } 111 | 112 | #else 113 | inline bool Regex::Init(const std::string& spec, std::string* error) { 114 | int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB); 115 | if (ec != 0) { 116 | if (error) { 117 | size_t needed = regerror(ec, &re_, nullptr, 0); 118 | char* errbuf = new char[needed]; 119 | regerror(ec, &re_, errbuf, needed); 120 | 121 | // regerror returns the number of bytes necessary to null terminate 122 | // the string, so we move that when assigning to error. 123 | CHECK_NE(needed, 0); 124 | error->assign(errbuf, needed - 1); 125 | 126 | delete[] errbuf; 127 | } 128 | 129 | return false; 130 | } 131 | 132 | init_ = true; 133 | return true; 134 | } 135 | 136 | inline Regex::~Regex() { 137 | if (init_) { 138 | regfree(&re_); 139 | } 140 | } 141 | 142 | inline bool Regex::Match(const std::string& str) { 143 | if (!init_) { 144 | return false; 145 | } 146 | return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0; 147 | } 148 | #endif 149 | 150 | } // end namespace benchmark 151 | 152 | #endif // BENCHMARK_RE_H_ 153 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/csv_reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "complexity.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "string_util.h" 26 | #include "timers.h" 27 | #include "check.h" 28 | 29 | // File format reference: http://edoceo.com/utilitas/csv-file-format. 30 | 31 | namespace benchmark { 32 | 33 | namespace { 34 | std::vector elements = { 35 | "name", "iterations", "real_time", "cpu_time", 36 | "time_unit", "bytes_per_second", "items_per_second", "label", 37 | "error_occurred", "error_message"}; 38 | } // namespace 39 | 40 | bool CSVReporter::ReportContext(const Context& context) { 41 | PrintBasicContext(&GetErrorStream(), context); 42 | return true; 43 | } 44 | 45 | void CSVReporter::ReportRuns(const std::vector & reports) { 46 | std::ostream& Out = GetOutputStream(); 47 | 48 | if (!printed_header_) { 49 | // save the names of all the user counters 50 | for (const auto& run : reports) { 51 | for (const auto& cnt : run.counters) { 52 | user_counter_names_.insert(cnt.first); 53 | } 54 | } 55 | 56 | // print the header 57 | for (auto B = elements.begin(); B != elements.end();) { 58 | Out << *B++; 59 | if (B != elements.end()) Out << ","; 60 | } 61 | for (auto B = user_counter_names_.begin(); B != user_counter_names_.end();) { 62 | Out << ",\"" << *B++ << "\""; 63 | } 64 | Out << "\n"; 65 | 66 | printed_header_ = true; 67 | } else { 68 | // check that all the current counters are saved in the name set 69 | for (const auto& run : reports) { 70 | for (const auto& cnt : run.counters) { 71 | CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end()) 72 | << "All counters must be present in each run. " 73 | << "Counter named \"" << cnt.first 74 | << "\" was not in a run after being added to the header"; 75 | } 76 | } 77 | } 78 | 79 | // print results for each run 80 | for (const auto& run : reports) { 81 | PrintRunData(run); 82 | } 83 | 84 | } 85 | 86 | void CSVReporter::PrintRunData(const Run & run) { 87 | std::ostream& Out = GetOutputStream(); 88 | 89 | // Field with embedded double-quote characters must be doubled and the field 90 | // delimited with double-quotes. 91 | std::string name = run.benchmark_name; 92 | ReplaceAll(&name, "\"", "\"\""); 93 | Out << '"' << name << "\","; 94 | if (run.error_occurred) { 95 | Out << std::string(elements.size() - 3, ','); 96 | Out << "true,"; 97 | std::string msg = run.error_message; 98 | ReplaceAll(&msg, "\"", "\"\""); 99 | Out << '"' << msg << "\"\n"; 100 | return; 101 | } 102 | 103 | // Do not print iteration on bigO and RMS report 104 | if (!run.report_big_o && !run.report_rms) { 105 | Out << run.iterations; 106 | } 107 | Out << ","; 108 | 109 | Out << run.GetAdjustedRealTime() << ","; 110 | Out << run.GetAdjustedCPUTime() << ","; 111 | 112 | // Do not print timeLabel on bigO and RMS report 113 | if (run.report_big_o) { 114 | Out << GetBigOString(run.complexity); 115 | } else if (!run.report_rms) { 116 | Out << GetTimeUnitString(run.time_unit); 117 | } 118 | Out << ","; 119 | 120 | if (run.bytes_per_second > 0.0) { 121 | Out << run.bytes_per_second; 122 | } 123 | Out << ","; 124 | if (run.items_per_second > 0.0) { 125 | Out << run.items_per_second; 126 | } 127 | Out << ","; 128 | if (!run.report_label.empty()) { 129 | // Field with embedded double-quote characters must be doubled and the field 130 | // delimited with double-quotes. 131 | std::string label = run.report_label; 132 | ReplaceAll(&label, "\"", "\"\""); 133 | Out << "\"" << label << "\""; 134 | } 135 | Out << ",,"; // for error_occurred and error_message 136 | 137 | // Print user counters 138 | for (const auto &ucn : user_counter_names_) { 139 | auto it = run.counters.find(ucn); 140 | if(it == run.counters.end()) { 141 | Out << ","; 142 | } else { 143 | Out << "," << it->second; 144 | } 145 | } 146 | Out << '\n'; 147 | } 148 | 149 | } // end namespace benchmark 150 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_MUTEX_H_ 2 | #define BENCHMARK_MUTEX_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "check.h" 8 | 9 | // Enable thread safety attributes only with clang. 10 | // The attributes can be safely erased when compiling with other compilers. 11 | #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) 12 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) 13 | #else 14 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op 15 | #endif 16 | 17 | #define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) 18 | 19 | #define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) 20 | 21 | #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) 22 | 23 | #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) 24 | 25 | #define ACQUIRED_BEFORE(...) \ 26 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) 27 | 28 | #define ACQUIRED_AFTER(...) \ 29 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) 30 | 31 | #define REQUIRES(...) \ 32 | THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) 33 | 34 | #define REQUIRES_SHARED(...) \ 35 | THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) 36 | 37 | #define ACQUIRE(...) \ 38 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) 39 | 40 | #define ACQUIRE_SHARED(...) \ 41 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) 42 | 43 | #define RELEASE(...) \ 44 | THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) 45 | 46 | #define RELEASE_SHARED(...) \ 47 | THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) 48 | 49 | #define TRY_ACQUIRE(...) \ 50 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) 51 | 52 | #define TRY_ACQUIRE_SHARED(...) \ 53 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) 54 | 55 | #define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) 56 | 57 | #define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) 58 | 59 | #define ASSERT_SHARED_CAPABILITY(x) \ 60 | THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) 61 | 62 | #define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) 63 | 64 | #define NO_THREAD_SAFETY_ANALYSIS \ 65 | THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) 66 | 67 | namespace benchmark { 68 | 69 | typedef std::condition_variable Condition; 70 | 71 | // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that 72 | // we can annotate them with thread safety attributes and use the 73 | // -Wthread-safety warning with clang. The standard library types cannot be 74 | // used directly because they do not provided the required annotations. 75 | class CAPABILITY("mutex") Mutex { 76 | public: 77 | Mutex() {} 78 | 79 | void lock() ACQUIRE() { mut_.lock(); } 80 | void unlock() RELEASE() { mut_.unlock(); } 81 | std::mutex& native_handle() { return mut_; } 82 | 83 | private: 84 | std::mutex mut_; 85 | }; 86 | 87 | class SCOPED_CAPABILITY MutexLock { 88 | typedef std::unique_lock MutexLockImp; 89 | 90 | public: 91 | MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {} 92 | ~MutexLock() RELEASE() {} 93 | MutexLockImp& native_handle() { return ml_; } 94 | 95 | private: 96 | MutexLockImp ml_; 97 | }; 98 | 99 | class Barrier { 100 | public: 101 | Barrier(int num_threads) : running_threads_(num_threads) {} 102 | 103 | // Called by each thread 104 | bool wait() EXCLUDES(lock_) { 105 | bool last_thread = false; 106 | { 107 | MutexLock ml(lock_); 108 | last_thread = createBarrier(ml); 109 | } 110 | if (last_thread) phase_condition_.notify_all(); 111 | return last_thread; 112 | } 113 | 114 | void removeThread() EXCLUDES(lock_) { 115 | MutexLock ml(lock_); 116 | --running_threads_; 117 | if (entered_ != 0) phase_condition_.notify_all(); 118 | } 119 | 120 | private: 121 | Mutex lock_; 122 | Condition phase_condition_; 123 | int running_threads_; 124 | 125 | // State for barrier management 126 | int phase_number_ = 0; 127 | int entered_ = 0; // Number of threads that have entered this barrier 128 | 129 | // Enter the barrier and wait until all other threads have also 130 | // entered the barrier. Returns iff this is the last thread to 131 | // enter the barrier. 132 | bool createBarrier(MutexLock& ml) REQUIRES(lock_) { 133 | CHECK_LT(entered_, running_threads_); 134 | entered_++; 135 | if (entered_ < running_threads_) { 136 | // Wait for all threads to enter 137 | int phase_number_cp = phase_number_; 138 | auto cb = [this, phase_number_cp]() { 139 | return this->phase_number_ > phase_number_cp || 140 | entered_ == running_threads_; // A thread has aborted in error 141 | }; 142 | phase_condition_.wait(ml.native_handle(), cb); 143 | if (phase_number_ > phase_number_cp) return false; 144 | // else (running_threads_ == entered_) and we are the last thread. 145 | } 146 | // Last thread has reached the barrier 147 | phase_number_++; 148 | entered_ = 0; 149 | return true; 150 | } 151 | }; 152 | 153 | } // end namespace benchmark 154 | 155 | #endif // BENCHMARK_MUTEX_H_ 156 | -------------------------------------------------------------------------------- /tests/customizations.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | template 4 | class customizations : public ::testing::Test 5 | { 6 | }; 7 | 8 | using FixedTypes = ::testing::Types; 9 | 10 | TYPED_TEST_SUITE(customizations, FixedTypes); 11 | 12 | TYPED_TEST(customizations, swap) 13 | { 14 | using std::swap; 15 | 16 | using P = TypeParam; 17 | P x{1}, y{2}; 18 | swap(x, y); 19 | EXPECT_EQ(P{2}, x); 20 | EXPECT_EQ(P{1}, y); 21 | } 22 | 23 | TYPED_TEST(customizations, hash) 24 | { 25 | using P = TypeParam; 26 | 27 | const std::hash

hash{}; 28 | for (int y = -50; y < 50; ++y) 29 | { 30 | EXPECT_EQ(hash(P{y}/10), hash(P{y}/10)); 31 | for (int x = -50; x < 50; ++x) 32 | { 33 | if (x != y) 34 | { 35 | EXPECT_NE(hash(P{x}/10), hash(P{y}/10)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | template 42 | struct Limits {}; 43 | 44 | template <> 45 | struct Limits 46 | { 47 | static constexpr bool is_signed() noexcept { return true; } 48 | static constexpr int digits() noexcept { return 31; } 49 | static constexpr int max_digits10() noexcept { return 5+5; } 50 | static constexpr int min_exponent() noexcept { return -15; } 51 | static constexpr int max_exponent() noexcept { return 15; } 52 | static constexpr int min_exponent10() noexcept { return -4; } 53 | static constexpr int max_exponent10() noexcept { return 4; } 54 | static constexpr fpm::fixed_16_16 min() noexcept { return fpm::fixed_16_16::from_raw_value(-2147483647 - 1); } 55 | static constexpr fpm::fixed_16_16 max() noexcept { return fpm::fixed_16_16::from_raw_value( 2147483647); } 56 | }; 57 | 58 | template <> 59 | struct Limits 60 | { 61 | static constexpr bool is_signed() noexcept { return true; } 62 | static constexpr int digits() noexcept { return 31; } 63 | static constexpr int max_digits10() noexcept { return 7+3; } 64 | static constexpr int min_exponent() noexcept { return -7; } 65 | static constexpr int max_exponent() noexcept { return 23; } 66 | static constexpr int min_exponent10() noexcept { return -2; } 67 | static constexpr int max_exponent10() noexcept { return 6; } 68 | static constexpr fpm::fixed_24_8 min() noexcept { return fpm::fixed_24_8::from_raw_value(-2147483647 - 1); } 69 | static constexpr fpm::fixed_24_8 max() noexcept { return fpm::fixed_24_8::from_raw_value( 2147483647); } 70 | }; 71 | 72 | template <> 73 | struct Limits 74 | { 75 | static constexpr bool is_signed() noexcept { return true; } 76 | static constexpr int digits() noexcept { return 31; } 77 | static constexpr int max_digits10() noexcept { return 3+8; } 78 | static constexpr int min_exponent() noexcept { return -23; } 79 | static constexpr int max_exponent() noexcept { return 7; } 80 | static constexpr int min_exponent10() noexcept { return -7; } 81 | static constexpr int max_exponent10() noexcept { return 2; } 82 | static constexpr fpm::fixed_8_24 min() noexcept { return fpm::fixed_8_24::from_raw_value(-2147483647 - 1); } 83 | static constexpr fpm::fixed_8_24 max() noexcept { return fpm::fixed_8_24::from_raw_value( 2147483647); } 84 | }; 85 | 86 | TYPED_TEST(customizations, numeric_limits) 87 | { 88 | using L = std::numeric_limits; 89 | using TL = Limits; 90 | 91 | EXPECT_EQ(L::is_specialized, true); 92 | EXPECT_EQ(L::is_signed, TL::is_signed()); 93 | EXPECT_EQ(L::is_integer, false); 94 | EXPECT_EQ(L::is_exact, true); 95 | EXPECT_EQ(L::has_infinity, false); 96 | EXPECT_EQ(L::has_quiet_NaN, false); 97 | EXPECT_EQ(L::has_signaling_NaN, false); 98 | EXPECT_EQ(L::has_denorm, std::denorm_absent); 99 | EXPECT_EQ(L::has_denorm_loss, false); 100 | EXPECT_EQ(L::round_style, std::round_to_nearest); 101 | EXPECT_EQ(L::is_iec559, false); 102 | EXPECT_EQ(L::is_bounded, true); 103 | EXPECT_EQ(L::is_modulo, false); 104 | EXPECT_EQ(L::digits, TL::digits()); 105 | EXPECT_EQ(L::digits10, 1); 106 | EXPECT_EQ(L::max_digits10, TL::max_digits10()); 107 | EXPECT_EQ(L::radix, 2); 108 | EXPECT_EQ(L::min_exponent, TL::min_exponent()); 109 | EXPECT_EQ(L::min_exponent10, TL::min_exponent10()); 110 | EXPECT_EQ(L::max_exponent, TL::max_exponent()); 111 | EXPECT_EQ(L::max_exponent10, TL::max_exponent10()); 112 | EXPECT_EQ(L::traps, true); 113 | EXPECT_EQ(L::tinyness_before, false); 114 | 115 | EXPECT_EQ(L::min(), TL::min()); 116 | EXPECT_EQ(L::lowest(), TL::min()); 117 | EXPECT_EQ(L::max(), TL::max()); 118 | EXPECT_EQ(L::epsilon(), TypeParam::from_raw_value(1)); 119 | EXPECT_EQ(L::round_error(), TypeParam(0.5)); 120 | EXPECT_EQ(L::denorm_min(), TL::min()); 121 | } 122 | 123 | // Verify that a a type with a single integral bit works correctly 124 | TEST(customizations, numeric_limits_edge) 125 | { 126 | using Q15 = fpm::fixed; 127 | EXPECT_TRUE(HasMaximumError(static_cast(std::numeric_limits::max()), 0.999, 0.01)); 128 | EXPECT_EQ(-1.0, static_cast(std::numeric_limits::lowest())); 129 | 130 | using Q31 = fpm::fixed; 131 | EXPECT_TRUE(HasMaximumError(static_cast(std::numeric_limits::max()), 0.999, 0.01)); 132 | EXPECT_EQ(-1.0, static_cast(std::numeric_limits::lowest())); 133 | } -------------------------------------------------------------------------------- /accuracy/accuracy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static constexpr double PI = 3.1415926535897932384626433832795; 10 | 11 | using fpm::fixed_8_24; 12 | using fpm::fixed_16_16; 13 | using fpm::fixed_24_8; 14 | using fixed_20_12 = fpm::fixed; 15 | 16 | using std::sin; 17 | using std::cos; 18 | using std::tan; 19 | using std::asin; 20 | using std::acos; 21 | using std::atan; 22 | using std::atan2; 23 | using std::sqrt; 24 | 25 | static Fix16 sin(Fix16 x) { return x.sin(); } 26 | static Fix16 cos(Fix16 x) { return x.cos(); } 27 | static Fix16 tan(Fix16 x) { return x.tan(); } 28 | static Fix16 asin(Fix16 x) { return x.asin(); } 29 | static Fix16 acos(Fix16 x) { return x.acos(); } 30 | static Fix16 atan(Fix16 x) { return x.atan(); } 31 | static Fix16 atan2(Fix16 x, Fix16 y) { return x.atan2(y); } 32 | static Fix16 sqrt(Fix16 x) { return x.sqrt(); } 33 | static Fix16 exp(Fix16 x) { return fix16_exp(x); } 34 | static Fix16 log(Fix16 x) { return fix16_log(x); } 35 | static Fix16 log2(Fix16 x) { return fix16_log2(x); } 36 | 37 | class csv_output 38 | { 39 | public: 40 | explicit csv_output(const std::string& filename) 41 | : m_stream(filename) 42 | { 43 | m_stream.setf(std::ios::fixed); 44 | m_stream.precision(12); 45 | m_stream << "x,real,Q24.8,Q20.12,Q16.16,Q8.24,fix16\n"; 46 | } 47 | 48 | void write_row(double x, double y_real, double y_q24_8, double y_q20_12, double y_q16_16, double y_q8_24, double y_fix16) 49 | { 50 | m_stream << x << "," << y_real << "," << y_q24_8 << "," << y_q20_12 << "," << y_q16_16 << "," << y_q8_24 << "," << y_fix16 << "\n"; 51 | } 52 | 53 | void write_row(double x, double y_real, double y_q24_8, double y_q20_12, double y_q16_16, double y_q8_24) 54 | { 55 | m_stream << x << "," << y_real << "," << y_q24_8 << "," << y_q20_12 << "," << y_q16_16 << "," << y_q8_24 << ",-\n"; 56 | } 57 | 58 | private: 59 | std::ofstream m_stream; 60 | }; 61 | 62 | template 63 | static void check_all(csv_output& output, double value, Callable&& callable, Args&& ...args) 64 | { 65 | output.write_row(value, 66 | callable(std::forward(args)...), 67 | static_cast(callable(fixed_24_8(std::forward(args))...)), 68 | static_cast(callable(fixed_20_12(std::forward(args))...)), 69 | static_cast(callable(fixed_16_16(std::forward(args))...)), 70 | static_cast(callable(fixed_8_24(std::forward(args))...)), 71 | static_cast(callable(Fix16(std::forward(args))...))); 72 | } 73 | 74 | template 75 | static void check_fpm(csv_output& output, double value, Callable&& callable, Args&& ...args) 76 | { 77 | output.write_row(value, 78 | callable(std::forward(args)...), 79 | static_cast(callable(fixed_24_8(std::forward(args))...)), 80 | static_cast(callable(fixed_20_12(std::forward(args))...)), 81 | static_cast(callable(fixed_16_16(std::forward(args))...)), 82 | static_cast(callable(fixed_8_24(std::forward(args))...))); 83 | } 84 | 85 | int main() 86 | { 87 | csv_output out_sin("sin.csv"); 88 | csv_output out_cos("cos.csv"); 89 | csv_output out_tan("tan.csv"); 90 | csv_output out_atan2("atan2.csv"); 91 | for (int angle = -179; angle <= 180; ++angle) 92 | { 93 | const double val = angle * PI / 180.0; 94 | 95 | check_all(out_sin, val, [](auto x) { return sin(x); }, val); 96 | check_all(out_cos, val, [](auto x) { return cos(x); }, val); 97 | if ((angle + 90) % 180 != 0) 98 | { 99 | check_all(out_tan, val, [](auto x) { return tan(x); }, val); 100 | } 101 | 102 | const auto y = std::sin(val); 103 | const auto x = std::cos(val); 104 | check_all(out_atan2, val, [](auto y, auto x) { return atan2(y, x); }, y, x); 105 | } 106 | 107 | csv_output out_asin("asin.csv"); 108 | csv_output out_acos("acos.csv"); 109 | for (int value = -100; value <= 100; ++value) 110 | { 111 | const double val = value / 100.0; 112 | check_all(out_asin, val, [](auto x) { return asin(x); }, val); 113 | check_all(out_acos, val, [](auto x) { return acos(x); }, val); 114 | } 115 | 116 | csv_output out_atan("atan.csv"); 117 | for (int value = -5000; value <= 5000; value += 5) 118 | { 119 | const double val = value / 1000.0; 120 | check_all(out_atan, val, [](auto x) { return atan(x); }, val); 121 | } 122 | 123 | csv_output out_sqrt("sqrt.csv"); 124 | for (int i = 0; i < 1000; ++i) 125 | { 126 | const auto val = i / 10.0; 127 | check_all(out_sqrt, val, [](auto x) { return sqrt(x); }, val); 128 | } 129 | 130 | csv_output out_cbrt("cbrt.csv"); 131 | for (int i = -1000; i < 1000; ++i) 132 | { 133 | const auto val = i / 10.0; 134 | check_fpm(out_cbrt, val, [](auto x) { return cbrt(x); }, val); 135 | } 136 | 137 | csv_output out_exp("exp.csv"); 138 | csv_output out_exp2("exp2.csv"); 139 | csv_output out_pow("pow.csv"); 140 | for (int i = -40; i <= 40; i++) 141 | { 142 | const auto val = i / 10.0; 143 | check_all(out_exp, val, [](auto x) { return exp(x); }, val); 144 | check_fpm(out_exp2, val, [](auto x) { return exp2(x); }, val); 145 | check_fpm(out_pow, val, [](auto x) { return pow(decltype(x){3.36}, x); }, val); 146 | } 147 | 148 | csv_output out_log("log.csv"); 149 | csv_output out_log2("log2.csv"); 150 | csv_output out_log10("log10.csv"); 151 | for (int i = 1; i < 1000; i++) 152 | { 153 | const auto val = i / 10.0; 154 | check_all(out_log, val, [](auto x) { return log(x); }, val); 155 | check_all(out_log2, val, [](auto x) { return log2(x); }, val); 156 | check_fpm(out_log10, val, [](auto x) { return log10(x); }, val); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/colorprint.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "colorprint.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "check.h" 25 | #include "internal_macros.h" 26 | 27 | #ifdef BENCHMARK_OS_WINDOWS 28 | #include 29 | #include 30 | #else 31 | #include 32 | #endif // BENCHMARK_OS_WINDOWS 33 | 34 | namespace benchmark { 35 | namespace { 36 | #ifdef BENCHMARK_OS_WINDOWS 37 | typedef WORD PlatformColorCode; 38 | #else 39 | typedef const char* PlatformColorCode; 40 | #endif 41 | 42 | PlatformColorCode GetPlatformColorCode(LogColor color) { 43 | #ifdef BENCHMARK_OS_WINDOWS 44 | switch (color) { 45 | case COLOR_RED: 46 | return FOREGROUND_RED; 47 | case COLOR_GREEN: 48 | return FOREGROUND_GREEN; 49 | case COLOR_YELLOW: 50 | return FOREGROUND_RED | FOREGROUND_GREEN; 51 | case COLOR_BLUE: 52 | return FOREGROUND_BLUE; 53 | case COLOR_MAGENTA: 54 | return FOREGROUND_BLUE | FOREGROUND_RED; 55 | case COLOR_CYAN: 56 | return FOREGROUND_BLUE | FOREGROUND_GREEN; 57 | case COLOR_WHITE: // fall through to default 58 | default: 59 | return 0; 60 | } 61 | #else 62 | switch (color) { 63 | case COLOR_RED: 64 | return "1"; 65 | case COLOR_GREEN: 66 | return "2"; 67 | case COLOR_YELLOW: 68 | return "3"; 69 | case COLOR_BLUE: 70 | return "4"; 71 | case COLOR_MAGENTA: 72 | return "5"; 73 | case COLOR_CYAN: 74 | return "6"; 75 | case COLOR_WHITE: 76 | return "7"; 77 | default: 78 | return nullptr; 79 | }; 80 | #endif 81 | } 82 | 83 | } // end namespace 84 | 85 | std::string FormatString(const char* msg, va_list args) { 86 | // we might need a second shot at this, so pre-emptivly make a copy 87 | va_list args_cp; 88 | va_copy(args_cp, args); 89 | 90 | std::size_t size = 256; 91 | char local_buff[256]; 92 | auto ret = vsnprintf(local_buff, size, msg, args_cp); 93 | 94 | va_end(args_cp); 95 | 96 | // currently there is no error handling for failure, so this is hack. 97 | CHECK(ret >= 0); 98 | 99 | if (ret == 0) // handle empty expansion 100 | return {}; 101 | else if (static_cast(ret) < size) 102 | return local_buff; 103 | else { 104 | // we did not provide a long enough buffer on our first attempt. 105 | size = (size_t)ret + 1; // + 1 for the null byte 106 | std::unique_ptr buff(new char[size]); 107 | ret = vsnprintf(buff.get(), size, msg, args); 108 | CHECK(ret > 0 && ((size_t)ret) < size); 109 | return buff.get(); 110 | } 111 | } 112 | 113 | std::string FormatString(const char* msg, ...) { 114 | va_list args; 115 | va_start(args, msg); 116 | auto tmp = FormatString(msg, args); 117 | va_end(args); 118 | return tmp; 119 | } 120 | 121 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) { 122 | va_list args; 123 | va_start(args, fmt); 124 | ColorPrintf(out, color, fmt, args); 125 | va_end(args); 126 | } 127 | 128 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, 129 | va_list args) { 130 | #ifdef BENCHMARK_OS_WINDOWS 131 | ((void)out); // suppress unused warning 132 | 133 | const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); 134 | 135 | // Gets the current text color. 136 | CONSOLE_SCREEN_BUFFER_INFO buffer_info; 137 | GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); 138 | const WORD old_color_attrs = buffer_info.wAttributes; 139 | 140 | // We need to flush the stream buffers into the console before each 141 | // SetConsoleTextAttribute call lest it affect the text that is already 142 | // printed but has not yet reached the console. 143 | fflush(stdout); 144 | SetConsoleTextAttribute(stdout_handle, 145 | GetPlatformColorCode(color) | FOREGROUND_INTENSITY); 146 | vprintf(fmt, args); 147 | 148 | fflush(stdout); 149 | // Restores the text color. 150 | SetConsoleTextAttribute(stdout_handle, old_color_attrs); 151 | #else 152 | const char* color_code = GetPlatformColorCode(color); 153 | if (color_code) out << FormatString("\033[0;3%sm", color_code); 154 | out << FormatString(fmt, args) << "\033[m"; 155 | #endif 156 | } 157 | 158 | bool IsColorTerminal() { 159 | #if BENCHMARK_OS_WINDOWS 160 | // On Windows the TERM variable is usually not set, but the 161 | // console there does support colors. 162 | return 0 != _isatty(_fileno(stdout)); 163 | #else 164 | // On non-Windows platforms, we rely on the TERM variable. This list of 165 | // supported TERM values is copied from Google Test: 166 | // . 167 | const char* const SUPPORTED_TERM_VALUES[] = { 168 | "xterm", "xterm-color", "xterm-256color", 169 | "screen", "screen-256color", "tmux", 170 | "tmux-256color", "rxvt-unicode", "rxvt-unicode-256color", 171 | "linux", "cygwin", 172 | }; 173 | 174 | const char* const term = getenv("TERM"); 175 | 176 | bool term_supports_color = false; 177 | for (const char* candidate : SUPPORTED_TERM_VALUES) { 178 | if (term && 0 == strcmp(term, candidate)) { 179 | term_supports_color = true; 180 | break; 181 | } 182 | } 183 | 184 | return 0 != isatty(fileno(stdout)) && term_supports_color; 185 | #endif // BENCHMARK_OS_WINDOWS 186 | } 187 | 188 | } // end namespace benchmark 189 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/string_util.cc: -------------------------------------------------------------------------------- 1 | #include "string_util.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "arraysize.h" 11 | 12 | namespace benchmark { 13 | namespace { 14 | 15 | // kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta. 16 | const char kBigSIUnits[] = "kMGTPEZY"; 17 | // Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi. 18 | const char kBigIECUnits[] = "KMGTPEZY"; 19 | // milli, micro, nano, pico, femto, atto, zepto, yocto. 20 | const char kSmallSIUnits[] = "munpfazy"; 21 | 22 | // We require that all three arrays have the same size. 23 | static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits), 24 | "SI and IEC unit arrays must be the same size"); 25 | static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits), 26 | "Small SI and Big SI unit arrays must be the same size"); 27 | 28 | static const int64_t kUnitsSize = arraysize(kBigSIUnits); 29 | 30 | void ToExponentAndMantissa(double val, double thresh, int precision, 31 | double one_k, std::string* mantissa, 32 | int64_t* exponent) { 33 | std::stringstream mantissa_stream; 34 | 35 | if (val < 0) { 36 | mantissa_stream << "-"; 37 | val = -val; 38 | } 39 | 40 | // Adjust threshold so that it never excludes things which can't be rendered 41 | // in 'precision' digits. 42 | const double adjusted_threshold = 43 | std::max(thresh, 1.0 / std::pow(10.0, precision)); 44 | const double big_threshold = adjusted_threshold * one_k; 45 | const double small_threshold = adjusted_threshold; 46 | // Values in ]simple_threshold,small_threshold[ will be printed as-is 47 | const double simple_threshold = 0.01; 48 | 49 | if (val > big_threshold) { 50 | // Positive powers 51 | double scaled = val; 52 | for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) { 53 | scaled /= one_k; 54 | if (scaled <= big_threshold) { 55 | mantissa_stream << scaled; 56 | *exponent = i + 1; 57 | *mantissa = mantissa_stream.str(); 58 | return; 59 | } 60 | } 61 | mantissa_stream << val; 62 | *exponent = 0; 63 | } else if (val < small_threshold) { 64 | // Negative powers 65 | if (val < simple_threshold) { 66 | double scaled = val; 67 | for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) { 68 | scaled *= one_k; 69 | if (scaled >= small_threshold) { 70 | mantissa_stream << scaled; 71 | *exponent = -static_cast(i + 1); 72 | *mantissa = mantissa_stream.str(); 73 | return; 74 | } 75 | } 76 | } 77 | mantissa_stream << val; 78 | *exponent = 0; 79 | } else { 80 | mantissa_stream << val; 81 | *exponent = 0; 82 | } 83 | *mantissa = mantissa_stream.str(); 84 | } 85 | 86 | std::string ExponentToPrefix(int64_t exponent, bool iec) { 87 | if (exponent == 0) return ""; 88 | 89 | const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1); 90 | if (index >= kUnitsSize) return ""; 91 | 92 | const char* array = 93 | (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits); 94 | if (iec) 95 | return array[index] + std::string("i"); 96 | else 97 | return std::string(1, array[index]); 98 | } 99 | 100 | std::string ToBinaryStringFullySpecified(double value, double threshold, 101 | int precision, double one_k = 1024.0) { 102 | std::string mantissa; 103 | int64_t exponent; 104 | ToExponentAndMantissa(value, threshold, precision, one_k, &mantissa, 105 | &exponent); 106 | return mantissa + ExponentToPrefix(exponent, false); 107 | } 108 | 109 | } // end namespace 110 | 111 | void AppendHumanReadable(int n, std::string* str) { 112 | std::stringstream ss; 113 | // Round down to the nearest SI prefix. 114 | ss << ToBinaryStringFullySpecified(n, 1.0, 0); 115 | *str += ss.str(); 116 | } 117 | 118 | std::string HumanReadableNumber(double n, double one_k) { 119 | // 1.1 means that figures up to 1.1k should be shown with the next unit down; 120 | // this softens edge effects. 121 | // 1 means that we should show one decimal place of precision. 122 | return ToBinaryStringFullySpecified(n, 1.1, 1, one_k); 123 | } 124 | 125 | std::string StrFormatImp(const char* msg, va_list args) { 126 | // we might need a second shot at this, so pre-emptivly make a copy 127 | va_list args_cp; 128 | va_copy(args_cp, args); 129 | 130 | // TODO(ericwf): use std::array for first attempt to avoid one memory 131 | // allocation guess what the size might be 132 | std::array local_buff; 133 | std::size_t size = local_buff.size(); 134 | // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation 135 | // in the android-ndk 136 | auto ret = vsnprintf(local_buff.data(), size, msg, args_cp); 137 | 138 | va_end(args_cp); 139 | 140 | // handle empty expansion 141 | if (ret == 0) return std::string{}; 142 | if (static_cast(ret) < size) 143 | return std::string(local_buff.data()); 144 | 145 | // we did not provide a long enough buffer on our first attempt. 146 | // add 1 to size to account for null-byte in size cast to prevent overflow 147 | size = static_cast(ret) + 1; 148 | auto buff_ptr = std::unique_ptr(new char[size]); 149 | // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation 150 | // in the android-ndk 151 | ret = vsnprintf(buff_ptr.get(), size, msg, args); 152 | return std::string(buff_ptr.get()); 153 | } 154 | 155 | std::string StrFormat(const char* format, ...) { 156 | va_list args; 157 | va_start(args, format); 158 | std::string tmp = StrFormatImp(format, args); 159 | va_end(args); 160 | return tmp; 161 | } 162 | 163 | void ReplaceAll(std::string* str, const std::string& from, 164 | const std::string& to) { 165 | std::size_t start = 0; 166 | while ((start = str->find(from, start)) != std::string::npos) { 167 | str->replace(start, from.length(), to); 168 | start += to.length(); 169 | } 170 | } 171 | 172 | } // end namespace benchmark 173 | -------------------------------------------------------------------------------- /3rdparty/googletest/src/gtest-matchers.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This file implements just enough of the matcher interface to allow 33 | // EXPECT_DEATH and friends to accept a matcher argument. 34 | 35 | #include "gtest/internal/gtest-internal.h" 36 | #include "gtest/internal/gtest-port.h" 37 | #include "gtest/gtest-matchers.h" 38 | 39 | #include 40 | 41 | namespace testing { 42 | 43 | // Constructs a matcher that matches a const std::string& whose value is 44 | // equal to s. 45 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 46 | 47 | #if GTEST_HAS_GLOBAL_STRING 48 | // Constructs a matcher that matches a const std::string& whose value is 49 | // equal to s. 50 | Matcher::Matcher(const ::string& s) { 51 | *this = Eq(static_cast(s)); 52 | } 53 | #endif // GTEST_HAS_GLOBAL_STRING 54 | 55 | // Constructs a matcher that matches a const std::string& whose value is 56 | // equal to s. 57 | Matcher::Matcher(const char* s) { 58 | *this = Eq(std::string(s)); 59 | } 60 | 61 | // Constructs a matcher that matches a std::string whose value is equal to 62 | // s. 63 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 64 | 65 | #if GTEST_HAS_GLOBAL_STRING 66 | // Constructs a matcher that matches a std::string whose value is equal to 67 | // s. 68 | Matcher::Matcher(const ::string& s) { 69 | *this = Eq(static_cast(s)); 70 | } 71 | #endif // GTEST_HAS_GLOBAL_STRING 72 | 73 | // Constructs a matcher that matches a std::string whose value is equal to 74 | // s. 75 | Matcher::Matcher(const char* s) { *this = Eq(std::string(s)); } 76 | 77 | #if GTEST_HAS_GLOBAL_STRING 78 | // Constructs a matcher that matches a const ::string& whose value is 79 | // equal to s. 80 | Matcher::Matcher(const std::string& s) { 81 | *this = Eq(static_cast<::string>(s)); 82 | } 83 | 84 | // Constructs a matcher that matches a const ::string& whose value is 85 | // equal to s. 86 | Matcher::Matcher(const ::string& s) { *this = Eq(s); } 87 | 88 | // Constructs a matcher that matches a const ::string& whose value is 89 | // equal to s. 90 | Matcher::Matcher(const char* s) { *this = Eq(::string(s)); } 91 | 92 | // Constructs a matcher that matches a ::string whose value is equal to s. 93 | Matcher<::string>::Matcher(const std::string& s) { 94 | *this = Eq(static_cast<::string>(s)); 95 | } 96 | 97 | // Constructs a matcher that matches a ::string whose value is equal to s. 98 | Matcher<::string>::Matcher(const ::string& s) { *this = Eq(s); } 99 | 100 | // Constructs a matcher that matches a string whose value is equal to s. 101 | Matcher<::string>::Matcher(const char* s) { *this = Eq(::string(s)); } 102 | #endif // GTEST_HAS_GLOBAL_STRING 103 | 104 | #if GTEST_HAS_ABSL 105 | // Constructs a matcher that matches a const absl::string_view& whose value is 106 | // equal to s. 107 | Matcher::Matcher(const std::string& s) { 108 | *this = Eq(s); 109 | } 110 | 111 | #if GTEST_HAS_GLOBAL_STRING 112 | // Constructs a matcher that matches a const absl::string_view& whose value is 113 | // equal to s. 114 | Matcher::Matcher(const ::string& s) { *this = Eq(s); } 115 | #endif // GTEST_HAS_GLOBAL_STRING 116 | 117 | // Constructs a matcher that matches a const absl::string_view& whose value is 118 | // equal to s. 119 | Matcher::Matcher(const char* s) { 120 | *this = Eq(std::string(s)); 121 | } 122 | 123 | // Constructs a matcher that matches a const absl::string_view& whose value is 124 | // equal to s. 125 | Matcher::Matcher(absl::string_view s) { 126 | *this = Eq(std::string(s)); 127 | } 128 | 129 | // Constructs a matcher that matches a absl::string_view whose value is equal to 130 | // s. 131 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 132 | 133 | #if GTEST_HAS_GLOBAL_STRING 134 | // Constructs a matcher that matches a absl::string_view whose value is equal to 135 | // s. 136 | Matcher::Matcher(const ::string& s) { *this = Eq(s); } 137 | #endif // GTEST_HAS_GLOBAL_STRING 138 | 139 | // Constructs a matcher that matches a absl::string_view whose value is equal to 140 | // s. 141 | Matcher::Matcher(const char* s) { 142 | *this = Eq(std::string(s)); 143 | } 144 | 145 | // Constructs a matcher that matches a absl::string_view whose value is equal to 146 | // s. 147 | Matcher::Matcher(absl::string_view s) { 148 | *this = Eq(std::string(s)); 149 | } 150 | #endif // GTEST_HAS_ABSL 151 | 152 | } // namespace testing 153 | -------------------------------------------------------------------------------- /tests/classification.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(classification, fpclassify) 5 | { 6 | using P = fpm::fixed; 7 | EXPECT_EQ(FP_NORMAL, fpclassify(P(1.0))); 8 | EXPECT_EQ(FP_NORMAL, fpclassify(P(-1.0))); 9 | EXPECT_EQ(FP_NORMAL, fpclassify(P(0.5))); 10 | EXPECT_EQ(FP_ZERO, fpclassify(P(0))); 11 | } 12 | 13 | TEST(classification, isfinite) 14 | { 15 | using P = fpm::fixed; 16 | EXPECT_TRUE(isfinite(P(1.0))); 17 | EXPECT_TRUE(isfinite(P(-1.0))); 18 | EXPECT_TRUE(isfinite(P(0.5))); 19 | EXPECT_TRUE(isfinite(P(0))); 20 | } 21 | 22 | TEST(classification, isinf) 23 | { 24 | using P = fpm::fixed; 25 | EXPECT_FALSE(isinf(P(1.0))); 26 | EXPECT_FALSE(isinf(P(-1.0))); 27 | EXPECT_FALSE(isinf(P(0.5))); 28 | EXPECT_FALSE(isinf(P(0))); 29 | } 30 | 31 | TEST(classification, isnan) 32 | { 33 | using P = fpm::fixed; 34 | EXPECT_FALSE(isnan(P(1.0))); 35 | EXPECT_FALSE(isnan(P(-1.0))); 36 | EXPECT_FALSE(isnan(P(0.5))); 37 | EXPECT_FALSE(isnan(P(0))); 38 | } 39 | 40 | TEST(classification, isnormal) 41 | { 42 | using P = fpm::fixed; 43 | EXPECT_TRUE(isnormal(P(1.0))); 44 | EXPECT_TRUE(isnormal(P(-1.0))); 45 | EXPECT_TRUE(isnormal(P(0.5))); 46 | EXPECT_FALSE(isnormal(P(0))); 47 | } 48 | 49 | TEST(classification, signbit) 50 | { 51 | using P = fpm::fixed; 52 | EXPECT_FALSE(signbit(P(1.0))); 53 | EXPECT_TRUE(signbit(P(-1.0))); 54 | EXPECT_FALSE(signbit(P(0.5))); 55 | EXPECT_FALSE(signbit(P(0))); 56 | } 57 | 58 | TEST(classification, isgreater) 59 | { 60 | using P = fpm::fixed; 61 | EXPECT_FALSE(isgreater(P(1.0), P(2.0))); 62 | EXPECT_FALSE(isgreater(P(1.0), P(1.0))); 63 | EXPECT_TRUE(isgreater(P(2.0), P(1.0))); 64 | EXPECT_FALSE(isgreater(P(-2.0), P(-1.0))); 65 | EXPECT_FALSE(isgreater(P(-2.0), P(-2.0))); 66 | EXPECT_TRUE(isgreater(P(-1.0), P(-2.0))); 67 | EXPECT_FALSE(isgreater(P(0.25), P(0.5))); 68 | EXPECT_FALSE(isgreater(P(0.25), P(0.25))); 69 | EXPECT_TRUE(isgreater(P(0.5), P(0.25))); 70 | EXPECT_FALSE(isgreater(P(-1), P(0))); 71 | EXPECT_FALSE(isgreater(P(-1), P(-1))); 72 | EXPECT_TRUE(isgreater(P(0), P(-1))); 73 | EXPECT_FALSE(isgreater(P(0), P(0))); 74 | } 75 | 76 | TEST(classification, isgreaterequal) 77 | { 78 | using P = fpm::fixed; 79 | EXPECT_FALSE(isgreaterequal(P(1.0), P(2.0))); 80 | EXPECT_TRUE(isgreaterequal(P(1.0), P(1.0))); 81 | EXPECT_TRUE(isgreaterequal(P(2.0), P(1.0))); 82 | EXPECT_FALSE(isgreaterequal(P(-2.0), P(-1.0))); 83 | EXPECT_TRUE(isgreaterequal(P(-2.0), P(-2.0))); 84 | EXPECT_TRUE(isgreaterequal(P(-1.0), P(-2.0))); 85 | EXPECT_FALSE(isgreaterequal(P(0.25), P(0.5))); 86 | EXPECT_TRUE(isgreaterequal(P(0.25), P(0.25))); 87 | EXPECT_TRUE(isgreaterequal(P(0.5), P(0.25))); 88 | EXPECT_FALSE(isgreaterequal(P(-1), P(0))); 89 | EXPECT_TRUE(isgreaterequal(P(-1), P(-1))); 90 | EXPECT_TRUE(isgreaterequal(P(0), P(-1))); 91 | EXPECT_TRUE(isgreaterequal(P(0), P(0))); 92 | } 93 | 94 | TEST(classification, isless) 95 | { 96 | using P = fpm::fixed; 97 | EXPECT_TRUE(isless(P(1.0), P(2.0))); 98 | EXPECT_FALSE(isless(P(1.0), P(1.0))); 99 | EXPECT_FALSE(isless(P(2.0), P(1.0))); 100 | EXPECT_TRUE(isless(P(-2.0), P(-1.0))); 101 | EXPECT_FALSE(isless(P(-2.0), P(-2.0))); 102 | EXPECT_FALSE(isless(P(-1.0), P(-2.0))); 103 | EXPECT_TRUE(isless(P(0.25), P(0.5))); 104 | EXPECT_FALSE(isless(P(0.25), P(0.25))); 105 | EXPECT_FALSE(isless(P(0.5), P(0.25))); 106 | EXPECT_TRUE(isless(P(-1), P(0))); 107 | EXPECT_FALSE(isless(P(-1), P(-1))); 108 | EXPECT_FALSE(isless(P(0), P(-1))); 109 | EXPECT_FALSE(isless(P(0), P(0))); 110 | } 111 | 112 | TEST(classification, islessequal) 113 | { 114 | using P = fpm::fixed; 115 | EXPECT_TRUE(islessequal(P(1.0), P(2.0))); 116 | EXPECT_TRUE(islessequal(P(1.0), P(1.0))); 117 | EXPECT_FALSE(islessequal(P(2.0), P(1.0))); 118 | EXPECT_TRUE(islessequal(P(-2.0), P(-1.0))); 119 | EXPECT_TRUE(islessequal(P(-2.0), P(-2.0))); 120 | EXPECT_FALSE(islessequal(P(-1.0), P(-2.0))); 121 | EXPECT_TRUE(islessequal(P(0.25), P(0.5))); 122 | EXPECT_TRUE(islessequal(P(0.25), P(0.25))); 123 | EXPECT_FALSE(islessequal(P(0.5), P(0.25))); 124 | EXPECT_TRUE(islessequal(P(-1), P(0))); 125 | EXPECT_TRUE(islessequal(P(-1), P(-1))); 126 | EXPECT_FALSE(islessequal(P(0), P(-1))); 127 | EXPECT_TRUE(islessequal(P(0), P(0))); 128 | } 129 | 130 | TEST(classification, islessgreater) 131 | { 132 | using P = fpm::fixed; 133 | EXPECT_TRUE(islessgreater(P(1.0), P(2.0))); 134 | EXPECT_FALSE(islessgreater(P(1.0), P(1.0))); 135 | EXPECT_TRUE(islessgreater(P(2.0), P(1.0))); 136 | EXPECT_TRUE(islessgreater(P(-2.0), P(-1.0))); 137 | EXPECT_FALSE(islessgreater(P(-2.0), P(-2.0))); 138 | EXPECT_TRUE(islessgreater(P(-1.0), P(-2.0))); 139 | EXPECT_TRUE(islessgreater(P(0.25), P(0.5))); 140 | EXPECT_FALSE(islessgreater(P(0.25), P(0.25))); 141 | EXPECT_TRUE(islessgreater(P(0.5), P(0.25))); 142 | EXPECT_TRUE(islessgreater(P(-1), P(0))); 143 | EXPECT_FALSE(islessgreater(P(-1), P(-1))); 144 | EXPECT_TRUE(islessgreater(P(0), P(-1))); 145 | EXPECT_FALSE(islessgreater(P(0), P(0))); 146 | } 147 | 148 | TEST(classification, isunordered) 149 | { 150 | using P = fpm::fixed; 151 | EXPECT_FALSE(isunordered(P(1.0), P(2.0))); 152 | EXPECT_FALSE(isunordered(P(1.0), P(1.0))); 153 | EXPECT_FALSE(isunordered(P(2.0), P(1.0))); 154 | EXPECT_FALSE(isunordered(P(-2.0), P(-1.0))); 155 | EXPECT_FALSE(isunordered(P(-2.0), P(-2.0))); 156 | EXPECT_FALSE(isunordered(P(-1.0), P(-2.0))); 157 | EXPECT_FALSE(isunordered(P(0.25), P(0.5))); 158 | EXPECT_FALSE(isunordered(P(0.25), P(0.25))); 159 | EXPECT_FALSE(isunordered(P(0.5), P(0.25))); 160 | EXPECT_FALSE(isunordered(P(-1), P(0))); 161 | EXPECT_FALSE(isunordered(P(-1), P(-1))); 162 | EXPECT_FALSE(isunordered(P(0), P(-1))); 163 | EXPECT_FALSE(isunordered(P(0), P(0))); 164 | } 165 | 166 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | # fpm 5 | A C++ header-only fixed-point math library. "fpm" stands for "fixed-point math". 6 | 7 | It is designed to serve as a drop-in replacement for floating-point types and aims to provide as much of the standard library's functionality as possible with exclusively integers. `fpm` requires C++11 or higher. 8 | 9 | ## Usage 10 | `fpm` defines the `fpm::fixed` class, which is templated on the underlying integer type and the number of bits in the fraction: 11 | ```c++ 12 | namespace fpm { 13 | template 14 | class fixed; 15 | } 16 | ``` 17 | **Note:** It's recommended to use a *signed* integer type for `BaseType` (and `IntermediateType`) to emulate floating-point numbers 18 | and to allow the compiler to optimize the computations, since overflow and underflow are undefined 19 | for signed integer types. 20 | 21 | To use this class, simply include its header: 22 | ```c++ 23 | #include 24 | ``` 25 | You may wish to typedef a particular choice of underlying type, intermediate type and fraction bitcount, e.g.: 26 | ```c++ 27 | using position = fpm::fixed; 28 | ``` 29 | This defines a signed 16.16 fixed-point number with a range of -32768 to 32767.999985... and a resolution of 0.0000153... It uses 64-bit integers as intermediate type during calculations to avoid loss of information. 30 | 31 | For your convenience, several popular fixed-point formats have been defined in the `fpm` namespace: 32 | ```c++ 33 | namespace fpm { 34 | using fixed_16_16 = fixed; // Q16.16 format 35 | using fixed_24_8 = fixed; // Q24.8 format 36 | using fixed_8_24 = fixed; // Q8.24 format 37 | } 38 | ``` 39 | 40 | ## Mathematical functions 41 | FPM offers the header `` with mathematical functions that operate on its fixed-point types, similar to `` for floating-point types. 42 | The available functions for fixed-point types include: 43 | * basic functions: `abs`, `fmod`, `remainder`, `copysign`, `remquo`, etc. 44 | * trigonometry functions: `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2`. 45 | * exponential functions: `exp`, `exp2`, `expm1`, `log`, `log10`, `log2` and `log1p`. 46 | * power functions: `pow`, `sqrt`, `cbrt` and `hypot`. 47 | * classification functions: `fpclassify`, `isnormal`, `isnan`, `isnormal`, etc. 48 | 49 | Notes: 50 | * all functions are in the `fpm` namespace. 51 | * certain functions will always return the same value (e.g. `isnan` and `isinf` will always return false). 52 | * be mindful of a function's domain and range: the result of `pow` can quickly overflow with certain inputs. On the other hand, trigonometry functions such as `sin` require more bits in the fraction for accurate results. 53 | 54 | ## Specialized customization points 55 | The header `` provides specializations for `fpm::fixed` for the following types: 56 | * `std::hash` 57 | * `std::numeric_limits` 58 | 59 | ## Conversions 60 | The intent behind `fpm` is to replace floats for purposes of performance or portability. Thus, it guards against accidental usage of floats by requiring explicit conversion: 61 | ```c++ 62 | fpm::fixed_16_16 a = 0.5; // Error: implicit construction from float 63 | fpm::fixed_16_16 b { 0.5 }; // OK: explicit construction from float 64 | fpm::fixed_16_16 c = b * 0.5; // Error: implicit conversion from float 65 | float d = b; // Error: implicit conversion to float 66 | float e = static_cast(b); // OK: explicit conversion to float 67 | ``` 68 | 69 | For integers, this still applies to initialization, but arithmetic operations *can* use integers: 70 | ```c++ 71 | fpm::fixed_16_16 a = 2; // Error: implicit construction from int 72 | fpm::fixed_16_16 b { 2 }; // OK: explicit construction from int 73 | fpm::fixed_16_16 c = b / 2; // OK 74 | int d = b; // Error: requires explicit conversion 75 | int e = static_cast(b); // OK: explicit conversion to int 76 | ``` 77 | You must still guard against underflow and overflow, though. 78 | 79 | `fpm::fixed` can be constructed from an `fpm::fixed` via explicit construction. This allows for conversion between fixed-point numbers of differing precision and range. 80 | Depending on the respective underlying types and number of fraction bits, this conversion may throw away high bits in the integral or low bits in the fraction. 81 | 82 | ## Printing and reading fixed-point numbers 83 | The `` header provides streaming operators. Simply stream an expression of type `fpm::fixed` to or from a `std::ostream`. 84 | 85 | For instance, the following program prints `"===3.142e+02"`: 86 | ```c++ 87 | #include 88 | #include 89 | #include 90 | #include 91 | 92 | int main() { 93 | fpm::fixed_16_16 x { 314.1516 }; 94 | std::cout << std::setw(12) << std::setfill('=') << std::setprecision(3) << std::scientific << x << std::endl; 95 | return 0; 96 | } 97 | ``` 98 | 99 | Reading fixed point numbers works similarly, by streaming `fpm::fixed` types from a `std::istream`. 100 | 101 | `fpm`'s implementation of the streaming operators emulates streaming native floats as closely as possible without using floating-point types. 102 | 103 | ## Common constants 104 | The following static member functions in the `fpm::fixed` class provide common mathematical constants in the fixed type: 105 | * `e()`: _e_, roughly equal to 2.71828183. 106 | * `pi()`: _π_, roughly equal to 3.14159265. 107 | * `half_pi()`: _½π_, roughly equal to 1.57079633. 108 | * `two_pi()`: _2π_, roughly equal to 6.2831853. 109 | 110 | ## Accuracy and performance 111 | Please refer to the pages for [accuracy](accuracy.md) and [performance](performance.md) results. 112 | 113 | ## Limitations 114 | Unlike floating-point numbers, `fpm::fixed`: 115 | * can not represent Not-a-Number, infinity or negative zero. 116 | * does not have a notion of subnormal numbers. 117 | * does have a risk of overflow and underflow. 118 | 119 | Notably the last point requires careful use of fixed-point numbers: like integers, you must ensure that they do not overflow or underflow. 120 | 121 | ## Alternatives 122 | * [libfixmath](https://github.com/PetteriAimonen/libfixmath): C99 library, only supports Q16.16 format backed by 32-bit integers. 123 | * [Compositional Numeric Library](https://github.com/johnmcfarlane/cnl): an experimental C++ header-only library worked on as part of WG-21/SG-14. Lacks many mathematical functions. 124 | * [fp](https://github.com/mizvekov/fp): a C++14 header-only library. Does not provide any mathematical functions. -------------------------------------------------------------------------------- /3rdparty/googlebench/src/statistics.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // Copyright 2017 Roman Lebedev. All rights reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | #include "benchmark/benchmark.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "check.h" 24 | #include "statistics.h" 25 | 26 | namespace benchmark { 27 | 28 | auto StatisticsSum = [](const std::vector& v) { 29 | return std::accumulate(v.begin(), v.end(), 0.0); 30 | }; 31 | 32 | double StatisticsMean(const std::vector& v) { 33 | if (v.empty()) return 0.0; 34 | return StatisticsSum(v) * (1.0 / v.size()); 35 | } 36 | 37 | double StatisticsMedian(const std::vector& v) { 38 | if (v.size() < 3) return StatisticsMean(v); 39 | std::vector copy(v); 40 | 41 | auto center = copy.begin() + v.size() / 2; 42 | std::nth_element(copy.begin(), center, copy.end()); 43 | 44 | // did we have an odd number of samples? 45 | // if yes, then center is the median 46 | // it no, then we are looking for the average between center and the value before 47 | if(v.size() % 2 == 1) 48 | return *center; 49 | auto center2 = copy.begin() + v.size() / 2 - 1; 50 | std::nth_element(copy.begin(), center2, copy.end()); 51 | return (*center + *center2) / 2.0; 52 | } 53 | 54 | // Return the sum of the squares of this sample set 55 | auto SumSquares = [](const std::vector& v) { 56 | return std::inner_product(v.begin(), v.end(), v.begin(), 0.0); 57 | }; 58 | 59 | auto Sqr = [](const double dat) { return dat * dat; }; 60 | auto Sqrt = [](const double dat) { 61 | // Avoid NaN due to imprecision in the calculations 62 | if (dat < 0.0) return 0.0; 63 | return std::sqrt(dat); 64 | }; 65 | 66 | double StatisticsStdDev(const std::vector& v) { 67 | const auto mean = StatisticsMean(v); 68 | if (v.empty()) return mean; 69 | 70 | // Sample standard deviation is undefined for n = 1 71 | if (v.size() == 1) 72 | return 0.0; 73 | 74 | const double avg_squares = SumSquares(v) * (1.0 / v.size()); 75 | return Sqrt(v.size() / (v.size() - 1.0) * (avg_squares - Sqr(mean))); 76 | } 77 | 78 | std::vector ComputeStats( 79 | const std::vector& reports) { 80 | typedef BenchmarkReporter::Run Run; 81 | std::vector results; 82 | 83 | auto error_count = 84 | std::count_if(reports.begin(), reports.end(), 85 | [](Run const& run) { return run.error_occurred; }); 86 | 87 | if (reports.size() - error_count < 2) { 88 | // We don't report aggregated data if there was a single run. 89 | return results; 90 | } 91 | 92 | // Accumulators. 93 | std::vector real_accumulated_time_stat; 94 | std::vector cpu_accumulated_time_stat; 95 | std::vector bytes_per_second_stat; 96 | std::vector items_per_second_stat; 97 | 98 | real_accumulated_time_stat.reserve(reports.size()); 99 | cpu_accumulated_time_stat.reserve(reports.size()); 100 | bytes_per_second_stat.reserve(reports.size()); 101 | items_per_second_stat.reserve(reports.size()); 102 | 103 | // All repetitions should be run with the same number of iterations so we 104 | // can take this information from the first benchmark. 105 | int64_t const run_iterations = reports.front().iterations; 106 | // create stats for user counters 107 | struct CounterStat { 108 | Counter c; 109 | std::vector s; 110 | }; 111 | std::map< std::string, CounterStat > counter_stats; 112 | for(Run const& r : reports) { 113 | for(auto const& cnt : r.counters) { 114 | auto it = counter_stats.find(cnt.first); 115 | if(it == counter_stats.end()) { 116 | counter_stats.insert({cnt.first, {cnt.second, std::vector{}}}); 117 | it = counter_stats.find(cnt.first); 118 | it->second.s.reserve(reports.size()); 119 | } else { 120 | CHECK_EQ(counter_stats[cnt.first].c.flags, cnt.second.flags); 121 | } 122 | } 123 | } 124 | 125 | // Populate the accumulators. 126 | for (Run const& run : reports) { 127 | CHECK_EQ(reports[0].benchmark_name, run.benchmark_name); 128 | CHECK_EQ(run_iterations, run.iterations); 129 | if (run.error_occurred) continue; 130 | real_accumulated_time_stat.emplace_back(run.real_accumulated_time); 131 | cpu_accumulated_time_stat.emplace_back(run.cpu_accumulated_time); 132 | items_per_second_stat.emplace_back(run.items_per_second); 133 | bytes_per_second_stat.emplace_back(run.bytes_per_second); 134 | // user counters 135 | for(auto const& cnt : run.counters) { 136 | auto it = counter_stats.find(cnt.first); 137 | CHECK_NE(it, counter_stats.end()); 138 | it->second.s.emplace_back(cnt.second); 139 | } 140 | } 141 | 142 | // Only add label if it is same for all runs 143 | std::string report_label = reports[0].report_label; 144 | for (std::size_t i = 1; i < reports.size(); i++) { 145 | if (reports[i].report_label != report_label) { 146 | report_label = ""; 147 | break; 148 | } 149 | } 150 | 151 | for(const auto& Stat : *reports[0].statistics) { 152 | // Get the data from the accumulator to BenchmarkReporter::Run's. 153 | Run data; 154 | data.benchmark_name = reports[0].benchmark_name + "_" + Stat.name_; 155 | data.report_label = report_label; 156 | data.iterations = run_iterations; 157 | 158 | data.real_accumulated_time = Stat.compute_(real_accumulated_time_stat); 159 | data.cpu_accumulated_time = Stat.compute_(cpu_accumulated_time_stat); 160 | data.bytes_per_second = Stat.compute_(bytes_per_second_stat); 161 | data.items_per_second = Stat.compute_(items_per_second_stat); 162 | 163 | data.time_unit = reports[0].time_unit; 164 | 165 | // user counters 166 | for(auto const& kv : counter_stats) { 167 | const auto uc_stat = Stat.compute_(kv.second.s); 168 | auto c = Counter(uc_stat, counter_stats[kv.first].c.flags); 169 | data.counters[kv.first] = c; 170 | } 171 | 172 | results.push_back(data); 173 | } 174 | 175 | return results; 176 | } 177 | 178 | } // end namespace benchmark 179 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/console_reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "complexity.h" 17 | #include "counter.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "check.h" 28 | #include "colorprint.h" 29 | #include "commandlineflags.h" 30 | #include "internal_macros.h" 31 | #include "string_util.h" 32 | #include "timers.h" 33 | 34 | namespace benchmark { 35 | 36 | bool ConsoleReporter::ReportContext(const Context& context) { 37 | name_field_width_ = context.name_field_width; 38 | printed_header_ = false; 39 | prev_counters_.clear(); 40 | 41 | PrintBasicContext(&GetErrorStream(), context); 42 | 43 | #ifdef BENCHMARK_OS_WINDOWS 44 | if ((output_options_ & OO_Color) && &std::cout != &GetOutputStream()) { 45 | GetErrorStream() 46 | << "Color printing is only supported for stdout on windows." 47 | " Disabling color printing\n"; 48 | output_options_ = static_cast< OutputOptions >(output_options_ & ~OO_Color); 49 | } 50 | #endif 51 | 52 | return true; 53 | } 54 | 55 | void ConsoleReporter::PrintHeader(const Run& run) { 56 | std::string str = FormatString("%-*s %13s %13s %10s", static_cast(name_field_width_), 57 | "Benchmark", "Time", "CPU", "Iterations"); 58 | if(!run.counters.empty()) { 59 | if(output_options_ & OO_Tabular) { 60 | for(auto const& c : run.counters) { 61 | str += FormatString(" %10s", c.first.c_str()); 62 | } 63 | } else { 64 | str += " UserCounters..."; 65 | } 66 | } 67 | str += "\n"; 68 | std::string line = std::string(str.length(), '-'); 69 | GetOutputStream() << line << "\n" << str << line << "\n"; 70 | } 71 | 72 | void ConsoleReporter::ReportRuns(const std::vector& reports) { 73 | for (const auto& run : reports) { 74 | // print the header: 75 | // --- if none was printed yet 76 | bool print_header = !printed_header_; 77 | // --- or if the format is tabular and this run 78 | // has different fields from the prev header 79 | print_header |= (output_options_ & OO_Tabular) && 80 | (!internal::SameNames(run.counters, prev_counters_)); 81 | if (print_header) { 82 | printed_header_ = true; 83 | prev_counters_ = run.counters; 84 | PrintHeader(run); 85 | } 86 | // As an alternative to printing the headers like this, we could sort 87 | // the benchmarks by header and then print. But this would require 88 | // waiting for the full results before printing, or printing twice. 89 | PrintRunData(run); 90 | } 91 | } 92 | 93 | static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt, 94 | ...) { 95 | va_list args; 96 | va_start(args, fmt); 97 | out << FormatString(fmt, args); 98 | va_end(args); 99 | } 100 | 101 | void ConsoleReporter::PrintRunData(const Run& result) { 102 | typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...); 103 | auto& Out = GetOutputStream(); 104 | PrinterFn* printer = (output_options_ & OO_Color) ? 105 | (PrinterFn*)ColorPrintf : IgnoreColorPrint; 106 | auto name_color = 107 | (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN; 108 | printer(Out, name_color, "%-*s ", name_field_width_, 109 | result.benchmark_name.c_str()); 110 | 111 | if (result.error_occurred) { 112 | printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'", 113 | result.error_message.c_str()); 114 | printer(Out, COLOR_DEFAULT, "\n"); 115 | return; 116 | } 117 | // Format bytes per second 118 | std::string rate; 119 | if (result.bytes_per_second > 0) { 120 | rate = StrCat(" ", HumanReadableNumber(result.bytes_per_second), "B/s"); 121 | } 122 | 123 | // Format items per second 124 | std::string items; 125 | if (result.items_per_second > 0) { 126 | items = 127 | StrCat(" ", HumanReadableNumber(result.items_per_second), " items/s"); 128 | } 129 | 130 | const double real_time = result.GetAdjustedRealTime(); 131 | const double cpu_time = result.GetAdjustedCPUTime(); 132 | 133 | if (result.report_big_o) { 134 | std::string big_o = GetBigOString(result.complexity); 135 | printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time, big_o.c_str(), 136 | cpu_time, big_o.c_str()); 137 | } else if (result.report_rms) { 138 | printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100, 139 | cpu_time * 100); 140 | } else { 141 | const char* timeLabel = GetTimeUnitString(result.time_unit); 142 | printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel, 143 | cpu_time, timeLabel); 144 | } 145 | 146 | if (!result.report_big_o && !result.report_rms) { 147 | printer(Out, COLOR_CYAN, "%10lld", result.iterations); 148 | } 149 | 150 | for (auto& c : result.counters) { 151 | const std::size_t cNameLen = std::max(std::string::size_type(10), 152 | c.first.length()); 153 | auto const& s = HumanReadableNumber(c.second.value, 1000); 154 | if (output_options_ & OO_Tabular) { 155 | if (c.second.flags & Counter::kIsRate) { 156 | printer(Out, COLOR_DEFAULT, " %*s/s", cNameLen - 2, s.c_str()); 157 | } else { 158 | printer(Out, COLOR_DEFAULT, " %*s", cNameLen, s.c_str()); 159 | } 160 | } else { 161 | const char* unit = (c.second.flags & Counter::kIsRate) ? "/s" : ""; 162 | printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), 163 | unit); 164 | } 165 | } 166 | 167 | if (!rate.empty()) { 168 | printer(Out, COLOR_DEFAULT, " %*s", 13, rate.c_str()); 169 | } 170 | 171 | if (!items.empty()) { 172 | printer(Out, COLOR_DEFAULT, " %*s", 18, items.c_str()); 173 | } 174 | 175 | if (!result.report_label.empty()) { 176 | printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str()); 177 | } 178 | 179 | printer(Out, COLOR_DEFAULT, "\n"); 180 | } 181 | 182 | } // end namespace benchmark 183 | -------------------------------------------------------------------------------- /tests/trigonometry.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include 3 | 4 | TEST(trigonometry, sin) 5 | { 6 | using P = fpm::fixed; 7 | const double PI = std::acos(-1); 8 | 9 | constexpr auto MAX_ERROR_PERC = 0.002; 10 | 11 | for (int angle = -1799; angle <= 1800; ++angle) 12 | { 13 | auto flt_angle = angle * PI / 180; 14 | auto sin_real = std::sin(flt_angle); 15 | auto sin_fixed = static_cast(sin(P(flt_angle))); 16 | EXPECT_TRUE(HasMaximumError(sin_fixed, sin_real, MAX_ERROR_PERC)); 17 | } 18 | } 19 | 20 | TEST(trigonometry, cos) 21 | { 22 | using P = fpm::fixed; 23 | const double PI = std::acos(-1); 24 | 25 | constexpr auto MAX_ERROR_PERC = 0.002; 26 | 27 | for (int angle = -1799; angle <= 1800; ++angle) 28 | { 29 | auto flt_angle = angle * PI / 180; 30 | auto cos_real = std::cos(flt_angle); 31 | auto cos_fixed = static_cast(cos(P(flt_angle))); 32 | EXPECT_TRUE(HasMaximumError(cos_fixed, cos_real, MAX_ERROR_PERC)); 33 | } 34 | 35 | // Boundary-value analysis 36 | // x = 2147380704 generates an overflow when calculating cos(x) = sin(x+π/2). Result: -0.9231 instead of 0.9279. 37 | constexpr int32_t raw_values[] = {INT32_MIN, INT32_MAX, 2147380704 }; 38 | 39 | for (auto raw_value : raw_values) 40 | { 41 | constexpr auto MAX_ERROR_PERC = 0.0492; // 4.92% = Maximum relative deviation over the value range of f_16_16 42 | P angle_fixed = P::from_raw_value(raw_value); 43 | auto angle_real = static_cast(angle_fixed); 44 | auto cos_fixed = static_cast(cos(angle_fixed)); 45 | auto cos_real = std::cos(angle_real); 46 | auto diff = std::abs(cos_fixed - cos_real); 47 | EXPECT_TRUE(HasMaximumError(cos_fixed, cos_real, MAX_ERROR_PERC)) << ", raw_value=" << raw_value << ", error=" << std::abs(diff/cos_real)*100 << "%"; 48 | } 49 | } 50 | 51 | TEST(trigonometry, tan) 52 | { 53 | using P = fpm::fixed; 54 | const double PI = std::acos(-1); 55 | 56 | constexpr auto MAX_ERROR_PERC = 0.002; 57 | 58 | for (int angle = -1799; angle <= 1800; ++angle) 59 | { 60 | // Tangent goes to infinite at 90 and -90 degrees. 61 | // We can't represent that with fixed-point maths, so don't test for it. 62 | if ((angle + 90) % 180 != 0) 63 | { 64 | auto flt_angle = angle * PI / 180; 65 | auto tan_real = std::tan(flt_angle); 66 | auto tan_fixed = static_cast(tan(P(flt_angle))); 67 | EXPECT_TRUE(HasMaximumError(tan_fixed, tan_real, MAX_ERROR_PERC)); 68 | } 69 | } 70 | 71 | // Boundary-value analysis 72 | // x = 2147380704 generates an overflow when calculating tan(x) with cos(x)=sin(x+π/2). cos(x) result: -0.9231 instead of 0.9279. 73 | constexpr int32_t raw_values[] = {INT32_MIN, INT32_MAX, 2147380704 }; 74 | for (auto raw_value : raw_values) 75 | { 76 | constexpr auto MAX_ERROR_PERC = 0.0492; // 4.92% = Maximum relative deviation over the value range of f_16_16 77 | P angle_fixed = P::from_raw_value(raw_value); 78 | auto angle_real = static_cast(angle_fixed); 79 | auto tan_fixed = static_cast(tan(angle_fixed)); 80 | auto tan_real = std::tan(angle_real); 81 | auto diff = std::abs(tan_fixed - tan_real); 82 | EXPECT_TRUE(HasMaximumError(tan_fixed, tan_real, MAX_ERROR_PERC)) << ", raw_value=" << raw_value << ", error=" << std::abs(diff/tan_real)*100 << "%"; 83 | } 84 | 85 | #ifndef NDEBUG 86 | EXPECT_DEATH(tan(P::pi()/2), ""); 87 | EXPECT_DEATH(tan(-P::pi()/2), ""); 88 | #endif 89 | } 90 | 91 | TEST(trigonometry, atan) 92 | { 93 | using P = fpm::fixed; 94 | 95 | constexpr auto MAX_ERROR_PERC = 0.025; 96 | 97 | for (int x = -1000; x <= 1000; ++x) 98 | { 99 | auto value = x / 10.0; 100 | auto atan_real = std::atan(value); 101 | auto atan_fixed = static_cast(atan(P(value))); 102 | EXPECT_TRUE(HasMaximumError(atan_fixed, atan_real, MAX_ERROR_PERC)); 103 | } 104 | 105 | for (int x = -1000; x <= 1000; ++x) 106 | { 107 | auto value = x / 1000.0; 108 | auto atan_real = std::atan(value); 109 | auto atan_fixed = static_cast(atan(P(value))); 110 | EXPECT_TRUE(HasMaximumError(atan_fixed, atan_real, MAX_ERROR_PERC)); 111 | } 112 | } 113 | 114 | TEST(trigonometry, asin) 115 | { 116 | using P = fpm::fixed; 117 | 118 | constexpr auto MAX_ERROR_PERC = 0.025; 119 | 120 | for (int x = -1000; x <= 1000; ++x) 121 | { 122 | auto value = x / 1000.0; 123 | auto asin_real = std::asin(value); 124 | auto asin_fixed = static_cast(asin(P(value))); 125 | EXPECT_TRUE(HasMaximumError(asin_fixed, asin_real, MAX_ERROR_PERC)); 126 | } 127 | } 128 | 129 | TEST(trigonometry, acos) 130 | { 131 | using P = fpm::fixed; 132 | 133 | constexpr auto MAX_ERROR_PERC = 0.025; 134 | 135 | for (int x = -1000; x <= 1000; ++x) 136 | { 137 | auto value = x / 1000.0; 138 | auto acos_real = std::acos(value); 139 | auto acos_fixed = static_cast(acos(P(value))); 140 | EXPECT_TRUE(HasMaximumError(acos_fixed, acos_real, MAX_ERROR_PERC)); 141 | } 142 | } 143 | 144 | TEST(trigonometry, atan2) 145 | { 146 | using P = fpm::fixed; 147 | const double PI = std::acos(-1); 148 | 149 | constexpr auto MAX_ERROR_PERC = 0.025; 150 | 151 | for (int angle = -1799; angle <= 1800; ++angle) 152 | { 153 | const auto y = std::sin(angle * PI / 1800); 154 | const auto x = std::cos(angle * PI / 1800); 155 | 156 | auto atan2_real = std::atan2(y, x); 157 | auto atan2_fixed = static_cast(atan2(P(y), P(x))); 158 | EXPECT_TRUE(HasMaximumError(atan2_fixed, atan2_real, MAX_ERROR_PERC)); 159 | } 160 | 161 | #ifndef NDEBUG 162 | EXPECT_DEATH(atan2(P(0), P(0)), ""); 163 | #endif 164 | } 165 | 166 | // Naively, atan2(y, x) does y / x which would overflow for near-zero x with Q16.16. 167 | // Test that we've got protections in place for this. 168 | TEST(trigonometry, atan2_near_zero) 169 | { 170 | constexpr auto MAX_ERROR_PERC = 0.025; 171 | using P = fpm::fixed_16_16; 172 | 173 | const auto x = P::from_raw_value(1); 174 | const auto y = P(100); 175 | 176 | // Positive x 177 | { 178 | auto atan2_real = std::atan2(static_cast(y), static_cast(x)); 179 | auto atan2_fixed = static_cast(atan2(y, x)); 180 | EXPECT_TRUE(HasMaximumError(atan2_fixed, atan2_real, MAX_ERROR_PERC)); 181 | } 182 | 183 | // Negative x 184 | { 185 | auto atan2_real = std::atan2(static_cast(y), static_cast(-x)); 186 | auto atan2_fixed = static_cast(atan2(y, -x)); 187 | EXPECT_TRUE(HasMaximumError(atan2_fixed, atan2_real, MAX_ERROR_PERC)); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /3rdparty/googlebench/src/json_reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "complexity.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include // for setprecision 25 | #include 26 | 27 | #include "string_util.h" 28 | #include "timers.h" 29 | 30 | namespace benchmark { 31 | 32 | namespace { 33 | 34 | std::string FormatKV(std::string const& key, std::string const& value) { 35 | return StrFormat("\"%s\": \"%s\"", key.c_str(), value.c_str()); 36 | } 37 | 38 | std::string FormatKV(std::string const& key, const char* value) { 39 | return StrFormat("\"%s\": \"%s\"", key.c_str(), value); 40 | } 41 | 42 | std::string FormatKV(std::string const& key, bool value) { 43 | return StrFormat("\"%s\": %s", key.c_str(), value ? "true" : "false"); 44 | } 45 | 46 | std::string FormatKV(std::string const& key, int64_t value) { 47 | std::stringstream ss; 48 | ss << '"' << key << "\": " << value; 49 | return ss.str(); 50 | } 51 | 52 | std::string FormatKV(std::string const& key, double value) { 53 | std::stringstream ss; 54 | ss << '"' << key << "\": "; 55 | 56 | const auto max_digits10 = std::numeric_limits::max_digits10; 57 | const auto max_fractional_digits10 = max_digits10 - 1; 58 | 59 | ss << std::scientific << std::setprecision(max_fractional_digits10) << value; 60 | return ss.str(); 61 | } 62 | 63 | int64_t RoundDouble(double v) { return static_cast(v + 0.5); } 64 | 65 | } // end namespace 66 | 67 | bool JSONReporter::ReportContext(const Context& context) { 68 | std::ostream& out = GetOutputStream(); 69 | 70 | out << "{\n"; 71 | std::string inner_indent(2, ' '); 72 | 73 | // Open context block and print context information. 74 | out << inner_indent << "\"context\": {\n"; 75 | std::string indent(4, ' '); 76 | 77 | std::string walltime_value = LocalDateTimeString(); 78 | out << indent << FormatKV("date", walltime_value) << ",\n"; 79 | 80 | if (Context::executable_name) { 81 | out << indent << FormatKV("executable", Context::executable_name) << ",\n"; 82 | } 83 | 84 | CPUInfo const& info = context.cpu_info; 85 | out << indent << FormatKV("num_cpus", static_cast(info.num_cpus)) 86 | << ",\n"; 87 | out << indent 88 | << FormatKV("mhz_per_cpu", 89 | RoundDouble(info.cycles_per_second / 1000000.0)) 90 | << ",\n"; 91 | out << indent << FormatKV("cpu_scaling_enabled", info.scaling_enabled) 92 | << ",\n"; 93 | 94 | out << indent << "\"caches\": [\n"; 95 | indent = std::string(6, ' '); 96 | std::string cache_indent(8, ' '); 97 | for (size_t i = 0; i < info.caches.size(); ++i) { 98 | auto& CI = info.caches[i]; 99 | out << indent << "{\n"; 100 | out << cache_indent << FormatKV("type", CI.type) << ",\n"; 101 | out << cache_indent << FormatKV("level", static_cast(CI.level)) 102 | << ",\n"; 103 | out << cache_indent 104 | << FormatKV("size", static_cast(CI.size) * 1000u) << ",\n"; 105 | out << cache_indent 106 | << FormatKV("num_sharing", static_cast(CI.num_sharing)) 107 | << "\n"; 108 | out << indent << "}"; 109 | if (i != info.caches.size() - 1) out << ","; 110 | out << "\n"; 111 | } 112 | indent = std::string(4, ' '); 113 | out << indent << "],\n"; 114 | 115 | #if defined(NDEBUG) 116 | const char build_type[] = "release"; 117 | #else 118 | const char build_type[] = "debug"; 119 | #endif 120 | out << indent << FormatKV("library_build_type", build_type) << "\n"; 121 | // Close context block and open the list of benchmarks. 122 | out << inner_indent << "},\n"; 123 | out << inner_indent << "\"benchmarks\": [\n"; 124 | return true; 125 | } 126 | 127 | void JSONReporter::ReportRuns(std::vector const& reports) { 128 | if (reports.empty()) { 129 | return; 130 | } 131 | std::string indent(4, ' '); 132 | std::ostream& out = GetOutputStream(); 133 | if (!first_report_) { 134 | out << ",\n"; 135 | } 136 | first_report_ = false; 137 | 138 | for (auto it = reports.begin(); it != reports.end(); ++it) { 139 | out << indent << "{\n"; 140 | PrintRunData(*it); 141 | out << indent << '}'; 142 | auto it_cp = it; 143 | if (++it_cp != reports.end()) { 144 | out << ",\n"; 145 | } 146 | } 147 | } 148 | 149 | void JSONReporter::Finalize() { 150 | // Close the list of benchmarks and the top level object. 151 | GetOutputStream() << "\n ]\n}\n"; 152 | } 153 | 154 | void JSONReporter::PrintRunData(Run const& run) { 155 | std::string indent(6, ' '); 156 | std::ostream& out = GetOutputStream(); 157 | out << indent << FormatKV("name", run.benchmark_name) << ",\n"; 158 | if (run.error_occurred) { 159 | out << indent << FormatKV("error_occurred", run.error_occurred) << ",\n"; 160 | out << indent << FormatKV("error_message", run.error_message) << ",\n"; 161 | } 162 | if (!run.report_big_o && !run.report_rms) { 163 | out << indent << FormatKV("iterations", run.iterations) << ",\n"; 164 | out << indent 165 | << FormatKV("real_time", run.GetAdjustedRealTime()) 166 | << ",\n"; 167 | out << indent 168 | << FormatKV("cpu_time", run.GetAdjustedCPUTime()); 169 | out << ",\n" 170 | << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit)); 171 | } else if (run.report_big_o) { 172 | out << indent 173 | << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime()) 174 | << ",\n"; 175 | out << indent 176 | << FormatKV("real_coefficient", run.GetAdjustedRealTime()) 177 | << ",\n"; 178 | out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n"; 179 | out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit)); 180 | } else if (run.report_rms) { 181 | out << indent 182 | << FormatKV("rms", run.GetAdjustedCPUTime()); 183 | } 184 | if (run.bytes_per_second > 0.0) { 185 | out << ",\n" 186 | << indent 187 | << FormatKV("bytes_per_second", run.bytes_per_second); 188 | } 189 | if (run.items_per_second > 0.0) { 190 | out << ",\n" 191 | << indent 192 | << FormatKV("items_per_second", run.items_per_second); 193 | } 194 | for(auto &c : run.counters) { 195 | out << ",\n" 196 | << indent 197 | << FormatKV(c.first, c.second); 198 | } 199 | if (!run.report_label.empty()) { 200 | out << ",\n" << indent << FormatKV("label", run.report_label); 201 | } 202 | out << '\n'; 203 | } 204 | 205 | } // end namespace benchmark 206 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/gtest-test-part.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // GOOGLETEST_CM0001 DO NOT DELETE 31 | 32 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 33 | #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 34 | 35 | #include 36 | #include 37 | #include "gtest/internal/gtest-internal.h" 38 | #include "gtest/internal/gtest-string.h" 39 | 40 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 41 | /* class A needs to have dll-interface to be used by clients of class B */) 42 | 43 | namespace testing { 44 | 45 | // A copyable object representing the result of a test part (i.e. an 46 | // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). 47 | // 48 | // Don't inherit from TestPartResult as its destructor is not virtual. 49 | class GTEST_API_ TestPartResult { 50 | public: 51 | // The possible outcomes of a test part (i.e. an assertion or an 52 | // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). 53 | enum Type { 54 | kSuccess, // Succeeded. 55 | kNonFatalFailure, // Failed but the test can continue. 56 | kFatalFailure, // Failed and the test should be terminated. 57 | kSkip // Skipped. 58 | }; 59 | 60 | // C'tor. TestPartResult does NOT have a default constructor. 61 | // Always use this constructor (with parameters) to create a 62 | // TestPartResult object. 63 | TestPartResult(Type a_type, const char* a_file_name, int a_line_number, 64 | const char* a_message) 65 | : type_(a_type), 66 | file_name_(a_file_name == nullptr ? "" : a_file_name), 67 | line_number_(a_line_number), 68 | summary_(ExtractSummary(a_message)), 69 | message_(a_message) {} 70 | 71 | // Gets the outcome of the test part. 72 | Type type() const { return type_; } 73 | 74 | // Gets the name of the source file where the test part took place, or 75 | // NULL if it's unknown. 76 | const char* file_name() const { 77 | return file_name_.empty() ? nullptr : file_name_.c_str(); 78 | } 79 | 80 | // Gets the line in the source file where the test part took place, 81 | // or -1 if it's unknown. 82 | int line_number() const { return line_number_; } 83 | 84 | // Gets the summary of the failure message. 85 | const char* summary() const { return summary_.c_str(); } 86 | 87 | // Gets the message associated with the test part. 88 | const char* message() const { return message_.c_str(); } 89 | 90 | // Returns true iff the test part was skipped. 91 | bool skipped() const { return type_ == kSkip; } 92 | 93 | // Returns true iff the test part passed. 94 | bool passed() const { return type_ == kSuccess; } 95 | 96 | // Returns true iff the test part non-fatally failed. 97 | bool nonfatally_failed() const { return type_ == kNonFatalFailure; } 98 | 99 | // Returns true iff the test part fatally failed. 100 | bool fatally_failed() const { return type_ == kFatalFailure; } 101 | 102 | // Returns true iff the test part failed. 103 | bool failed() const { return fatally_failed() || nonfatally_failed(); } 104 | 105 | private: 106 | Type type_; 107 | 108 | // Gets the summary of the failure message by omitting the stack 109 | // trace in it. 110 | static std::string ExtractSummary(const char* message); 111 | 112 | // The name of the source file where the test part took place, or 113 | // "" if the source file is unknown. 114 | std::string file_name_; 115 | // The line in the source file where the test part took place, or -1 116 | // if the line number is unknown. 117 | int line_number_; 118 | std::string summary_; // The test failure summary. 119 | std::string message_; // The test failure message. 120 | }; 121 | 122 | // Prints a TestPartResult object. 123 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result); 124 | 125 | // An array of TestPartResult objects. 126 | // 127 | // Don't inherit from TestPartResultArray as its destructor is not 128 | // virtual. 129 | class GTEST_API_ TestPartResultArray { 130 | public: 131 | TestPartResultArray() {} 132 | 133 | // Appends the given TestPartResult to the array. 134 | void Append(const TestPartResult& result); 135 | 136 | // Returns the TestPartResult at the given index (0-based). 137 | const TestPartResult& GetTestPartResult(int index) const; 138 | 139 | // Returns the number of TestPartResult objects in the array. 140 | int size() const; 141 | 142 | private: 143 | std::vector array_; 144 | 145 | GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); 146 | }; 147 | 148 | // This interface knows how to report a test part result. 149 | class GTEST_API_ TestPartResultReporterInterface { 150 | public: 151 | virtual ~TestPartResultReporterInterface() {} 152 | 153 | virtual void ReportTestPartResult(const TestPartResult& result) = 0; 154 | }; 155 | 156 | namespace internal { 157 | 158 | // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a 159 | // statement generates new fatal failures. To do so it registers itself as the 160 | // current test part result reporter. Besides checking if fatal failures were 161 | // reported, it only delegates the reporting to the former result reporter. 162 | // The original result reporter is restored in the destructor. 163 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 164 | class GTEST_API_ HasNewFatalFailureHelper 165 | : public TestPartResultReporterInterface { 166 | public: 167 | HasNewFatalFailureHelper(); 168 | ~HasNewFatalFailureHelper() override; 169 | void ReportTestPartResult(const TestPartResult& result) override; 170 | bool has_new_fatal_failure() const { return has_new_fatal_failure_; } 171 | private: 172 | bool has_new_fatal_failure_; 173 | TestPartResultReporterInterface* original_reporter_; 174 | 175 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); 176 | }; 177 | 178 | } // namespace internal 179 | 180 | } // namespace testing 181 | 182 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 183 | 184 | #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 185 | -------------------------------------------------------------------------------- /3rdparty/googletest/include/gtest/internal/gtest-string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This header file declares the String class and functions used internally by 33 | // Google Test. They are subject to change without notice. They should not used 34 | // by code external to Google Test. 35 | // 36 | // This header file is #included by gtest-internal.h. 37 | // It should not be #included by other files. 38 | 39 | // GOOGLETEST_CM0001 DO NOT DELETE 40 | 41 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 42 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 43 | 44 | #ifdef __BORLANDC__ 45 | // string.h is not guaranteed to provide strcpy on C++ Builder. 46 | # include 47 | #endif 48 | 49 | #include 50 | #include 51 | 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | namespace testing { 55 | namespace internal { 56 | 57 | // String - an abstract class holding static string utilities. 58 | class GTEST_API_ String { 59 | public: 60 | // Static utility methods 61 | 62 | // Clones a 0-terminated C string, allocating memory using new. The 63 | // caller is responsible for deleting the return value using 64 | // delete[]. Returns the cloned string, or NULL if the input is 65 | // NULL. 66 | // 67 | // This is different from strdup() in string.h, which allocates 68 | // memory using malloc(). 69 | static const char* CloneCString(const char* c_str); 70 | 71 | #if GTEST_OS_WINDOWS_MOBILE 72 | // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be 73 | // able to pass strings to Win32 APIs on CE we need to convert them 74 | // to 'Unicode', UTF-16. 75 | 76 | // Creates a UTF-16 wide string from the given ANSI string, allocating 77 | // memory using new. The caller is responsible for deleting the return 78 | // value using delete[]. Returns the wide string, or NULL if the 79 | // input is NULL. 80 | // 81 | // The wide string is created using the ANSI codepage (CP_ACP) to 82 | // match the behaviour of the ANSI versions of Win32 calls and the 83 | // C runtime. 84 | static LPCWSTR AnsiToUtf16(const char* c_str); 85 | 86 | // Creates an ANSI string from the given wide string, allocating 87 | // memory using new. The caller is responsible for deleting the return 88 | // value using delete[]. Returns the ANSI string, or NULL if the 89 | // input is NULL. 90 | // 91 | // The returned string is created using the ANSI codepage (CP_ACP) to 92 | // match the behaviour of the ANSI versions of Win32 calls and the 93 | // C runtime. 94 | static const char* Utf16ToAnsi(LPCWSTR utf16_str); 95 | #endif 96 | 97 | // Compares two C strings. Returns true iff they have the same content. 98 | // 99 | // Unlike strcmp(), this function can handle NULL argument(s). A 100 | // NULL C string is considered different to any non-NULL C string, 101 | // including the empty string. 102 | static bool CStringEquals(const char* lhs, const char* rhs); 103 | 104 | // Converts a wide C string to a String using the UTF-8 encoding. 105 | // NULL will be converted to "(null)". If an error occurred during 106 | // the conversion, "(failed to convert from wide string)" is 107 | // returned. 108 | static std::string ShowWideCString(const wchar_t* wide_c_str); 109 | 110 | // Compares two wide C strings. Returns true iff they have the same 111 | // content. 112 | // 113 | // Unlike wcscmp(), this function can handle NULL argument(s). A 114 | // NULL C string is considered different to any non-NULL C string, 115 | // including the empty string. 116 | static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); 117 | 118 | // Compares two C strings, ignoring case. Returns true iff they 119 | // have the same content. 120 | // 121 | // Unlike strcasecmp(), this function can handle NULL argument(s). 122 | // A NULL C string is considered different to any non-NULL C string, 123 | // including the empty string. 124 | static bool CaseInsensitiveCStringEquals(const char* lhs, 125 | const char* rhs); 126 | 127 | // Compares two wide C strings, ignoring case. Returns true iff they 128 | // have the same content. 129 | // 130 | // Unlike wcscasecmp(), this function can handle NULL argument(s). 131 | // A NULL C string is considered different to any non-NULL wide C string, 132 | // including the empty string. 133 | // NB: The implementations on different platforms slightly differ. 134 | // On windows, this method uses _wcsicmp which compares according to LC_CTYPE 135 | // environment variable. On GNU platform this method uses wcscasecmp 136 | // which compares according to LC_CTYPE category of the current locale. 137 | // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the 138 | // current locale. 139 | static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, 140 | const wchar_t* rhs); 141 | 142 | // Returns true iff the given string ends with the given suffix, ignoring 143 | // case. Any string is considered to end with an empty suffix. 144 | static bool EndsWithCaseInsensitive( 145 | const std::string& str, const std::string& suffix); 146 | 147 | // Formats an int value as "%02d". 148 | static std::string FormatIntWidth2(int value); // "%02d" for width == 2 149 | 150 | // Formats an int value as "%X". 151 | static std::string FormatHexInt(int value); 152 | 153 | // Formats a byte as "%02X". 154 | static std::string FormatByte(unsigned char value); 155 | 156 | private: 157 | String(); // Not meant to be instantiated. 158 | }; // class String 159 | 160 | // Gets the content of the stringstream's buffer as an std::string. Each '\0' 161 | // character in the buffer is replaced with "\\0". 162 | GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); 163 | 164 | } // namespace internal 165 | } // namespace testing 166 | 167 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 168 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | 3 | project(fpm) 4 | 5 | include(GNUInstallDirs) 6 | 7 | set(CMAKE_CXX_STANDARD 11) 8 | 9 | add_library(fpm INTERFACE) 10 | 11 | target_include_directories(fpm INTERFACE include) 12 | 13 | install(FILES 14 | include/fpm/fixed.hpp 15 | include/fpm/ios.hpp 16 | include/fpm/math.hpp 17 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fpm) 18 | 19 | OPTION(BUILD_ACCURACY "fpm accuracy" ON) 20 | OPTION(BUILD_BENCHMARK "fpm benchmark" ON) 21 | OPTION(BUILD_TESTS "fpm tests" ON) 22 | 23 | # only build tests & benchmarks if a top-level project 24 | if (NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 25 | set(BUILD_ACCURACY OFF) 26 | set(BUILD_BENCHMARK OFF) 27 | set(BUILD_TESTS OFF) 28 | endif() 29 | 30 | # 31 | # Test suite 32 | # 33 | if (BUILD_TESTS) 34 | enable_testing() 35 | include(GoogleTest) 36 | 37 | add_executable(fpm-test 38 | tests/arithmetic.cpp 39 | tests/arithmetic_int.cpp 40 | tests/basic_math.cpp 41 | tests/constants.cpp 42 | tests/conversion.cpp 43 | tests/classification.cpp 44 | tests/customizations.cpp 45 | tests/detail.cpp 46 | tests/input.cpp 47 | tests/manip.cpp 48 | tests/nearest.cpp 49 | tests/output.cpp 50 | tests/power.cpp 51 | tests/trigonometry.cpp 52 | ) 53 | set_target_properties(fpm-test PROPERTIES CXX_STANDARD 11) 54 | target_link_libraries(fpm-test PRIVATE fpm gtest_main) 55 | gtest_add_tests(TARGET fpm-test) 56 | 57 | endif() 58 | 59 | # 60 | # libfixmath for alternative comparison 61 | # 62 | include(ExternalProject) 63 | 64 | if (BUILD_ACCURACY OR BUILD_BENCHMARK) 65 | 66 | # Libfixmath uses a Makefile with hardcoded compiler (gcc). 67 | # So we need to define our own build rules. 68 | set(LIBFIXMATH_ROOT "${CMAKE_CURRENT_BINARY_DIR}/libfixmath") 69 | 70 | ExternalProject_Add(libfixmath-external 71 | GIT_REPOSITORY "https://github.com/PetteriAimonen/libfixmath.git" 72 | GIT_TAG bada934981a5961569ad2cb6b9006ed94542cc9c 73 | PREFIX ${LIBFIXMATH_ROOT} 74 | CONFIGURE_COMMAND "" 75 | BUILD_COMMAND "" 76 | INSTALL_COMMAND "" 77 | ) 78 | 79 | set(LIBFIXMATH_SOURCES 80 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16.c 81 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_exp.c 82 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_sqrt.c 83 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_str.c 84 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fix16_trig.c 85 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/fract32.c 86 | ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath/uint32.c 87 | ) 88 | set_source_files_properties(${LIBFIXMATH_SOURCES} PROPERTIES GENERATED TRUE) 89 | add_library(libfixmath ${LIBFIXMATH_SOURCES}) 90 | 91 | # Set libfixmath compile options to match fpm functionality 92 | target_compile_definitions(libfixmath 93 | PUBLIC 94 | FIXMATH_NO_CACHE # No caching of results 95 | 96 | #FIXMATH_NO_OVERFLOW # We want no runtime-overflow detection, but it fails to compile 97 | #FIXMATH_NO_ROUNDING # We do want rounding 98 | #FIXMATH_NO_64BIT # We do want 64-bit integer support 99 | #FIXMATH_OPTIMIZE_8BIT # No special 8-bit architecture optimizations 100 | #FIXMATH_SIN_LUT # No lookup table for sin 101 | #FIXMATH_FAST_SIN # Prefer accuracy over speed 102 | ) 103 | 104 | target_include_directories(libfixmath PUBLIC ${LIBFIXMATH_ROOT}/src/libfixmath-external/libfixmath) 105 | add_dependencies(libfixmath libfixmath-external) 106 | 107 | endif() 108 | 109 | if (BUILD_ACCURACY OR BUILD_BENCHMARK) 110 | # 111 | # CNL for alternative comparison 112 | # 113 | set(LIBCNL_ROOT "${CMAKE_CURRENT_BINARY_DIR}/libcnl") 114 | 115 | ExternalProject_Add(libcnl-external 116 | GIT_REPOSITORY "https://github.com/johnmcfarlane/cnl" 117 | GIT_TAG 4d445566fe7c6c8939fffc145a2f30fd587796a6 118 | PREFIX ${LIBCNL_ROOT} 119 | CONFIGURE_COMMAND "" 120 | BUILD_COMMAND "" 121 | INSTALL_COMMAND "" 122 | ) 123 | 124 | add_library(libcnl INTERFACE) 125 | target_include_directories(libcnl INTERFACE ${LIBCNL_ROOT}/src/libcnl-external/include) 126 | add_dependencies(libcnl libcnl-external) 127 | endif() 128 | 129 | if (BUILD_BENCHMARK) 130 | # 131 | # Benchmark tool. 132 | # Runs benchmarks of FPM operations and dumps results to standard output. 133 | # 134 | add_executable(fpm-benchmark 135 | benchmarks/arithmetic.cpp 136 | benchmarks/power.cpp 137 | benchmarks/trigonometry.cpp 138 | ) 139 | target_link_libraries(fpm-benchmark PRIVATE fpm libfixmath libcnl benchmark benchmark_main) 140 | endif() 141 | 142 | if (BUILD_ACCURACY) 143 | # 144 | # Accuracy tool. 145 | # Dumps the accuracy of approximated FPM functions to JSON files. 146 | # 147 | add_executable(fpm-accuracy 148 | accuracy/accuracy.cpp 149 | ) 150 | set_target_properties(fpm-accuracy PROPERTIES CXX_STANDARD 14) 151 | target_link_libraries(fpm-accuracy PRIVATE fpm libfixmath) 152 | endif() 153 | 154 | set(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}) 155 | 156 | include(FindGnuplot) 157 | if (GNUPLOT_FOUND AND BUILD_ACCURACY) 158 | # Create accuracy data 159 | set(DATA_FILES_ACCURACY "") 160 | set(IMG_FILES_ACCURACY "") 161 | foreach(DATA sin-trig cos-trig tan-trig asin-invtrig acos-invtrig atan-invtrig atan2-trig sqrt-auto cbrt-auto pow-auto exp-auto exp2-auto log-auto log2-auto log10-auto) 162 | string(REGEX MATCHALL "[^-]+" M ${DATA}) 163 | list(GET M 0 SERIES) 164 | list(GET M 1 TYPE) 165 | 166 | set(IMG_FILE ${DATA_DIR}/accuracy-${SERIES}.png) 167 | list(APPEND DATA_FILES_ACCURACY ${DATA_DIR}/${SERIES}.csv) 168 | list(APPEND IMG_FILES_ACCURACY ${IMG_FILE}) 169 | 170 | add_custom_command( 171 | OUTPUT ${IMG_FILE} 172 | COMMAND ${GNUPLOT_EXECUTABLE} -c ${PROJECT_SOURCE_DIR}/accuracy/accuracy.gnuplot ${SERIES} ${TYPE} 173 | DEPENDS ${DATA_DIR}/${SERIES}.csv accuracy/accuracy.gnuplot 174 | WORKING_DIRECTORY ${DATA_DIR} 175 | VERBATIM 176 | COMMENT "Plotting ${SERIES} accuracy data" 177 | ) 178 | endforeach(DATA) 179 | 180 | add_custom_command( 181 | OUTPUT ${DATA_FILES_ACCURACY} 182 | COMMAND fpm-accuracy 183 | DEPENDS fpm-accuracy 184 | WORKING_DIRECTORY ${DATA_DIR} 185 | VERBATIM 186 | COMMENT "Generating accuracy data with fpm-accuracy" 187 | ) 188 | 189 | add_custom_target(fpm-accuracy-images DEPENDS ${IMG_FILES_ACCURACY}) 190 | endif() 191 | 192 | if (CMAKE_BUILD_TYPE STREQUAL "Release" AND GNUPLOT_FOUND AND BUILD_BENCHMARK) 193 | # Enable the performance data-generation command only for Release builds. 194 | 195 | set(DATA_FILE_PERFORMANCE_JSON ${DATA_DIR}/performance.json) 196 | add_custom_command( 197 | OUTPUT ${DATA_FILE_PERFORMANCE_JSON} 198 | COMMAND fpm-benchmark --benchmark_out=${DATA_FILE_PERFORMANCE_JSON} --benchmark_out_format=json 199 | DEPENDS fpm-benchmark 200 | WORKING_DIRECTORY ${DATA_DIR} 201 | VERBATIM 202 | COMMENT "Generating performance data with fpm-benchmark" 203 | ) 204 | 205 | set(DATA_FILE_PERFORMANCE_GNUPLOT ${DATA_DIR}/performance.csv) 206 | add_custom_command( 207 | OUTPUT ${DATA_FILE_PERFORMANCE_GNUPLOT} 208 | COMMAND python ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.py ${DATA_FILE_PERFORMANCE_JSON} ${DATA_FILE_PERFORMANCE_GNUPLOT} 209 | DEPENDS ${DATA_FILE_PERFORMANCE_JSON} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.py 210 | WORKING_DIRECTORY ${DATA_DIR} 211 | VERBATIM 212 | COMMENT "Converting performance data for GnuPlot" 213 | ) 214 | 215 | set(IMG_FILE_PERFORMANCE "{$DATA_DIR}/performance.png") 216 | add_custom_command( 217 | OUTPUT ${IMG_FILE_PERFORMANCE} 218 | COMMAND ${GNUPLOT_EXECUTABLE} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.gnuplot 219 | DEPENDS ${DATA_FILE_PERFORMANCE_GNUPLOT} ${PROJECT_SOURCE_DIR}/benchmarks/benchmark.gnuplot 220 | WORKING_DIRECTORY ${DATA_DIR} 221 | VERBATIM 222 | COMMENT "Plotting performance data" 223 | ) 224 | 225 | add_custom_target(fpm-performance-images DEPENDS ${IMG_FILE_PERFORMANCE}) 226 | endif() 227 | 228 | if (BUILD_BENCHMARK) 229 | add_subdirectory(3rdparty/googlebench) 230 | endif() 231 | 232 | if (BUILD_TESTS) 233 | add_subdirectory(3rdparty/googletest) 234 | endif() 235 | --------------------------------------------------------------------------------