@@ -33,10 +33,54 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
3333	* - If the fractional part ends with zeros, the zeros are omitted and the number of digits in num is reduced. 
3434	*   Meaning we might end up in the previous case. 
3535	*/ 
36+ 
37+ 	/* e.g. value is 0.1 and precision is -3, ret is 0 or 1000  */ 
3638	if  (precision  <  0  &&  num -> n_len  <  (size_t ) (- (precision  +  Z_L (1 ))) +  1 ) {
37- 		* result  =  bc_copy_num (BCG (_zero_ ));
39+ 		switch  (mode ) {
40+ 			case  PHP_ROUND_HALF_UP :
41+ 			case  PHP_ROUND_HALF_DOWN :
42+ 			case  PHP_ROUND_HALF_EVEN :
43+ 			case  PHP_ROUND_HALF_ODD :
44+ 			case  PHP_ROUND_TOWARD_ZERO :
45+ 				* result  =  bc_copy_num (BCG (_zero_ ));
46+ 				return ;
47+ 
48+ 			case  PHP_ROUND_CEILING :
49+ 				if  (num -> n_sign  ==  MINUS ) {
50+ 					* result  =  bc_copy_num (BCG (_zero_ ));
51+ 					return ;
52+ 				}
53+ 				break ;
54+ 
55+ 			case  PHP_ROUND_FLOOR :
56+ 				if  (num -> n_sign  ==  PLUS ) {
57+ 					* result  =  bc_copy_num (BCG (_zero_ ));
58+ 					return ;
59+ 				}
60+ 				break ;
61+ 
62+ 			case  PHP_ROUND_AWAY_FROM_ZERO :
63+ 				break ;
64+ 
65+ 			EMPTY_SWITCH_DEFAULT_CASE ()
66+ 		}
67+ 
68+ 		if  (bc_is_zero (num )) {
69+ 			* result  =  bc_copy_num (BCG (_zero_ ));
70+ 			return ;
71+ 		}
72+ 
73+ 		/* If precision is -3, it becomes 1000. */ 
74+ 		if  (UNEXPECTED (precision  ==  ZEND_LONG_MIN )) {
75+ 			* result  =  bc_new_num ((size_t ) ZEND_LONG_MAX  +  2 , 0 );
76+ 		} else  {
77+ 			* result  =  bc_new_num (- precision  +  1 , 0 );
78+ 		}
79+ 		(* result )-> n_value [0 ] =  1 ;
80+ 		(* result )-> n_sign  =  num -> n_sign ;
3881		return ;
3982	}
83+ 
4084	/* Just like bcadd('1', '1', 4) becomes '2.0000', it pads with zeros at the end if necessary. */ 
4185	if  (precision  >= 0  &&  num -> n_scale  <= precision ) {
4286		if  (num -> n_scale  ==  precision ) {
@@ -61,7 +105,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
61105	 * If the result of rounding is carried over, it will be added later, so first set it to 0 here. 
62106	 */ 
63107	if  (rounded_len  ==  0 ) {
64- 		* result  =  bc_copy_num ( BCG ( _zero_ ) );
108+ 		* result  =  bc_new_num ( 1 ,  0 );
65109	} else  {
66110		* result  =  bc_new_num (num -> n_len , precision  >  0  ? precision  : 0 );
67111		memcpy ((* result )-> n_value , num -> n_value , rounded_len );
0 commit comments