From 501183ca3e33283d6429ebff17eff28cea8c34b9 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 17 Aug 2023 12:56:13 +0200 Subject: [PATCH] math: add Signed-off-by: Simon Rozman --- UnitTests/UnitTests.vcxproj | 1 + UnitTests/UnitTests.vcxproj.filters | 3 ++ UnitTests/math.cpp | 42 +++++++++++++++++++++++++ UnitTests/pch.h | 1 + include/stdex/math.hpp | 49 +++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 UnitTests/math.cpp create mode 100644 include/stdex/math.hpp diff --git a/UnitTests/UnitTests.vcxproj b/UnitTests/UnitTests.vcxproj index b6cd49e05..cdc137988 100644 --- a/UnitTests/UnitTests.vcxproj +++ b/UnitTests/UnitTests.vcxproj @@ -116,6 +116,7 @@ + Create diff --git a/UnitTests/UnitTests.vcxproj.filters b/UnitTests/UnitTests.vcxproj.filters index 05a4e21ce..a1d5947e6 100644 --- a/UnitTests/UnitTests.vcxproj.filters +++ b/UnitTests/UnitTests.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + diff --git a/UnitTests/math.cpp b/UnitTests/math.cpp new file mode 100644 index 000000000..9975c3dd6 --- /dev/null +++ b/UnitTests/math.cpp @@ -0,0 +1,42 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2023 Amebis +*/ + +#include "pch.h" + +using namespace std; +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace UnitTests +{ + TEST_CLASS(math) + { + public: + TEST_METHOD(mul) + { + Assert::AreEqual(10, stdex::mul(2, 5)); + Assert::AreEqual(10, stdex::mul(5, 2)); + Assert::AreEqual(0, stdex::mul(0, 10)); + Assert::AreEqual(0, stdex::mul(10, 0)); + Assert::AreEqual(0, stdex::mul(SIZE_MAX, 0)); + Assert::AreEqual(0, stdex::mul(0, SIZE_MAX)); + Assert::AreEqual(SIZE_MAX, stdex::mul(SIZE_MAX, 1)); + Assert::AreEqual(SIZE_MAX, stdex::mul(1, SIZE_MAX)); + Assert::ExpectException([] { stdex::mul(SIZE_MAX, 2); }); + Assert::ExpectException([] { stdex::mul(2, SIZE_MAX); }); + } + + TEST_METHOD(add) + { + Assert::AreEqual(7, stdex::add(2, 5)); + Assert::AreEqual(7, stdex::add(5, 2)); + Assert::AreEqual(10, stdex::add(0, 10)); + Assert::AreEqual(10, stdex::add(10, 0)); + Assert::AreEqual(SIZE_MAX, stdex::add(SIZE_MAX, 0)); + Assert::AreEqual(SIZE_MAX, stdex::add(0, SIZE_MAX)); + Assert::ExpectException([] { stdex::add(SIZE_MAX, 1); }); + Assert::ExpectException([] { stdex::add(1, SIZE_MAX); }); + } + }; +} diff --git a/UnitTests/pch.h b/UnitTests/pch.h index 6016f700e..b7d7f5037 100644 --- a/UnitTests/pch.h +++ b/UnitTests/pch.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/include/stdex/math.hpp b/include/stdex/math.hpp new file mode 100644 index 000000000..73427a34d --- /dev/null +++ b/include/stdex/math.hpp @@ -0,0 +1,49 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2023 Amebis +*/ + +#pragma once + +#include "sal.hpp" +#include "system.hpp" +#include + +namespace stdex +{ + inline size_t mul(size_t a, size_t b) + { +#if _MSC_VER >= 1300 + SIZE_T result; + if (SUCCEEDED(SIZETMult(a, b, &result))) + return result; +#elif defined(_MSC_VER) + if (a == 0) + return 0; + if (b <= SIZE_MAX / a) + return a * b; +#else + size_t result; + if (!__builtin_mul_overflow(a, b, &result)) + return result; +#endif + throw std::invalid_argument("multiply overflow"); + } + + inline size_t add(size_t a, size_t b) + { +#if _MSC_VER >= 1300 + SIZE_T result; + if (SUCCEEDED(SIZETAdd(a, b, &result))) + return result; +#elif defined(_MSC_VER) + if (a <= SIZE_MAX - b) + return a + b; +#else + size_t result; + if (!__builtin_add_overflow(a, b, &result)) + return result; +#endif + throw std::invalid_argument("add overflow"); + } +} \ No newline at end of file