@@ -46,32 +46,45 @@ static inline double php_intpow10(int power) {
46
46
}
47
47
/* }}} */
48
48
49
- #define PHP_ROUND_GET_EDGE_CASE (adjusted_value , value_abs , integral , exponent ) do {\
50
- if (fabs(adjusted_value) >= value_abs) {\
51
- edge_case = fabs((integral + copysign(0.5, integral)) / exponent);\
52
- } else {\
53
- edge_case = fabs((integral + copysign(0.5, integral)) * exponent);\
54
- }\
55
- } while(0);
56
-
57
- #define PHP_ROUND_GET_ZERO_EDGE_CASE (adjusted_value , value_abs , integral , exponent ) do {\
58
- if (fabs(adjusted_value) >= value_abs) {\
59
- edge_case = fabs((integral) / exponent);\
60
- } else {\
61
- edge_case = fabs((integral) * exponent);\
62
- }\
63
- } while(0);
64
-
65
49
/* {{{ php_round_helper
66
50
Actually performs the rounding of a value to integer in a certain mode */
67
- static inline double php_round_helper (double adjusted_value , double value , double exponent , int mode ) {
68
- double integral = adjusted_value >= 0.0 ? floor (adjusted_value ) : ceil (adjusted_value );
51
+ static inline double php_round_helper (double adjusted_value , double value , double exponent , int places , int mode ) {
52
+ double integral ;
53
+ PHP_ROUND_GET_CURRENT_REG ();
54
+ if (value >= 0.0 ) {
55
+ PHP_ROUND_ROUND_MODE_SWITCH_UP ();
56
+ integral = floor (places > 0 ? value * exponent : value / exponent );
57
+ } else {
58
+ PHP_ROUND_ROUND_MODE_SWITCH_DOWN ();
59
+ integral = ceil (places > 0 ? value * exponent : value / exponent );
60
+ }
61
+ PHP_ROUND_RESTORE_REG ();
62
+
69
63
double value_abs = fabs (value );
70
64
double edge_case ;
71
65
72
66
switch (mode ) {
73
67
case PHP_ROUND_HALF_UP :
74
- PHP_ROUND_GET_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
68
+ case PHP_ROUND_HALF_DOWN :
69
+ case PHP_ROUND_HALF_EVEN :
70
+ case PHP_ROUND_HALF_ODD :
71
+ if (fabs (adjusted_value ) >= value_abs ) {
72
+ edge_case = fabs ((integral + copysign (0.5 , integral )) / exponent );
73
+ } else {
74
+ edge_case = fabs ((integral + copysign (0.5 , integral )) * exponent );
75
+ }
76
+ break ;
77
+ default :
78
+ if (fabs (adjusted_value ) >= value_abs ) {
79
+ edge_case = fabs ((integral ) / exponent );
80
+ } else {
81
+ edge_case = fabs ((integral ) * exponent );
82
+ }
83
+ break ;
84
+ }
85
+
86
+ switch (mode ) {
87
+ case PHP_ROUND_HALF_UP :
75
88
if (value_abs >= edge_case ) {
76
89
/* We must increase the magnitude of the integral part
77
90
* (rounding up / towards infinity). copysign(1.0, integral)
@@ -87,23 +100,20 @@ static inline double php_round_helper(double adjusted_value, double value, doubl
87
100
return integral ;
88
101
89
102
case PHP_ROUND_HALF_DOWN :
90
- PHP_ROUND_GET_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
91
103
if (value_abs > edge_case ) {
92
104
return integral + copysign (1.0 , integral );
93
105
}
94
106
95
107
return integral ;
96
108
97
109
case PHP_ROUND_CEILING :
98
- PHP_ROUND_GET_ZERO_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
99
110
if (value > 0.0 && value_abs > edge_case ) {
100
111
return integral + 1.0 ;
101
112
}
102
113
103
114
return integral ;
104
115
105
116
case PHP_ROUND_FLOOR :
106
- PHP_ROUND_GET_ZERO_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
107
117
if (value < 0.0 && value_abs > edge_case ) {
108
118
return integral - 1.0 ;
109
119
}
@@ -114,15 +124,13 @@ static inline double php_round_helper(double adjusted_value, double value, doubl
114
124
return integral ;
115
125
116
126
case PHP_ROUND_AWAY_FROM_ZERO :
117
- PHP_ROUND_GET_ZERO_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
118
127
if (value_abs > edge_case ) {
119
128
return integral + copysign (1.0 , integral );
120
129
}
121
130
122
131
return integral ;
123
132
124
133
case PHP_ROUND_HALF_EVEN :
125
- PHP_ROUND_GET_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
126
134
if (value_abs > edge_case ) {
127
135
return integral + copysign (1.0 , integral );
128
136
} else if (UNEXPECTED (value_abs == edge_case )) {
@@ -139,7 +147,6 @@ static inline double php_round_helper(double adjusted_value, double value, doubl
139
147
return integral ;
140
148
141
149
case PHP_ROUND_HALF_ODD :
142
- PHP_ROUND_GET_EDGE_CASE (adjusted_value , value_abs , integral , exponent );
143
150
if (value_abs > edge_case ) {
144
151
return integral + copysign (1.0 , integral );
145
152
} else if (UNEXPECTED (value_abs == edge_case )) {
@@ -188,7 +195,7 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
188
195
}
189
196
190
197
/* round the temp value */
191
- tmp_value = php_round_helper (tmp_value , value , exponent , mode );
198
+ tmp_value = php_round_helper (tmp_value , value , exponent , places , mode );
192
199
193
200
/* see if it makes sense to use simple division to round the value */
194
201
if (abs (places ) < 23 ) {
@@ -215,7 +222,6 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
215
222
tmp_value = value ;
216
223
}
217
224
}
218
-
219
225
return tmp_value ;
220
226
}
221
227
/* }}} */
0 commit comments