diff --git a/CMakeLists.txt b/CMakeLists.txt index 57a2e32..4223199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,12 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) endif() if(MSVC) - add_compile_options(/W4 /clang:-Wno-character-conversion /clang:-Wno-error=character-conversion) + add_compile_options(/W4) + + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + add_compile_options(/clang:-Wno-character-conversion /clang:-Wno-error=character-conversion) + else() + endif() else() set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(CMAKE_HAVE_THREADS_LIBRARY 1) diff --git a/CMakePresets.json b/CMakePresets.json index 5927804..20d5532 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -23,6 +23,7 @@ "lhs": "${hostSystemName}", "rhs": "Windows" }, + "generator": "Visual Studio 18 2026", "cacheVariables": { "CMAKE_C_COMPILER": "cl", "CMAKE_CXX_COMPILER": "cl" diff --git a/Source/CTF/ctf/Algorithm.cpp b/Source/CTF/ctf/Algorithm.cpp index a16119a..0ed2df6 100644 --- a/Source/CTF/ctf/Algorithm.cpp +++ b/Source/CTF/ctf/Algorithm.cpp @@ -22,6 +22,11 @@ #include "Algorithm.h" namespace CTF { + template + CTF_CONSTEXPR T Abs(T x) { + return (x < 0) ? -x : x; + } + template CTF_CONSTEXPR T Min(T a, T b) { return b < a ? b : a; diff --git a/Source/CTF/ctf/Algorithm.h b/Source/CTF/ctf/Algorithm.h index f29888a..d20d313 100644 --- a/Source/CTF/ctf/Algorithm.h +++ b/Source/CTF/ctf/Algorithm.h @@ -22,10 +22,11 @@ #define ALGORITHM_H #pragma once - - namespace CTF { + template + CTF_API CTF_CONSTEXPR T Abs(T x); + template CTF_API CTF_CONSTEXPR T Max(T a, T b); diff --git a/Source/CTF/ctf/BasicString.h b/Source/CTF/ctf/BasicString.h index 4b72854..0c99052 100644 --- a/Source/CTF/ctf/BasicString.h +++ b/Source/CTF/ctf/BasicString.h @@ -31,7 +31,7 @@ namespace CTF { * @brief Just a simple basic string class. */ template -class BasicString { +class CTF_API BasicString { public: /** * @brief Initializes an empty string. diff --git a/Source/CTF/ctf/CMakeLists.txt b/Source/CTF/ctf/CMakeLists.txt index 1a94ac6..33c6a0d 100644 --- a/Source/CTF/ctf/CMakeLists.txt +++ b/Source/CTF/ctf/CMakeLists.txt @@ -46,6 +46,12 @@ set(SOURCES "Logging/LogListener.cpp" "Logging/LogListener.h" + # mathematics + "Math/Logarithms.h" + "Math/Power.h" + "Math/Rounding.h" + "Math/Trigonometry.h" + # string #"String.inl" "BasicString.h" @@ -107,6 +113,8 @@ set(SOURCES "PipeStream.h" # memory management + "LinearArena.cpp" + "LinearArena.h" "Memory.cpp" "Memory.h" "RefCounted.cpp" diff --git a/Source/CTF/ctf/Collections/Hash.cpp b/Source/CTF/ctf/Collections/Hash.cpp index fd0ed11..fa16f82 100644 --- a/Source/CTF/ctf/Collections/Hash.cpp +++ b/Source/CTF/ctf/Collections/Hash.cpp @@ -22,20 +22,20 @@ namespace CTF::Collections { -template int Hash::operator()(const T &key) const { - const unsigned char *data = reinterpret_cast(&key); - int Hash = 0; - for (int i = 0; i < sizeof(T); ++i) - Hash = Hash * 131 + data[i]; - return Hash; -} + template int Hash::operator()(const T &key) const { + const unsigned char *data = reinterpret_cast(&key); + int Hash = 0; + for (int i = 0; i < sizeof(T); ++i) + Hash = Hash * 131 + data[i]; + return Hash; + } -int Hash::operator()(const String &s) const { - int Hash = 5381; - const char *str = s.CStr(); - int len = s.Length(); - for (int i = 0; i < len; ++i) - Hash = ((Hash << 5) + Hash) + static_cast(str[i]); - return Hash; -} + int Hash::operator()(const String &s) const { + int Hash = 5381; + const char *str = s.CStr(); + size_t len = s.Length(); + for (int i = 0; i < len; ++i) + Hash = ((Hash << 5) + Hash) + static_cast(str[i]); + return Hash; + } } // namespace CTF::Collections \ No newline at end of file diff --git a/Source/CTF/ctf/FileStream.cpp b/Source/CTF/ctf/FileStream.cpp index b506e9d..4d92b2a 100644 --- a/Source/CTF/ctf/FileStream.cpp +++ b/Source/CTF/ctf/FileStream.cpp @@ -117,7 +117,7 @@ namespace CTF { return *this; } - if (fscanf(fp_, "%511s", buffer) == 1) { + if (fscanf(fp_, "%511s", buffer, (unsigned)sizeof(buffer)) == 1) { out = buffer; state_ = StreamState::Good; } else { diff --git a/Source/CTF/ctf/FileStream.h b/Source/CTF/ctf/FileStream.h index b15bf4a..cfd4a60 100644 --- a/Source/CTF/ctf/FileStream.h +++ b/Source/CTF/ctf/FileStream.h @@ -22,7 +22,6 @@ #define FILESTREAM_H #pragma once - #include "Stream.h" #include "stdio.h" #include diff --git a/Source/CTF/ctf/LinearArena.cpp b/Source/CTF/ctf/LinearArena.cpp new file mode 100644 index 0000000..8f64e2b --- /dev/null +++ b/Source/CTF/ctf/LinearArena.cpp @@ -0,0 +1,57 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#include "CTF.h" +#include "Memory.h" +#include "LinearArena.h" + +namespace CTF +{ + +LinearArena::LinearArena( size_t size ) +{ + m_buffer = (char *) Memory::Alloc( size ); + m_capacity = size; + m_offset = 0; +} + +LinearArena::~LinearArena() +{ + Memory::Free( m_buffer ); +} + +void *LinearArena::Alloc( size_t size ) +{ + size_t alignedSize = ( size + 7 ) & ~7ULL; + + if ( m_offset + alignedSize > m_capacity ) + return nullptr; + + void *ptr = m_buffer + m_offset; + m_offset += alignedSize; + return ptr; +} + +void LinearArena::Reset() +{ + m_offset = 0; +} + +} \ No newline at end of file diff --git a/Source/CTF/ctf/LinearArena.h b/Source/CTF/ctf/LinearArena.h new file mode 100644 index 0000000..5ff4385 --- /dev/null +++ b/Source/CTF/ctf/LinearArena.h @@ -0,0 +1,45 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#ifndef CTF_LINEARARENA_H +#define CTF_LINEARARENA_H +#pragma once + +namespace CTF +{ + +class CTF_API LinearArena +{ +public: + LinearArena( size_t size ); + ~LinearArena(); + + void *Alloc( size_t size ); + void Reset(); + +private: + char *m_buffer; + size_t m_capacity; + size_t m_offset; +}; + +} + +#endif // !CTF_LINEARARENA_H diff --git a/Source/CTF/ctf/Math/Logarithms.h b/Source/CTF/ctf/Math/Logarithms.h new file mode 100644 index 0000000..b5d8d0c --- /dev/null +++ b/Source/CTF/ctf/Math/Logarithms.h @@ -0,0 +1,77 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#ifndef MATH_LOGARITHMS_H +#define MATH_LOGARITHMS_H +#pragma once + +#include + +namespace CTF::Math { + CTF_CONSTEXPR double Log2 = 0.693147180559945309417; + + template + CTF_CONSTEXPR T Exp(T x) { + int k = static_cast(x / Log2); + T r = x - k * Log2; + + T term = 1; + T sum = 1; + + for (int n = 1; n < 30; ++n) { + term *= r / n; + sum += term; + if (std::abs(term) < 1e-15) break; + } + + return std::ldexp(sum, k); + } + + template + CTF_CONSTEXPR T Log(T x) { + int k; + T m = std::frexp(x, &k); // x = m * 2^k, m in [0.5, 1) + + if (m < T(0.70710678118)) { // ~1/sqrt(2) + m *= 2; + k -= 1; + } + + T y = (m - 1) / (m + 1); + T y2 = y * y; + + T sum = 0; + T term = y; + + for (int i = 1; i < 50; i += 2) { + sum += term / i; + term *= y2; + } + + return 2 * sum + k * Log2; + } + + template + CTF_CONSTEXPR T Log(T x, T b) { + return Log(x) / Log(b); + } +} + +#endif // !MATH_LOGARITHMS_H diff --git a/Source/CTF/ctf/Math/Power.h b/Source/CTF/ctf/Math/Power.h new file mode 100644 index 0000000..0f6fda0 --- /dev/null +++ b/Source/CTF/ctf/Math/Power.h @@ -0,0 +1,38 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#ifndef MATH_POWER_H +#define MATH_POWER_H +#pragma once + +#include +#include "Algorithm.h" + +namespace CTF::Math { + template + CTF_CONSTEXPR T Pow(T b, T ex) { + T result = 1.0; + T absEx = Abs(ex); + for (int i = 0; i < absEx; i++) result *= b; + return (ex < 0) ? 1.0 / result : result; + } +} + +#endif // !MATH_POWER_H diff --git a/Source/CTF/ctf/Math/Rounding.h b/Source/CTF/ctf/Math/Rounding.h new file mode 100644 index 0000000..8158379 --- /dev/null +++ b/Source/CTF/ctf/Math/Rounding.h @@ -0,0 +1,45 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#ifndef MATH_ROUNDING_H +#define MATH_ROUNDING_H +#pragma once + +#include + +namespace CTF::Math { + template + CTF_CONSTEXPR T Ceil(T x) { + long long truncated = static_cast(x); + if (static_cast(truncated) == x) return x; + if (x > 0) return static_cast(truncated + 1); + return static_cast(truncated); + } + + template + CTF_CONSTEXPR T Floor(T x) { + long long integer = static_cast(x); + T result = static_cast(truncated); + if (x > 0 && x != result) return result - 1; + return result; + } +} + +#endif // !MATH_ROUNDING_H diff --git a/Source/CTF/ctf/Math/Trigonometry.h b/Source/CTF/ctf/Math/Trigonometry.h new file mode 100644 index 0000000..8fab957 --- /dev/null +++ b/Source/CTF/ctf/Math/Trigonometry.h @@ -0,0 +1,82 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#ifndef MATH_TRIGONOMETRY_H +#define MATH_TRIGONOMETRY_H +#pragma once + +#include + +namespace CTF::Math { + template + CTF_CONSTEXPR T Sin(T x) { + const T pi = std::numbers::pi_v; + const T twoPi = T(2) * pi; + + x = std::fmod(x, twoPi); + + if (x > pi) + x -= twoPi; + else if (x < -pi) + x += twoPi; + + if (x > pi / 2) + x = pi - x; + else if (x < -pi / 2) + x = -pi - x; + + T term = x; + T sum = x; + T sq = x * x; + + for (int i = 1; i <= 20; i++) { + term *= -sq / ((2 * i) * (2 * i + 1)); + sum += term; + } + + return sum; + } + + template + CTF_CONSTEXPR T Cos(T x) { + const T pi = std::numbers::pi_v; + while (x < 0) x += 2 * pi; + x = std::fmod(x, T(2) * T(pi)); + + T term = 1; + T sum = 1; + + for (int i = 1; i <= 20; i++) { + term *= -x * x / ((2 * i) * (2 * i - 1)); + sum += term; + + if (std::abs(term) < std::numeric_limits::epsilon()) break; + } + + return sum; + } + + template + CTF_CONSTEXPR T Tan(T x) { + return Sin(x) / Cos(x); + } +} + +#endif // !MATH_TRIGONOMETRY_H diff --git a/Source/CTF/ctf/Memory.cpp b/Source/CTF/ctf/Memory.cpp index 1802311..ae53f08 100644 --- a/Source/CTF/ctf/Memory.cpp +++ b/Source/CTF/ctf/Memory.cpp @@ -62,33 +62,4 @@ namespace CTF { std::free(ptr); #endif } - - LinearArena::LinearArena(size_t size) - { - m_buffer = (char*)Memory::Alloc(size); - m_capacity = size; - m_offset = 0; - } - - LinearArena::~LinearArena() - { - Memory::Free(m_buffer); - } - - void* LinearArena::Alloc(size_t size) - { - size_t alignedSize = (size + 7) & ~7ULL; - - if (m_offset + alignedSize > m_capacity) - return nullptr; - - void* ptr = m_buffer + m_offset; - m_offset += alignedSize; - return ptr; - } - - void LinearArena::Reset() - { - m_offset = 0; - } } diff --git a/Source/CTF/ctf/Memory.h b/Source/CTF/ctf/Memory.h index 2b04f2a..7e86bb6 100644 --- a/Source/CTF/ctf/Memory.h +++ b/Source/CTF/ctf/Memory.h @@ -25,33 +25,20 @@ #include "CTF.h" namespace CTF { - class CTF_API Memory - { - public: - static void* Alloc(size_t size); - static void* Calloc(size_t count, size_t size); - static void Free(void* ptr); - - static void* Realloc(void* ptr, size_t newSize); - - static void* AllocAligned(size_t size, size_t alignment); - static void FreeAligned(void* ptr); - }; - - class CTF_API LinearArena - { - public: - LinearArena(size_t size); - ~LinearArena(); - - void* Alloc(size_t size); - void Reset(); - - private: - char* m_buffer; - size_t m_capacity; - size_t m_offset; - }; + +class CTF_API Memory +{ +public: + static void *Alloc( size_t size ); + static void *Calloc( size_t count, size_t size ); + static void Free( void *ptr ); + + static void *Realloc( void *ptr, size_t newSize ); + + static void *AllocAligned( size_t size, size_t alignment ); + static void FreeAligned( void *ptr ); +}; + } #endif // !CTF_MEMORY_H \ No newline at end of file diff --git a/Source/CTF/ctf/Stream.h b/Source/CTF/ctf/Stream.h index 326ca8e..4fb687c 100644 --- a/Source/CTF/ctf/Stream.h +++ b/Source/CTF/ctf/Stream.h @@ -36,7 +36,7 @@ namespace CTF { Error }; - class Stream { + class CTF_API Stream { public: virtual ~Stream() = default; diff --git a/Source/CTF/ctf/Threading/Task.h b/Source/CTF/ctf/Threading/Task.h index 9ef3d94..bde86d4 100644 --- a/Source/CTF/ctf/Threading/Task.h +++ b/Source/CTF/ctf/Threading/Task.h @@ -1,6 +1,21 @@ /* - * Cereon Template Framework - Task - * Type definitions + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . */ #ifndef TASK_H diff --git a/Source/CTF/tests/CMakeLists.txt b/Source/CTF/tests/CMakeLists.txt index 8306521..2cb3e40 100644 --- a/Source/CTF/tests/CMakeLists.txt +++ b/Source/CTF/tests/CMakeLists.txt @@ -1,3 +1,4 @@ -add_subdirectory(json) add_subdirectory(io) +add_subdirectory(json) +add_subdirectory(math) #add_subdirectory(keyvalues) diff --git a/Source/CTF/tests/math/CMakeLists.txt b/Source/CTF/tests/math/CMakeLists.txt new file mode 100644 index 0000000..6b1ee01 --- /dev/null +++ b/Source/CTF/tests/math/CMakeLists.txt @@ -0,0 +1,55 @@ +project(testMath) + +if(MSVC) + add_compile_options(/wd4172) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options(-Wno-return-local-addr) +endif() + +set(CTF_INC_DIRS ${SRC_DIR}/CTF/ctf) + +set(SOURCES + "main.cpp" + "trigonometrytest.cpp" +) + +if(MSVC) + foreach(FILE ${SOURCES}) + get_filename_component(PARENT_DIR "${FILE}" DIRECTORY) + + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${PARENT_DIR}") + string(REPLACE "/" "\\" GROUP "${GROUP}") + + if ("${FILE}" MATCHES ".*\\.cpp" OR "${FILE}" MATCHES ".*\\.inl" OR "${FILE}" MATCHES ".*\\.ui" OR "${FILE}" MATCHES ".*\\.qml") + set(GROUP "Source Files\\${GROUP}") + elseif("${FILE}" MATCHES ".*\\.h") + set(GROUP "Header Files\\${GROUP}") + endif() + + source_group("${GROUP}" FILES "${FILE}") + endforeach() +endif() + +add_executable(${PROJECT_NAME} ${SOURCES}) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CTF_INC_DIRS} + ${THIRDPARTY_DIR}/googletest/googletest/include +) + +add_dependencies(${PROJECT_NAME} + CTF + gtest + gtest_main +) +target_link_libraries(${PROJECT_NAME} PRIVATE CTF) +target_link_libraries(${PROJECT_NAME} PRIVATE + gtest + gtest_main +) + +add_test( + NAME CTF_Math_Test + COMMAND testMath +) diff --git a/Source/CTF/tests/math/logarithmtest.cpp b/Source/CTF/tests/math/logarithmtest.cpp new file mode 100644 index 0000000..18763ea --- /dev/null +++ b/Source/CTF/tests/math/logarithmtest.cpp @@ -0,0 +1,113 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#include +#include +#include + +#include +#include + +namespace { + constexpr double EPS = 1e-8; + constexpr double EPS_EXP = 1e-9; + + template + void ExpectNear(T a, T b, T eps = EPS) { + EXPECT_NEAR(a, b, eps); + } +} + +TEST(LogarithmTest, Exp_KnownValues) { + ExpectNear(CTF::Math::Exp(0.0), 1.0, EPS_EXP); + ExpectNear(CTF::Math::Exp(1.0), std::exp(1.0), EPS_EXP); + ExpectNear(CTF::Math::Exp(-1.0), std::exp(-1.0), EPS_EXP); +} + +TEST(LogarithmTest, Exp_AgainstStd) { + for (double x = -5.0; x <= 5.0; x += 0.1) { + ExpectNear(CTF::Math::Exp(x), std::exp(x), 1e-8); + } +} + +TEST(LogarithmTest, Exp_Additivity) { + for (double x = -2.0; x <= 2.0; x += 0.5) { + for (double y = -2.0; y <= 2.0; y += 0.5) { + double lhs = CTF::Math::Exp(x + y); + double rhs = CTF::Math::Exp(x) * CTF::Math::Exp(y); + EXPECT_NEAR(lhs, rhs, 1e-7); + } + } +} + +TEST(LogarithmTest, Exp_Log_Inverse) { + for (double x = 0.1; x <= 5.0; x += 0.1) { + double val = CTF::Math::Exp(CTF::Math::Log(x)); + EXPECT_NEAR(val, x, 1e-7); + } +} + +TEST(LogarithmTest, Exp_LargerValues) { + for (double x = 5.0; x <= 10.0; x += 1.0) { + EXPECT_NEAR(CTF::Math::Exp(x), std::exp(x), 1e-5); + } +} + +TEST(LogarithmTest, Log_KnownValues) { + ExpectNear(CTF::Math::Log(1.0), 0.0, EPS); + ExpectNear(CTF::Math::Log(std::exp(1.0)), 1.0, EPS); +} + +TEST(LogarithmTest, Log_AgainstStd) { + for (double x = 0.1; x <= 5.0; x += 0.1) { + ExpectNear(CTF::Math::Log(x), std::log(x), 1e-7); + } +} + +TEST(LogarithmTest, Log_ProductRule) { + for (double a = 0.5; a <= 3.0; a += 0.5) { + for (double b = 0.5; b <= 3.0; b += 0.5) { + double lhs = CTF::Math::Log(a * b); + double rhs = CTF::Math::Log(a) + CTF::Math::Log(b); + EXPECT_NEAR(lhs, rhs, 1e-6); + } + } +} + +TEST(LogarithmTest, Log_BaseChange) { + for (double x = 0.5; x <= 5.0; x += 0.5) { + for (double b = 2.0; b <= 5.0; b += 1.0) { + double result = CTF::Math::Log(x, b); + double expected = std::log(x) / std::log(b); + EXPECT_NEAR(result, expected, 1e-7); + } + } +} + +TEST(LogarithmTest, Log_InvalidInput) { + EXPECT_LT(CTF::Math::Log(0.0), 0.0); + EXPECT_LT(CTF::Math::Log(-1.0), 0.0); +} + +TEST(LogarithmTest, Log_WideRange) { + for (double x = 0.1; x <= 10.0; x += 0.5) { + EXPECT_NEAR(CTF::Math::Log(x), std::log(x), 1e-6); + } +} \ No newline at end of file diff --git a/Source/CTF/tests/math/main.cpp b/Source/CTF/tests/math/main.cpp new file mode 100644 index 0000000..45d1c2b --- /dev/null +++ b/Source/CTF/tests/math/main.cpp @@ -0,0 +1,26 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#include + +int main(int argc, char* argv[]) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/Source/CTF/tests/math/trigonometrytest.cpp b/Source/CTF/tests/math/trigonometrytest.cpp new file mode 100644 index 0000000..df24488 --- /dev/null +++ b/Source/CTF/tests/math/trigonometrytest.cpp @@ -0,0 +1,115 @@ +/* + * Cereon Template Framework, a C++ 23 standard template library. + * Copyright (c) 2026 The Aridity Team, all rights reserved. + * + * This file is part of the Cereon Template Framework project. + * + * Cereon Template Framework is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation, either + * version 3 of the License, or any later version. + * + * Cereon Template Framework is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Cereon Template Framework. If not, see . + */ + +#include +#include +#include + +#include +#include + +namespace { + constexpr double EPS = 1e-8; + + template + void ExpectNear(T a, T b, T eps = EPS) { + EXPECT_NEAR(a, b, eps); + } +} + +TEST(TrigonometryTest, Sin_KnownValues) { + using std::numbers::pi; + + ExpectNear(CTF::Math::Sin(0.0), 0.0); + ExpectNear(CTF::Math::Sin(pi / 2), 1.0); + ExpectNear(CTF::Math::Sin(pi), 0.0); + ExpectNear(CTF::Math::Sin(3 * pi / 2), -1.0); +} + +TEST(TrigonometryTest, Sin_AgainstStd) { + for (double x = -10.0; x <= 10.0; x += 0.1) { + ExpectNear(CTF::Math::Sin(x), std::sin(x)); + } +} + +TEST(TrigonometryTest, Sin_Periodicity) { + using std::numbers::pi; + + for (double x = -5.0; x <= 5.0; x += 0.5) { + ExpectNear(CTF::Math::Sin(x), CTF::Math::Sin(x + 2 * pi)); + } +} + +TEST(TrigonometryTest, Sin_LargeValues) { + for (double x = -100.0; x <= 100.0; x += 5.0) { + EXPECT_NEAR(CTF::Math::Sin(x), std::sin(x), 1e-6); + } +} + +TEST(TrigonometryTest, Cos_LargeValues) { + for (double x = -100.0; x <= 100.0; x += 5.0) { + EXPECT_NEAR(CTF::Math::Cos(x), std::cos(x), 1e-6); + } +} + +TEST(TrigonometryTest, Cos_KnownValues) { + using std::numbers::pi; + + ExpectNear(CTF::Math::Cos(0.0), 1.0); + ExpectNear(CTF::Math::Cos(pi / 2), 0.0); + ExpectNear(CTF::Math::Cos(pi), -1.0); + ExpectNear(CTF::Math::Cos(2 * pi), 1.0); +} + +TEST(TrigonometryTest, Cos_AgainstStd) { + for (double x = -10.0; x <= 10.0; x += 0.1) { + ExpectNear(CTF::Math::Cos(x), std::cos(x)); + } +} + +TEST(TrigonometryTest, Cos_Periodicity) { + using std::numbers::pi; + + for (double x = -5.0; x <= 5.0; x += 0.5) { + ExpectNear(CTF::Math::Cos(x), CTF::Math::Cos(x + 2 * pi)); + } +} + +TEST(TrigonometryTest, Tan_KnownValues) { + using std::numbers::pi; + + ExpectNear(CTF::Math::Tan(0.0), 0.0); + ExpectNear(CTF::Math::Tan(pi / 4), 1.0); + ExpectNear(CTF::Math::Tan(-pi / 4), -1.0); +} + +TEST(TrigonometryTest, Tan_AgainstStd) { + using std::numbers::pi; + + for (double x = -1.4; x <= 1.4; x += 0.05) { // avoid ±pi/2 ≈ 1.57 + ExpectNear(CTF::Math::Tan(x), std::tan(x), 1e-6); + } +} + +TEST(TrigonometryTest, Tan_OddFunction) { + for (double x = -1.0; x <= 1.0; x += 0.1) { + ExpectNear(CTF::Math::Tan(-x), -CTF::Math::Tan(x)); + } +}