Skip to content

Commit 9c1e650

Browse files
committed
Refactored rounding function
1 parent a5755c1 commit 9c1e650

File tree

1 file changed

+18
-23
lines changed

1 file changed

+18
-23
lines changed

ext/standard/math.c

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,19 @@ static inline double php_intpow10(int power) {
9393
/* {{{ php_round_helper
9494
Actually performs the rounding of a value to integer in a certain mode */
9595
static inline double php_round_helper(double value, int mode) {
96-
double integral, fractional;
9796

9897
/* Split the input value into the integral and fractional part.
9998
*
10099
* Both parts will have the same sign as the input value. We take
101100
* the absolute value of the fractional part (which will not result
102101
* in branches in the assembly) to make the following cases simpler.
103102
*/
103+
double integral;
104+
double fractional = modf(value, &integral);
104105

105106
switch (mode) {
106107
case PHP_ROUND_HALF_UP:
107-
fractional = fabs(modf(value, &integral));
108-
if (fractional >= 0.5) {
108+
if (fractional >= 0.5 || fractional <= -0.5) {
109109
/* We must increase the magnitude of the integral part
110110
* (rounding up / towards infinity). copysign(1.0, integral)
111111
* will either result in 1.0 or -1.0 depending on the sign
@@ -120,40 +120,36 @@ static inline double php_round_helper(double value, int mode) {
120120
return integral;
121121

122122
case PHP_ROUND_HALF_DOWN:
123-
fractional = fabs(modf(value, &integral));
124-
if (fractional > 0.5) {
123+
if (fractional > 0.5 || fractional < -0.5) {
125124
return integral + copysign(1.0, integral);
126125
}
127126

128127
return integral;
129128

130129
case PHP_ROUND_CEILING:
131-
return ceil(value);
130+
if (value > 0.0) {
131+
return fractional == 0 ? integral : integral + 1.0;
132+
}
133+
return integral;
132134

133135
case PHP_ROUND_FLOOR:
134-
return floor(value);
136+
if (value < 0.0) {
137+
return fractional == 0 ? integral : integral - 1.0;
138+
}
139+
return integral;
135140

136141
case PHP_ROUND_TOWARD_ZERO:
137-
if (value >= 0.0) {
138-
return floor(value);
139-
} else {
140-
return ceil(value);
141-
}
142+
return integral;
142143

143144
case PHP_ROUND_AWAY_FROM_ZERO:
144-
if (value >= 0.0) {
145-
return ceil(value);
146-
} else {
147-
return floor(value);
148-
}
145+
return fractional == 0 ? integral : integral + copysign(1.0, integral);
149146

150147
case PHP_ROUND_HALF_EVEN:
151-
fractional = fabs(modf(value, &integral));
152-
if (fractional > 0.5) {
148+
if (fractional > 0.5 || fractional < -0.5) {
153149
return integral + copysign(1.0, integral);
154150
}
155151

156-
if (UNEXPECTED(fractional == 0.5)) {
152+
if (UNEXPECTED(fractional == 0.5 || fractional == -0.5)) {
157153
bool even = !fmod(integral, 2.0);
158154

159155
/* If the integral part is not even we can make it even
@@ -167,12 +163,11 @@ static inline double php_round_helper(double value, int mode) {
167163
return integral;
168164

169165
case PHP_ROUND_HALF_ODD:
170-
fractional = fabs(modf(value, &integral));
171-
if (fractional > 0.5) {
166+
if (fractional > 0.5 || fractional < -0.5) {
172167
return integral + copysign(1.0, integral);
173168
}
174169

175-
if (UNEXPECTED(fractional == 0.5)) {
170+
if (UNEXPECTED(fractional == 0.5 || fractional == -0.5)) {
176171
bool even = !fmod(integral, 2.0);
177172

178173
if (even) {

0 commit comments

Comments
 (0)