1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Saki Takamachi <saki@php.net>                               |
14    +----------------------------------------------------------------------+
15 */
16 
17 #include "bcmath.h"
18 #include "private.h"
19 #include <stddef.h>
20 
bc_floor_or_ceil(bc_num num,bool is_floor)21 bc_num bc_floor_or_ceil(bc_num num, bool is_floor)
22 {
23 	/*  Initialize result */
24 	bc_num result = bc_new_num(num->n_len, 0);
25 	result->n_sign = num->n_sign;
26 
27 	/* copy integer part */
28 	memcpy(result->n_value, num->n_value, num->n_len);
29 
30 	/* If the number is positive and we are flooring, then nothing else needs to be done.
31 	 * Similarly, if the number is negative and we are ceiling, then nothing else needs to be done. */
32 	if (num->n_scale == 0 || result->n_sign == (is_floor ? PLUS : MINUS)) {
33 		goto check_zero;
34 	}
35 
36 	/* check fractional part. */
37 	size_t count = num->n_scale;
38 	const char *nptr = num->n_value + num->n_len;
39 	while ((count > 0) && (*nptr == 0)) {
40 		count--;
41 		nptr++;
42 	}
43 
44 	/* If all digits past the decimal point are 0 */
45 	if (count == 0) {
46 		goto check_zero;
47 	}
48 
49 	/* Increment the absolute value of the result by 1 and add sign information */
50 	bc_num tmp = _bc_do_add(result, BCG(_one_));
51 	tmp->n_sign = result->n_sign;
52 	bc_free_num(&result);
53 	result = tmp;
54 
55 check_zero:
56 	if (bc_is_zero(result)) {
57 		result->n_sign = PLUS;
58 	}
59 
60 	return result;
61 }
62