File size: 4,766 Bytes
78d2150 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
#include "../../unity/unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>
/* Helper: absolute value for long double without libm dependency */
static long double ldabs(long double x) { return x < 0 ? -x : x; }
/* Helper: assert two long doubles are approximately equal */
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);
}
}
/* Unity fixtures */
void setUp(void) {
/* no global state to set for expld() */
}
void tearDown(void) {
/* nothing to clean up */
}
/* Tests */
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; /* 10^3 */
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|");
/* Expected: -1.2345 */
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); /* 5 * 1024^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; /* 2 * 1024 */
long double out = expld(in, 1024, NULL);
/* Should scale to 2.0, but we cannot check x as it's NULL; ensure no crash and correct value */
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); /* 7.25e6 */
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");
/* Verify |out| < base and reconstruction property approximately holds */
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;
/* Use relative tolerance for large numbers */
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();
} |