xref: /php-src/ext/bcmath/libbcmath/src/long2num.c (revision fad899e5)
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 <stdbool.h>
19 #include "convert.h"
20 
21 #define BC_LONG_MAX_DIGITS (sizeof(LONG_MIN_DIGITS) - 1)
22 
bc_long2num(zend_long lval)23 bc_num bc_long2num(zend_long lval)
24 {
25 	bc_num num;
26 
27 	if (UNEXPECTED(lval == 0)) {
28 		num = bc_copy_num(BCG(_zero_));
29 		return num;
30 	}
31 
32 	bool negative = lval < 0;
33 	if (UNEXPECTED(lval == ZEND_LONG_MIN)) {
34 		num = bc_new_num_nonzeroed(BC_LONG_MAX_DIGITS, 0);
35 		const char *ptr = LONG_MIN_DIGITS;
36 		bc_copy_and_toggle_bcd(num->n_value, ptr, ptr + BC_LONG_MAX_DIGITS);
37 		num->n_sign = MINUS;
38 		return num;
39 	} else if (negative) {
40 		lval = -lval;
41 	}
42 
43 	zend_long tmp = lval;
44 	size_t len = 0;
45 	while (tmp > 0) {
46 		tmp /= BASE;
47 		len++;
48 	}
49 
50 	num = bc_new_num_nonzeroed(len, 0);
51 	char *ptr = num->n_value + len - 1;
52 	for (; len > 0; len--) {
53 		*ptr-- = lval % BASE;
54 		lval /= BASE;
55 	}
56 	num->n_sign = negative ? MINUS : PLUS;
57 
58 	return num;
59 }
60