File size: 6,735 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "../../unity/unity.h"
#include <limits.h>
#include <stdint.h>
#include <stdio.h>

/* Unity fixtures */
void setUp(void) {
  /* no setup needed */
}
void tearDown(void) {
  /* no teardown needed */
}

/* Helper to assert long double equality for integer results */
static void assert_ld_equal(long double expected, long double actual, const char* msg)
{
  if (!(expected == actual)) {
    char buf[256];
    /* Print with no fractional digits as results are integral */
    snprintf(buf, sizeof(buf), "%s: expected %.0Lf got %.0Lf", msg, expected, actual);
    TEST_FAIL_MESSAGE(buf);
  }
}

/* Convenience: get INTMAX_MAX as long double */
static long double LDMAX(void) {
  return (long double)INTMAX_MAX;
}

/* Basic rounding tests for small values */
void test_simple_round_ceiling_basic(void) {
  TEST_ASSERT_EQUAL_INT(2, (int)simple_round(1.1L, round_ceiling));
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.0L, round_ceiling));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.1L, round_ceiling));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.0L, round_ceiling));
}

void test_simple_round_floor_basic(void) {
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.9L, round_floor));
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.0L, round_floor));
  TEST_ASSERT_EQUAL_INT(-2, (int)simple_round(-1.1L, round_floor));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.0L, round_floor));
}

void test_simple_round_from_zero_basic(void) {
  TEST_ASSERT_EQUAL_INT(2, (int)simple_round(1.1L, round_from_zero));
  TEST_ASSERT_EQUAL_INT(-2, (int)simple_round(-1.1L, round_from_zero));
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.0L, round_from_zero));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.0L, round_from_zero));
}

void test_simple_round_to_zero_basic(void) {
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.9L, round_to_zero));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.9L, round_to_zero));
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.0L, round_to_zero));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.0L, round_to_zero));
}

void test_simple_round_nearest_basic(void) {
  TEST_ASSERT_EQUAL_INT(1, (int)simple_round(1.49L, round_nearest));
  TEST_ASSERT_EQUAL_INT(2, (int)simple_round(1.5L, round_nearest));
  TEST_ASSERT_EQUAL_INT(-1, (int)simple_round(-1.49L, round_nearest));
  TEST_ASSERT_EQUAL_INT(-2, (int)simple_round(-1.5L, round_nearest));
}

/* Boundary behavior around INTMAX_MAX using 0.5 which is representable */
void test_simple_round_near_INTMAX_MAX_ceil_floor(void) {
  long double M = LDMAX();

  /* M - 0.5 */
  long double v1 = M - 0.5L;
  long double ceil_v1 = simple_round(v1, round_ceiling);
  long double floor_v1 = simple_round(v1, round_floor);
  assert_ld_equal(M,          ceil_v1,  "ceil(M-0.5)");
  assert_ld_equal(M - 1.0L,   floor_v1, "floor(M-0.5)");

  /* M + 0.5 */
  long double v2 = M + 0.5L;
  long double ceil_v2 = simple_round(v2, round_ceiling);
  long double floor_v2 = simple_round(v2, round_floor);
  assert_ld_equal(M + 1.0L,   ceil_v2,  "ceil(M+0.5)");
  assert_ld_equal(M,          floor_v2, "floor(M+0.5)");
}

void test_simple_round_near_INTMAX_MAX_from_to_zero(void) {
  long double M = LDMAX();

  /* Positive side */
  long double vp = M + 0.5L;
  assert_ld_equal(M + 1.0L, simple_round(vp, round_from_zero), "from_zero(M+0.5)");
  assert_ld_equal(M,        simple_round(vp, round_to_zero),   "to_zero(M+0.5)");

  /* Negative side */
  long double vn = -(M + 0.5L);
  assert_ld_equal(-(M + 1.0L), simple_round(vn, round_from_zero), "from_zero(-(M+0.5))");
  assert_ld_equal(-M,          simple_round(vn, round_to_zero),   "to_zero(-(M+0.5))");
}

void test_simple_round_near_INTMAX_MAX_nearest(void) {
  long double M = LDMAX();

  /* .5 ties away from zero */
  assert_ld_equal(M + 1.0L, simple_round(M + 0.5L, round_nearest),  "nearest(M+0.5)");
  assert_ld_equal(- (M + 1.0L), simple_round(- (M + 0.5L), round_nearest), "nearest(-(M+0.5))");

  /* Below half goes to nearest integer */
  assert_ld_equal(M,          simple_round(M + 0.49L, round_nearest),  "nearest(M+0.49)");
  assert_ld_equal(-M,         simple_round(- (M + 0.49L), round_nearest), "nearest(-(M+0.49))");
}

/* Large values exercising partitioning logic with multiples of INTMAX_MAX */
void test_simple_round_large_exact_multiples(void) {
  long double M = LDMAX();

  /* Exactly 2*M */
  long double v = 2.0L * M;
  assert_ld_equal(2.0L * M, simple_round(v, round_ceiling),   "ceil(2*M)");
  assert_ld_equal(2.0L * M, simple_round(v, round_floor),     "floor(2*M)");
  assert_ld_equal(2.0L * M, simple_round(v, round_from_zero), "from_zero(2*M)");
  assert_ld_equal(2.0L * M, simple_round(v, round_to_zero),   "to_zero(2*M)");
  assert_ld_equal(2.0L * M, simple_round(v, round_nearest),   "nearest(2*M)");

  /* 2*M + 1 (still an integer) */
  long double v2 = 2.0L * M + 1.0L;
  assert_ld_equal(2.0L * M + 1.0L, simple_round(v2, round_ceiling),   "ceil(2*M+1)");
  assert_ld_equal(2.0L * M + 1.0L, simple_round(v2, round_floor),     "floor(2*M+1)");
  assert_ld_equal(2.0L * M + 1.0L, simple_round(v2, round_from_zero), "from_zero(2*M+1)");
  assert_ld_equal(2.0L * M + 1.0L, simple_round(v2, round_to_zero),   "to_zero(2*M+1)");
  assert_ld_equal(2.0L * M + 1.0L, simple_round(v2, round_nearest),   "nearest(2*M+1)");

  /* Negative exact large values */
  long double vn = - (2.0L * M);
  assert_ld_equal(- (2.0L * M), simple_round(vn, round_ceiling),   "ceil(-2*M)");
  assert_ld_equal(- (2.0L * M), simple_round(vn, round_floor),     "floor(-2*M)");
  assert_ld_equal(- (2.0L * M), simple_round(vn, round_from_zero), "from_zero(-2*M)");
  assert_ld_equal(- (2.0L * M), simple_round(vn, round_to_zero),   "to_zero(-2*M)");
  assert_ld_equal(- (2.0L * M), simple_round(vn, round_nearest),   "nearest(-2*M)");
}

/* Zero edge cases */
void test_simple_round_zero_cases(void) {
  TEST_ASSERT_EQUAL_INT(0, (int)simple_round(0.0L, round_ceiling));
  TEST_ASSERT_EQUAL_INT(0, (int)simple_round(0.0L, round_floor));
  TEST_ASSERT_EQUAL_INT(0, (int)simple_round(0.0L, round_from_zero));
  TEST_ASSERT_EQUAL_INT(0, (int)simple_round(0.0L, round_to_zero));
  TEST_ASSERT_EQUAL_INT(0, (int)simple_round(0.0L, round_nearest));
}

int main(void) {
  UNITY_BEGIN();

  RUN_TEST(test_simple_round_ceiling_basic);
  RUN_TEST(test_simple_round_floor_basic);
  RUN_TEST(test_simple_round_from_zero_basic);
  RUN_TEST(test_simple_round_to_zero_basic);
  RUN_TEST(test_simple_round_nearest_basic);

  RUN_TEST(test_simple_round_near_INTMAX_MAX_ceil_floor);
  RUN_TEST(test_simple_round_near_INTMAX_MAX_from_to_zero);
  RUN_TEST(test_simple_round_near_INTMAX_MAX_nearest);

  RUN_TEST(test_simple_round_large_exact_multiples);
  RUN_TEST(test_simple_round_zero_cases);

  return UNITY_END();
}