| | #include "../../unity/unity.h" |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| | #include <float.h> |
| | #include <math.h> |
| |
|
| | |
| | static long double ldabs(long double x) { return x < 0 ? -x : x; } |
| |
|
| | |
| | static void assert_ld_close(long double expected, long double actual, long double tol, const char* msg) |
| | { |
| | long double diff = ldabs(expected - actual); |
| | if (diff > tol) |
| | { |
| | char buf[256]; |
| | snprintf(buf, sizeof(buf), |
| | "%s: expected %.18Lg but got %.18Lg (diff=%.18Lg, tol=%.18Lg)", |
| | msg ? msg : "Mismatch", expected, actual, diff, tol); |
| | TEST_FAIL_MESSAGE(buf); |
| | } |
| | } |
| |
|
| | |
| | void setUp(void) { |
| | |
| | } |
| | void tearDown(void) { |
| | |
| | } |
| |
|
| | |
| |
|
| | static void test_expld_abs_less_than_base(void) |
| | { |
| | int x = -1; |
| | long double in = 9.5L; |
| | long double out = expld(in, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, x, "power should be 0 when |val| < base"); |
| | assert_ld_close(in, out, 1e-15L, "value should be unchanged when |val| < base"); |
| | } |
| |
|
| | static void test_expld_exact_power_of_base(void) |
| | { |
| | int x = -1; |
| | long double in = 1000.0L; |
| | long double out = expld(in, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(3, x, "power should be 3 for 10^3"); |
| | assert_ld_close(1.0L, out, 1e-18L, "scaled value should be 1.0 for 10^3"); |
| | } |
| |
|
| | static void test_expld_negative_value(void) |
| | { |
| | int x = -1; |
| | long double in = -12345.0L; |
| | long double out = expld(in, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(4, x, "power should be 4 for |-12345|"); |
| | |
| | assert_ld_close(-1.2345L, out, 1e-15L, "scaled value mismatch for negative input"); |
| | } |
| |
|
| | static void test_expld_base_1024_exact(void) |
| | { |
| | int x = -1; |
| | long double in = 5.0L * powerld(1024.0L, 2); |
| | long double out = expld(in, 1024, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(2, x, "power should be 2 for 5*1024^2"); |
| | assert_ld_close(5.0L, out, 1e-18L, "scaled value should be exactly 5.0"); |
| | } |
| |
|
| | static void test_expld_zero_value(void) |
| | { |
| | int x = -1; |
| | long double out = expld(0.0L, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, x, "power should be 0 for input 0"); |
| | assert_ld_close(0.0L, out, 0.0L, "output should be 0 for input 0"); |
| | } |
| |
|
| | static void test_expld_null_x_pointer(void) |
| | { |
| | long double in = 2048.0L; |
| | long double out = expld(in, 1024, NULL); |
| | |
| | assert_ld_close(2.0L, out, 1e-18L, "scaled value should be 2.0 when x is NULL"); |
| | } |
| |
|
| | static void test_expld_fractional_scaling_and_reversibility(void) |
| | { |
| | int x = -1; |
| | long double base = 10.0L; |
| | int k = 6; |
| | long double mantissa = 7.25L; |
| | long double in = mantissa * powerld(base, k); |
| | long double out = expld(in, (int)base, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(k, x, "power should equal the constructed exponent"); |
| | assert_ld_close(mantissa, out, 1e-12L, "scaled mantissa mismatch"); |
| |
|
| | |
| | TEST_ASSERT_TRUE_MESSAGE(ldabs(out) < base, "|scaled value| should be < base"); |
| | long double recon = out; |
| | for (int i = 0; i < x; i++) recon *= base; |
| | |
| | long double rel_tol = 1e-12L; |
| | long double tol = ldabs(in) * rel_tol + 1e-6L; |
| | assert_ld_close(in, recon, tol, "reconstructed value mismatch"); |
| | } |
| |
|
| | static void test_expld_fractional_input_base10(void) |
| | { |
| | int x = -1; |
| | long double in = 123.456L; |
| | long double out = expld(in, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(2, x, "power should be 2 for 123.456 with base 10"); |
| | assert_ld_close(1.23456L, out, 1e-15L, "scaled value mismatch for 123.456"); |
| | } |
| |
|
| | static void test_expld_nan_input_sets_x_zero_and_returns_nan(void) |
| | { |
| | int x = -1; |
| | long double nanval = (long double)NAN; |
| | long double out = expld(nanval, 10, &x); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, x, "power should be 0 for NaN input"); |
| | TEST_ASSERT_TRUE_MESSAGE(out != out, "output should be NaN (NaN != NaN)"); |
| | } |
| |
|
| | int main(void) |
| | { |
| | UNITY_BEGIN(); |
| | RUN_TEST(test_expld_abs_less_than_base); |
| | RUN_TEST(test_expld_exact_power_of_base); |
| | RUN_TEST(test_expld_negative_value); |
| | RUN_TEST(test_expld_base_1024_exact); |
| | RUN_TEST(test_expld_zero_value); |
| | RUN_TEST(test_expld_null_x_pointer); |
| | RUN_TEST(test_expld_fractional_scaling_and_reversibility); |
| | RUN_TEST(test_expld_fractional_input_base10); |
| | RUN_TEST(test_expld_nan_input_sets_x_zero_and_returns_nan); |
| | return UNITY_END(); |
| | } |