Path: blob/master/tests/core/math/test_math_funcs.cpp
23450 views
/**************************************************************************/1/* test_math_funcs.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "core/math/math_funcs_binary.h"31#include "tests/test_macros.h"3233TEST_FORCE_LINK(test_math_funcs)3435namespace TestMathFuncs {3637TEST_CASE("[Math] C++ macros") {38CHECK(MIN(-2, 2) == -2);39CHECK(MIN(600, 2) == 2);4041CHECK(MAX(-2, 2) == 2);42CHECK(MAX(600, 2) == 600);4344CHECK(CLAMP(600, -2, 2) == 2);45CHECK(CLAMP(620, 600, 650) == 620);46// `max` is lower than `min`.47CHECK(CLAMP(620, 600, 50) == 50);4849CHECK(Math::abs(-5) == 5);50CHECK(Math::abs(0) == 0);51CHECK(Math::abs(5) == 5);5253CHECK(SIGN(-5) == -1.0);54CHECK(SIGN(0) == 0.0);55CHECK(SIGN(5) == 1.0);56// Check that SIGN(Math::NaN) returns 0.0.57CHECK(SIGN(Math::NaN) == 0.0);58}5960TEST_CASE("[Math] Power of two functions") {61CHECK(Math::next_power_of_2((uint32_t)0) == 0);62CHECK(Math::next_power_of_2((uint32_t)1) == 1);63CHECK(Math::next_power_of_2((uint32_t)16) == 16);64CHECK(Math::next_power_of_2((uint32_t)17) == 32);65CHECK(Math::next_power_of_2((uint32_t)65535) == 65536);6667CHECK(Math::previous_power_of_2((uint32_t)0) == 0);68CHECK(Math::previous_power_of_2((uint32_t)1) == 1);69CHECK(Math::previous_power_of_2((uint32_t)16) == 16);70CHECK(Math::previous_power_of_2((uint32_t)17) == 16);71CHECK(Math::previous_power_of_2((uint32_t)65535) == 32768);7273CHECK(Math::closest_power_of_2((uint32_t)0) == 0);74CHECK(Math::closest_power_of_2((uint32_t)1) == 1);75CHECK(Math::closest_power_of_2((uint32_t)16) == 16);76CHECK(Math::closest_power_of_2((uint32_t)17) == 16);77CHECK(Math::closest_power_of_2((uint32_t)65535) == 65536);7879CHECK(Math::get_shift_from_power_of_2((uint32_t)0) == -1);80CHECK(Math::get_shift_from_power_of_2((uint32_t)1) == 0);81CHECK(Math::get_shift_from_power_of_2((uint32_t)16) == 4);82CHECK(Math::get_shift_from_power_of_2((uint32_t)17) == -1);83CHECK(Math::get_shift_from_power_of_2((uint32_t)65535) == -1);8485CHECK(Math::nearest_shift((uint32_t)0) == 0);86CHECK(Math::nearest_shift((uint32_t)1) == 1);87CHECK(Math::nearest_shift((uint32_t)16) == 5);88CHECK(Math::nearest_shift((uint32_t)17) == 5);89CHECK(Math::nearest_shift((uint32_t)65535) == 16);90}9192TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) {93CHECK(Math::abs((T)-1) == (T)1);94CHECK(Math::abs((T)0) == (T)0);95CHECK(Math::abs((T)1) == (T)1);96CHECK(Math::abs((T)0.1) == (T)0.1);97}9899TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) {100CHECK(Math::round((T)1.5) == (T)2.0);101CHECK(Math::round((T)1.6) == (T)2.0);102CHECK(Math::round((T)-1.5) == (T)-2.0);103CHECK(Math::round((T)-1.1) == (T)-1.0);104105CHECK(Math::floor((T)1.5) == (T)1.0);106CHECK(Math::floor((T)-1.5) == (T)-2.0);107108CHECK(Math::ceil((T)1.5) == (T)2.0);109CHECK(Math::ceil((T)-1.9) == (T)-1.0);110}111112TEST_CASE_TEMPLATE("[Math] integer division round up unsigned", T, uint32_t, uint64_t) {113CHECK(Math::division_round_up((T)0, (T)64) == 0);114CHECK(Math::division_round_up((T)1, (T)64) == 1);115CHECK(Math::division_round_up((T)63, (T)64) == 1);116CHECK(Math::division_round_up((T)64, (T)64) == 1);117CHECK(Math::division_round_up((T)65, (T)64) == 2);118CHECK(Math::division_round_up((T)65, (T)1) == 65);119}120121TEST_CASE_TEMPLATE("[Math] integer division round up signed", T, int32_t, int64_t) {122CHECK(Math::division_round_up((T)0, (T)64) == 0);123CHECK(Math::division_round_up((T)1, (T)64) == 1);124CHECK(Math::division_round_up((T)63, (T)64) == 1);125CHECK(Math::division_round_up((T)64, (T)64) == 1);126CHECK(Math::division_round_up((T)65, (T)64) == 2);127CHECK(Math::division_round_up((T)65, (T)1) == 65);128CHECK(Math::division_round_up((T)-1, (T)64) == 0);129CHECK(Math::division_round_up((T)-1, (T)-1) == 1);130CHECK(Math::division_round_up((T)-1, (T)1) == -1);131CHECK(Math::division_round_up((T)-1, (T)-2) == 1);132CHECK(Math::division_round_up((T)-4, (T)-2) == 2);133}134135TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) {136CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166));137CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166));138CHECK(Math::sin((T)0.5) == doctest::Approx((T)0.4794255386));139CHECK(Math::sin((T)1.0) == doctest::Approx((T)0.8414709848));140CHECK(Math::sin((T)1.5) == doctest::Approx((T)0.9974949866));141CHECK(Math::sin((T)450.0) == doctest::Approx((T)-0.683283725));142143CHECK(Math::cos((T)-0.1) == doctest::Approx((T)0.99500416530));144CHECK(Math::cos((T)0.1) == doctest::Approx((T)0.9950041653));145CHECK(Math::cos((T)0.5) == doctest::Approx((T)0.8775825619));146CHECK(Math::cos((T)1.0) == doctest::Approx((T)0.5403023059));147CHECK(Math::cos((T)1.5) == doctest::Approx((T)0.0707372017));148CHECK(Math::cos((T)450.0) == doctest::Approx((T)-0.7301529642));149150CHECK(Math::tan((T)-0.1) == doctest::Approx((T)-0.1003346721));151CHECK(Math::tan((T)0.1) == doctest::Approx((T)0.1003346721));152CHECK(Math::tan((T)0.5) == doctest::Approx((T)0.5463024898));153CHECK(Math::tan((T)1.0) == doctest::Approx((T)1.5574077247));154CHECK(Math::tan((T)1.5) == doctest::Approx((T)14.1014199472));155CHECK(Math::tan((T)450.0) == doctest::Approx((T)0.9358090134));156}157158TEST_CASE_TEMPLATE("[Math] sinh/cosh/tanh", T, float, double) {159CHECK(Math::sinh((T)-0.1) == doctest::Approx((T)-0.10016675));160CHECK(Math::sinh((T)0.1) == doctest::Approx((T)0.10016675));161CHECK(Math::sinh((T)0.5) == doctest::Approx((T)0.5210953055));162CHECK(Math::sinh((T)1.0) == doctest::Approx((T)1.1752011936));163CHECK(Math::sinh((T)1.5) == doctest::Approx((T)2.1292794551));164165CHECK(Math::cosh((T)-0.1) == doctest::Approx((T)1.0050041681));166CHECK(Math::cosh((T)0.1) == doctest::Approx((T)1.0050041681));167CHECK(Math::cosh((T)0.5) == doctest::Approx((T)1.1276259652));168CHECK(Math::cosh((T)1.0) == doctest::Approx((T)1.5430806348));169CHECK(Math::cosh((T)1.5) == doctest::Approx((T)2.3524096152));170171CHECK(Math::tanh((T)-0.1) == doctest::Approx((T)-0.0996679946));172CHECK(Math::tanh((T)0.1) == doctest::Approx((T)0.0996679946));173CHECK(Math::tanh((T)0.5) == doctest::Approx((T)0.4621171573));174CHECK(Math::tanh((T)1.0) == doctest::Approx((T)0.761594156));175CHECK(Math::tanh((T)1.5) == doctest::Approx((T)0.9051482536));176CHECK(Math::tanh((T)450.0) == doctest::Approx((T)1.0));177}178179TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {180CHECK(Math::asin((T)-0.1) == doctest::Approx((T)-0.1001674212));181CHECK(Math::asin((T)0.1) == doctest::Approx((T)0.1001674212));182CHECK(Math::asin((T)0.5) == doctest::Approx((T)0.5235987756));183CHECK(Math::asin((T)1.0) == doctest::Approx((T)1.5707963268));184CHECK(Math::asin((T)2.0) == doctest::Approx((T)1.5707963268));185CHECK(Math::asin((T)-2.0) == doctest::Approx((T)-1.5707963268));186187CHECK(Math::acos((T)-0.1) == doctest::Approx((T)1.670963748));188CHECK(Math::acos((T)0.1) == doctest::Approx((T)1.4706289056));189CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512));190CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0));191CHECK(Math::acos((T)2.0) == doctest::Approx((T)0.0));192CHECK(Math::acos((T)-2.0) == doctest::Approx((T)Math::PI));193194CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525));195CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525));196CHECK(Math::atan((T)0.5) == doctest::Approx((T)0.463647609));197CHECK(Math::atan((T)1.0) == doctest::Approx((T)0.7853981634));198CHECK(Math::atan((T)1.5) == doctest::Approx((T)0.9827937232));199CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082));200}201202TEST_CASE_TEMPLATE("[Math] asinh/acosh/atanh", T, float, double) {203CHECK(Math::asinh((T)-2.0) == doctest::Approx((T)-1.4436354751));204CHECK(Math::asinh((T)-0.1) == doctest::Approx((T)-0.0998340788));205CHECK(Math::asinh((T)0.1) == doctest::Approx((T)0.0998340788));206CHECK(Math::asinh((T)0.5) == doctest::Approx((T)0.4812118250));207CHECK(Math::asinh((T)1.0) == doctest::Approx((T)0.8813735870));208CHECK(Math::asinh((T)2.0) == doctest::Approx((T)1.4436354751));209210CHECK(Math::acosh((T)-2.0) == doctest::Approx((T)0.0));211CHECK(Math::acosh((T)-0.1) == doctest::Approx((T)0.0));212CHECK(Math::acosh((T)0.1) == doctest::Approx((T)0.0));213CHECK(Math::acosh((T)0.5) == doctest::Approx((T)0.0));214CHECK(Math::acosh((T)1.0) == doctest::Approx((T)0.0));215CHECK(Math::acosh((T)2.0) == doctest::Approx((T)1.3169578969));216CHECK(Math::acosh((T)450.0) == doctest::Approx((T)6.8023935287));217218CHECK(Math::is_inf(Math::atanh((T)-2.0)));219CHECK(Math::atanh((T)-2.0) < (T)0.0);220CHECK(Math::is_inf(Math::atanh((T)-1.0)));221CHECK(Math::atanh((T)-1.0) < (T)0.0);222CHECK(Math::atanh((T)-0.1) == doctest::Approx((T)-0.1003353477));223CHECK(Math::atanh((T)0.1) == doctest::Approx((T)0.1003353477));224CHECK(Math::atanh((T)0.5) == doctest::Approx((T)0.5493061443));225CHECK(Math::is_inf(Math::atanh((T)1.0)));226CHECK(Math::atanh((T)1.0) > (T)0.0);227CHECK(Math::is_inf(Math::atanh((T)1.5)));228CHECK(Math::atanh((T)1.5) > (T)0.0);229CHECK(Math::is_inf(Math::atanh((T)450.0)));230CHECK(Math::atanh((T)450.0) > (T)0.0);231}232233TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) {234CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665));235CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665));236CHECK(Math::sinc((T)0.5) == doctest::Approx((T)0.9588510772));237CHECK(Math::sinc((T)1.0) == doctest::Approx((T)0.8414709848));238CHECK(Math::sinc((T)1.5) == doctest::Approx((T)0.6649966577));239CHECK(Math::sinc((T)450.0) == doctest::Approx((T)-0.0015184083));240241CHECK(Math::sincn((T)-0.1) == doctest::Approx((T)0.9836316431));242CHECK(Math::sincn((T)0.1) == doctest::Approx((T)0.9836316431));243CHECK(Math::sincn((T)0.5) == doctest::Approx((T)0.6366197724));244CHECK(Math::sincn((T)1.0) == doctest::Approx((T)0.0));245CHECK(Math::sincn((T)1.5) == doctest::Approx((T)-0.2122065908));246CHECK(Math::sincn((T)450.0) == doctest::Approx((T)0.0));247248CHECK(Math::atan2((T)-0.1, (T)0.5) == doctest::Approx((T)-0.1973955598));249CHECK(Math::atan2((T)0.1, (T)-0.5) == doctest::Approx((T)2.9441970937));250CHECK(Math::atan2((T)0.5, (T)1.5) == doctest::Approx((T)0.3217505544));251CHECK(Math::atan2((T)1.0, (T)2.5) == doctest::Approx((T)0.3805063771));252CHECK(Math::atan2((T)1.5, (T)1.0) == doctest::Approx((T)0.9827937232));253CHECK(Math::atan2((T)450.0, (T)1.0) == doctest::Approx((T)1.5685741082));254}255256TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) {257CHECK(Math::pow((T)-0.1, (T)2.0) == doctest::Approx((T)0.01));258CHECK(Math::pow((T)0.1, (T)2.5) == doctest::Approx((T)0.0031622777));259CHECK(Math::pow((T)0.5, (T)0.5) == doctest::Approx((T)0.7071067812));260CHECK(Math::pow((T)1.0, (T)1.0) == doctest::Approx((T)1.0));261CHECK(Math::pow((T)1.5, (T)-1.0) == doctest::Approx((T)0.6666666667));262CHECK(Math::pow((T)450.0, (T)-2.0) == doctest::Approx((T)0.0000049383));263CHECK(Math::pow((T)450.0, (T)0.0) == doctest::Approx((T)1.0));264265CHECK(Math::is_nan(Math::log((T)-0.1)));266CHECK(Math::log((T)0.1) == doctest::Approx((T)-2.302585093));267CHECK(Math::log((T)0.5) == doctest::Approx((T)-0.6931471806));268CHECK(Math::log((T)1.0) == doctest::Approx((T)0.0));269CHECK(Math::log((T)1.5) == doctest::Approx((T)0.4054651081));270CHECK(Math::log((T)450.0) == doctest::Approx((T)6.1092475828));271272CHECK(Math::is_nan(Math::log2((T)-0.1)));273CHECK(Math::log2((T)0.1) == doctest::Approx((T)-3.3219280949));274CHECK(Math::log2((T)0.5) == doctest::Approx((T)-1.0));275CHECK(Math::log2((T)1.0) == doctest::Approx((T)0.0));276CHECK(Math::log2((T)1.5) == doctest::Approx((T)0.5849625007));277CHECK(Math::log2((T)450.0) == doctest::Approx((T)8.8137811912));278279CHECK(Math::exp((T)-0.1) == doctest::Approx((T)0.904837418));280CHECK(Math::exp((T)0.1) == doctest::Approx((T)1.1051709181));281CHECK(Math::exp((T)0.5) == doctest::Approx((T)1.6487212707));282CHECK(Math::exp((T)1.0) == doctest::Approx((T)2.7182818285));283CHECK(Math::exp((T)1.5) == doctest::Approx((T)4.4816890703));284285CHECK(Math::is_nan(Math::sqrt((T)-0.1)));286CHECK(Math::sqrt((T)0.1) == doctest::Approx((T)0.316228));287CHECK(Math::sqrt((T)0.5) == doctest::Approx((T)0.707107));288CHECK(Math::sqrt((T)1.0) == doctest::Approx((T)1.0));289CHECK(Math::sqrt((T)1.5) == doctest::Approx((T)1.224745));290}291292TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) {293CHECK(!Math::is_nan((T)0.0));294CHECK(Math::is_nan((T)Math::NaN));295296CHECK(!Math::is_inf((T)0.0));297CHECK(Math::is_inf((T)Math::INF));298}299300TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) {301CHECK(Math::linear_to_db((T)1.0) == doctest::Approx((T)0.0));302CHECK(Math::linear_to_db((T)20.0) == doctest::Approx((T)26.0206));303CHECK(Math::is_inf(Math::linear_to_db((T)0.0)));304CHECK(Math::is_nan(Math::linear_to_db((T)-20.0)));305}306307TEST_CASE_TEMPLATE("[Math] db_to_linear", T, float, double) {308CHECK(Math::db_to_linear((T)0.0) == doctest::Approx((T)1.0));309CHECK(Math::db_to_linear((T)1.0) == doctest::Approx((T)1.122018));310CHECK(Math::db_to_linear((T)20.0) == doctest::Approx((T)10.0));311CHECK(Math::db_to_linear((T)-20.0) == doctest::Approx((T)0.1));312}313314TEST_CASE_TEMPLATE("[Math] step_decimals", T, float, double) {315CHECK(Math::step_decimals((T)-0.5) == 1);316CHECK(Math::step_decimals((T)0) == 0);317CHECK(Math::step_decimals((T)1) == 0);318CHECK(Math::step_decimals((T)0.1) == 1);319CHECK(Math::step_decimals((T)0.01) == 2);320CHECK(Math::step_decimals((T)0.001) == 3);321CHECK(Math::step_decimals((T)0.0001) == 4);322CHECK(Math::step_decimals((T)0.00001) == 5);323CHECK(Math::step_decimals((T)0.000001) == 6);324CHECK(Math::step_decimals((T)0.0000001) == 7);325CHECK(Math::step_decimals((T)0.00000001) == 8);326CHECK(Math::step_decimals((T)0.000000001) == 9);327// Too many decimals to handle.328CHECK(Math::step_decimals((T)0.0000000001) == 0);329}330331TEST_CASE_TEMPLATE("[Math] range_step_decimals", T, float, double) {332CHECK(Math::range_step_decimals((T)0.000000001) == 9);333// Too many decimals to handle.334CHECK(Math::range_step_decimals((T)0.0000000001) == 0);335// Should be treated as a step of 0 for use by the editor.336CHECK(Math::range_step_decimals((T)0.0) == 16);337CHECK(Math::range_step_decimals((T)-0.5) == 16);338}339340TEST_CASE_TEMPLATE("[Math] lerp", T, float, double) {341CHECK(Math::lerp((T)2.0, (T)5.0, (T)-0.1) == doctest::Approx((T)1.7));342CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.0) == doctest::Approx((T)2.0));343CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.1) == doctest::Approx((T)2.3));344CHECK(Math::lerp((T)2.0, (T)5.0, (T)1.0) == doctest::Approx((T)5.0));345CHECK(Math::lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)8.0));346347CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)-0.1) == doctest::Approx((T)-1.7));348CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.0) == doctest::Approx((T)-2.0));349CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.1) == doctest::Approx((T)-2.3));350CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)1.0) == doctest::Approx((T)-5.0));351CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)2.0) == doctest::Approx((T)-8.0));352}353354TEST_CASE_TEMPLATE("[Math] inverse_lerp", T, float, double) {355CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)1.7) == doctest::Approx((T)-0.1));356CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)0.0));357CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.3) == doctest::Approx((T)0.1));358CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)5.0) == doctest::Approx((T)1.0));359CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)8.0) == doctest::Approx((T)2.0));360361CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-1.7) == doctest::Approx((T)-0.1));362CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.0) == doctest::Approx((T)0.0));363CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.3) == doctest::Approx((T)0.1));364CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-5.0) == doctest::Approx((T)1.0));365CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-8.0) == doctest::Approx((T)2.0));366}367368TEST_CASE_TEMPLATE("[Math] remap", T, float, double) {369CHECK(Math::remap((T)50.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));370CHECK(Math::remap((T)100.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));371CHECK(Math::remap((T)200.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));372CHECK(Math::remap((T)250.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));373374CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));375CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));376CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));377CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));378379CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)500.0));380CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)0.0));381CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1000.0));382CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0));383384// Note: undefined behavior can happen when `p_istart == p_istop`. We don't bother testing this as it will385// vary between hardware and compilers properly implementing IEEE 754.386}387388TEST_CASE_TEMPLATE("[Math] angle_difference", T, float, double) {389// Loops around, should return 0.0.390CHECK(Math::angle_difference((T)0.0, (T)Math::TAU) == doctest::Approx((T)0.0));391CHECK(Math::angle_difference((T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));392CHECK(Math::angle_difference((T)0.0, (T)Math::TAU * (T)4.0) == doctest::Approx((T)0.0));393394// Rotation is clockwise, so it should return -PI.395CHECK(Math::angle_difference((T)0.0, (T)Math::PI) == doctest::Approx((T)-Math::PI));396CHECK(Math::angle_difference((T)0.0, (T)-Math::PI) == doctest::Approx((T)Math::PI));397CHECK(Math::angle_difference((T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI));398CHECK(Math::angle_difference((T)-Math::PI, (T)0.0) == doctest::Approx((T)-Math::PI));399400CHECK(Math::angle_difference((T)0.0, (T)3.0) == doctest::Approx((T)3.0));401CHECK(Math::angle_difference((T)1.0, (T)-2.0) == doctest::Approx((T)-3.0));402CHECK(Math::angle_difference((T)-1.0, (T)2.0) == doctest::Approx((T)3.0));403CHECK(Math::angle_difference((T)-2.0, (T)-4.5) == doctest::Approx((T)-2.5));404CHECK(Math::angle_difference((T)100.0, (T)102.5) == doctest::Approx((T)2.5));405}406407TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) {408// Counter-clockwise rotation.409CHECK(Math::lerp_angle((T)0.24 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)-0.005 * Math::TAU));410// Counter-clockwise rotation.411CHECK(Math::lerp_angle((T)0.25 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.0));412// Clockwise rotation.413CHECK(Math::lerp_angle((T)0.26 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.505 * Math::TAU));414415CHECK(Math::lerp_angle((T)-0.25 * Math::TAU, 1.25 * Math::TAU, 0.5) == doctest::Approx((T)-0.5 * Math::TAU));416CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 0.96) == doctest::Approx((T)0.4512 * Math::TAU));417CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 1.04) == doctest::Approx((T)0.4288 * Math::TAU));418419// Initial and final angles are effectively identical, so the value returned420// should always be the same regardless of the `weight` parameter.421CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, -1.0) == doctest::Approx((T)-4.0 * Math::TAU));422CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.0) == doctest::Approx((T)-4.0 * Math::TAU));423CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.5) == doctest::Approx((T)-4.0 * Math::TAU));424CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 1.0) == doctest::Approx((T)-4.0 * Math::TAU));425CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 500.0) == doctest::Approx((T)-4.0 * Math::TAU));426}427428TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {429CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx((T)1.0));430CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx((T)4.5));431CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx((T)5.0));432CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx((T)-1.0));433CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx((T)-4.5));434CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0));435}436437TEST_CASE_TEMPLATE("[Math] rotate_toward", T, float, double) {438// Rotate toward.439CHECK(Math::rotate_toward((T)0.0, (T)Math::PI * (T)0.75, (T)1.5) == doctest::Approx((T)1.5));440CHECK(Math::rotate_toward((T)-2.0, (T)1.0, (T)2.5) == doctest::Approx((T)0.5));441CHECK(Math::rotate_toward((T)-2.0, (T)Math::PI, (T)Math::PI) == doctest::Approx((T)-Math::PI));442CHECK(Math::rotate_toward((T)1.0, (T)Math::PI, (T)20.0) == doctest::Approx((T)Math::PI));443444// Rotate away.445CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-1.5) == doctest::Approx((T)-1.5));446CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-Math::PI) == doctest::Approx((T)-Math::PI));447CHECK(Math::rotate_toward((T)3.0, (T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));448CHECK(Math::rotate_toward((T)2.0, (T)Math::PI, (T)-1.5) == doctest::Approx((T)0.5));449CHECK(Math::rotate_toward((T)1.0, (T)2.0, (T)-0.5) == doctest::Approx((T)0.5));450CHECK(Math::rotate_toward((T)2.5, (T)2.0, (T)-0.5) == doctest::Approx((T)3.0));451CHECK(Math::rotate_toward((T)-1.0, (T)1.0, (T)-1.0) == doctest::Approx((T)-2.0));452}453454TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) {455CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0));456CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625));457CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)1.0) == doctest::Approx((T)0.5));458CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)2.0) == doctest::Approx((T)1.0));459}460461TEST_CASE("[Math] ease") {462CHECK(Math::ease(0.1, 1.0) == doctest::Approx(0.1));463CHECK(Math::ease(0.1, 2.0) == doctest::Approx(0.01));464CHECK(Math::ease(0.1, 0.5) == doctest::Approx(0.19));465CHECK(Math::ease(0.1, 0.0) == doctest::Approx(0));466CHECK(Math::ease(0.1, -0.5) == doctest::Approx(0.2236067977));467CHECK(Math::ease(0.1, -1.0) == doctest::Approx(0.1));468CHECK(Math::ease(0.1, -2.0) == doctest::Approx(0.02));469470CHECK(Math::ease(-1.0, 1.0) == doctest::Approx(0));471CHECK(Math::ease(-1.0, 2.0) == doctest::Approx(0));472CHECK(Math::ease(-1.0, 0.5) == doctest::Approx(0));473CHECK(Math::ease(-1.0, 0.0) == doctest::Approx(0));474CHECK(Math::ease(-1.0, -0.5) == doctest::Approx(0));475CHECK(Math::ease(-1.0, -1.0) == doctest::Approx(0));476CHECK(Math::ease(-1.0, -2.0) == doctest::Approx(0));477}478479TEST_CASE("[Math] snapped") {480CHECK(Math::snapped(0.5, 0.04) == doctest::Approx(0.52));481CHECK(Math::snapped(-0.5, 0.04) == doctest::Approx(-0.48));482CHECK(Math::snapped(0.0, 0.04) == doctest::Approx(0));483CHECK(Math::snapped(128'000.025, 0.04) == doctest::Approx(128'000.04));484485CHECK(Math::snapped(0.5, 400) == doctest::Approx(0));486CHECK(Math::snapped(-0.5, 400) == doctest::Approx(0));487CHECK(Math::snapped(0.0, 400) == doctest::Approx(0));488CHECK(Math::snapped(128'000.025, 400) == doctest::Approx(128'000.0));489490CHECK(Math::snapped(0.5, 0.0) == doctest::Approx(0.5));491CHECK(Math::snapped(-0.5, 0.0) == doctest::Approx(-0.5));492CHECK(Math::snapped(0.0, 0.0) == doctest::Approx(0.0));493CHECK(Math::snapped(128'000.025, 0.0) == doctest::Approx(128'000.0));494495CHECK(Math::snapped(0.5, -1.0) == doctest::Approx(0));496CHECK(Math::snapped(-0.5, -1.0) == doctest::Approx(-1.0));497CHECK(Math::snapped(0.0, -1.0) == doctest::Approx(0));498CHECK(Math::snapped(128'000.025, -1.0) == doctest::Approx(128'000.0));499}500501TEST_CASE("[Math] larger_prime") {502CHECK(Math::larger_prime(0) == 5);503CHECK(Math::larger_prime(1) == 5);504CHECK(Math::larger_prime(2) == 5);505CHECK(Math::larger_prime(5) == 13);506CHECK(Math::larger_prime(500) == 769);507CHECK(Math::larger_prime(1'000'000) == 1'572'869);508CHECK(Math::larger_prime(1'000'000'000) == 1'610'612'741);509510// The next prime is larger than `INT32_MAX` and is not present in the built-in prime table.511ERR_PRINT_OFF;512CHECK(Math::larger_prime(2'000'000'000) == 0);513ERR_PRINT_ON;514}515516TEST_CASE_TEMPLATE("[Math] fmod", T, float, double) {517CHECK(Math::fmod((T)-2.0, (T)0.3) == doctest::Approx((T)-0.2));518CHECK(Math::fmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));519CHECK(Math::fmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));520521CHECK(Math::fmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));522CHECK(Math::fmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));523CHECK(Math::fmod((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));524}525526TEST_CASE_TEMPLATE("[Math] fposmod", T, float, double) {527CHECK(Math::fposmod((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));528CHECK(Math::fposmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));529CHECK(Math::fposmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));530531CHECK(Math::fposmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));532CHECK(Math::fposmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));533CHECK(Math::fposmod((T)2.0, (T)-0.3) == doctest::Approx((T)-0.1));534}535536TEST_CASE_TEMPLATE("[Math] fposmodp", T, float, double) {537CHECK(Math::fposmodp((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));538CHECK(Math::fposmodp((T)0.0, (T)0.3) == doctest::Approx((T)0.0));539CHECK(Math::fposmodp((T)2.0, (T)0.3) == doctest::Approx((T)0.2));540541CHECK(Math::fposmodp((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.5));542CHECK(Math::fposmodp((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));543CHECK(Math::fposmodp((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));544}545546TEST_CASE("[Math] posmod") {547CHECK(Math::posmod(-20, 3) == 1);548CHECK(Math::posmod(0, 3) == 0);549CHECK(Math::posmod(20, 3) == 2);550CHECK(Math::posmod(-20, -3) == -2);551CHECK(Math::posmod(0, -3) == 0);552CHECK(Math::posmod(20, -3) == -1);553}554555TEST_CASE("[Math] wrapi") {556CHECK(Math::wrapi(-30, -20, 160) == 150);557CHECK(Math::wrapi(30, -20, 160) == 30);558CHECK(Math::wrapi(300, -20, 160) == 120);559CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120);560}561562TEST_CASE_TEMPLATE("[Math] wrapf", T, float, double) {563CHECK(Math::wrapf((T)-30.0, (T)-20.0, (T)160.0) == doctest::Approx((T)150.0));564CHECK(Math::wrapf((T)30.0, (T)-2.0, (T)160.0) == doctest::Approx((T)30.0));565CHECK(Math::wrapf((T)300.0, (T)-20.0, (T)160.0) == doctest::Approx((T)120.0));566567CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx((T)120.0));568// float's precision is too low for 300'000'000'000.0, so we reduce it by a factor of 1000.569CHECK(Math::wrapf((float)15'000'000.0, (float)-20.0, (float)160.0) == doctest::Approx((T)60.0));570}571572TEST_CASE_TEMPLATE("[Math] fract", T, float, double) {573CHECK(Math::fract((T)1.0) == doctest::Approx((T)0.0));574CHECK(Math::fract((T)77.8) == doctest::Approx((T)0.8));575CHECK(Math::fract((T)-10.1) == doctest::Approx((T)0.9));576}577578TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) {579CHECK(Math::pingpong((T)0.0, (T)0.0) == doctest::Approx((T)0.0));580CHECK(Math::pingpong((T)1.0, (T)1.0) == doctest::Approx((T)1.0));581CHECK(Math::pingpong((T)0.5, (T)2.0) == doctest::Approx((T)0.5));582CHECK(Math::pingpong((T)3.5, (T)2.0) == doctest::Approx((T)0.5));583CHECK(Math::pingpong((T)11.5, (T)2.0) == doctest::Approx((T)0.5));584CHECK(Math::pingpong((T)-2.5, (T)2.0) == doctest::Approx((T)1.5));585}586587TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) {588CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math::PI));589CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239));590591CHECK(Math::rad_to_deg((T)Math::PI) == doctest::Approx((T)180.0));592CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927));593}594595TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) {596CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0) == doctest::Approx((T)0.2));597CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25) == doctest::Approx((T)0.33125));598CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));599CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75) == doctest::Approx((T)0.66875));600CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0) == doctest::Approx((T)0.8));601602CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-50.0) == doctest::Approx((T)-6662732.3));603CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-5.0) == doctest::Approx((T)-9356.3));604CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)0.0) == doctest::Approx((T)20.2));605CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)1.0) == doctest::Approx((T)30.1));606CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)4.0) == doctest::Approx((T)1853.2));607}608609TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) {610CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI * (1.0 / 6.0)));611CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25) == doctest::Approx((T)0.973566));612CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5) == doctest::Approx((T)Math::PI / 2.0));613CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75) == doctest::Approx((T)2.16803));614CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));615}616617TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {618CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));619CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.1625));620CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.4));621CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.6375));622CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.8));623}624625TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) {626CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));627CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));628CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));629CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));630CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));631}632633TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {634CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.0) == doctest::Approx((T)0.0));635CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.25) == doctest::Approx((T)0.2125));636CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));637CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.75) == doctest::Approx((T)0.7875));638CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)1.0) == doctest::Approx((T)1.0));639}640641} // namespace TestMathFuncs642643644