aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-11 19:04:44 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-11 19:22:04 +0100
commit7f4daa4f5842b26c5f3e233819e583573eeebaf6 (patch)
tree4900aac83de9d35b8815095eca69e8206edaa0dc
parent1aeacefbb33f2590c875c9a3704e485a4a643898 (diff)
downloadbusybox-w32-7f4daa4f5842b26c5f3e233819e583573eeebaf6.tar.gz
busybox-w32-7f4daa4f5842b26c5f3e233819e583573eeebaf6.tar.bz2
busybox-w32-7f4daa4f5842b26c5f3e233819e583573eeebaf6.zip
bc: convert arithmetic calc functions to "z" logic
In order for magic macros to work, a bit of reordering was necessary. function old new delta zbc_program_modexp - 558 +558 zbc_program_assign - 448 +448 zbc_program_pushArray - 111 +111 zbc_num_s 239 237 -2 zbc_num_d 543 541 -2 zbc_num_binary 145 143 -2 zbc_num_a 443 441 -2 zbc_num_rem 95 91 -4 zbc_num_divmod 150 146 -4 zbc_num_m 269 257 -12 zbc_num_r 230 208 -22 zbc_num_printNum 447 417 -30 bc_program_exec 3960 3928 -32 zbc_num_p 434 399 -35 zbc_program_num 880 840 -40 zbc_num_k 913 852 -61 zbc_program_printStream 141 - -141 bc_program_assign 455 - -455 bc_program_modexp 668 - -668 ------------------------------------------------------------------------------ (add/remove: 3/3 grow/shrink: 0/13 up/down: 1117/-1512) Total: -395 bytes text data bss dec hex filename 982632 485 7296 990413 f1ccd busybox_old 982237 485 7296 990018 f1b42 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c779
1 files changed, 424 insertions, 355 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 3ab0bf3b7..5ede8598d 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -929,35 +929,94 @@ dc_parse_insts[] = {
929// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. 929// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo.
930// 930//
931#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP 931#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP
932# define ERRORS_ARE_FATAL 0
932# define ERRORFUNC /*nothing*/ 933# define ERRORFUNC /*nothing*/
933# define ERROR_RETURN(a) a 934# define ERROR_RETURN(a) a
934# define ERRORS_ARE_FATAL 0
935# define BC_STATUS BcStatus 935# define BC_STATUS BcStatus
936# define RETURN_STATUS(v) return (v) 936# define RETURN_STATUS(v) return (v)
937#else 937#else
938# define ERRORS_ARE_FATAL 1
938# define ERRORFUNC NORETURN 939# define ERRORFUNC NORETURN
939# define ERROR_RETURN(a) /*nothing*/ 940# define ERROR_RETURN(a) /*nothing*/
940# define ERRORS_ARE_FATAL 1
941# define BC_STATUS void 941# define BC_STATUS void
942# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) 942# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0)
943#endif 943#endif
944 944
945#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
946#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
947#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
948//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
949static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b)
950{
951 return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
952}
953//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
954static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale)
955{
956 return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1;
957}
958
945typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; 959typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC;
946 960
947typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; 961typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC;
948 962
949static BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 963static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
950static BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 964 BcNumBinaryOp op, size_t req);
951static BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 965static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
952static BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 966static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
953static BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 967static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
954static BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; 968static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
955static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, 969static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
956 size_t scale); 970static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
971
972static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
973{
974 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s;
975 (void) scale;
976 RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)));
977}
978
979static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
980{
981 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a;
982 (void) scale;
983 RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)));
984}
985
986static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
987{
988 size_t req = BC_NUM_MREQ(a, b, scale);
989 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req));
990}
991
992static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
993{
994 size_t req = BC_NUM_MREQ(a, b, scale);
995 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req));
996}
997
998static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
999{
1000 size_t req = BC_NUM_MREQ(a, b, scale);
1001 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req));
1002}
1003
1004static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1005{
1006 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1));
1007}
957 1008
958static const BcNumBinaryOp zbc_program_ops[] = { 1009static const BcNumBinaryOp zbc_program_ops[] = {
959 zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, 1010 zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub,
960}; 1011};
1012#if ERRORS_ARE_FATAL
1013# define zbc_num_add(...) (zbc_num_add(__VA_ARGS__), BC_STATUS_SUCCESS)
1014# define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__), BC_STATUS_SUCCESS)
1015# define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__), BC_STATUS_SUCCESS)
1016# define zbc_num_div(...) (zbc_num_div(__VA_ARGS__), BC_STATUS_SUCCESS)
1017# define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__), BC_STATUS_SUCCESS)
1018# define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__), BC_STATUS_SUCCESS)
1019#endif
961 1020
962static void fflush_and_check(void) 1021static void fflush_and_check(void)
963{ 1022{
@@ -1527,20 +1586,6 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
1527 } 1586 }
1528} 1587}
1529 1588
1530#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
1531#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
1532#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
1533//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
1534static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b)
1535{
1536 return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
1537}
1538//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
1539static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale)
1540{
1541 return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1;
1542}
1543
1544static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) 1589static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
1545{ 1590{
1546 size_t i; 1591 size_t i;
@@ -1692,7 +1737,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places)
1692# define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) 1737# define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS)
1693#endif 1738#endif
1694 1739
1695static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale) 1740static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
1696{ 1741{
1697 BcNum one; 1742 BcNum one;
1698 BcDig num[2]; 1743 BcDig num[2];
@@ -1701,10 +1746,13 @@ static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
1701 one.num = num; 1746 one.num = num;
1702 bc_num_one(&one); 1747 bc_num_one(&one);
1703 1748
1704 return zbc_num_div(&one, a, b, scale); 1749 RETURN_STATUS(zbc_num_div(&one, a, b, scale));
1705} 1750}
1751#if ERRORS_ARE_FATAL
1752# define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__), BC_STATUS_SUCCESS)
1753#endif
1706 1754
1707static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) 1755static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1708{ 1756{
1709 BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; 1757 BcDig *ptr, *ptr_a, *ptr_b, *ptr_c;
1710 size_t i, max, min_rdx, min_int, diff, a_int, b_int; 1758 size_t i, max, min_rdx, min_int, diff, a_int, b_int;
@@ -1716,11 +1764,11 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_
1716 if (a->len == 0) { 1764 if (a->len == 0) {
1717 bc_num_copy(c, b); 1765 bc_num_copy(c, b);
1718 if (sub && c->len) c->neg = !c->neg; 1766 if (sub && c->len) c->neg = !c->neg;
1719 return BC_STATUS_SUCCESS; 1767 RETURN_STATUS(BC_STATUS_SUCCESS);
1720 } 1768 }
1721 else if (b->len == 0) { 1769 if (b->len == 0) {
1722 bc_num_copy(c, a); 1770 bc_num_copy(c, a);
1723 return BC_STATUS_SUCCESS; 1771 RETURN_STATUS(BC_STATUS_SUCCESS);
1724 } 1772 }
1725 1773
1726 c->neg = a->neg; 1774 c->neg = a->neg;
@@ -1772,10 +1820,10 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_
1772 1820
1773 if (carry != 0) c->num[c->len++] = (BcDig) carry; 1821 if (carry != 0) c->num[c->len++] = (BcDig) carry;
1774 1822
1775 return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() 1823 RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
1776} 1824}
1777 1825
1778static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) 1826static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1779{ 1827{
1780 ssize_t cmp; 1828 ssize_t cmp;
1781 BcNum *minuend, *subtrahend; 1829 BcNum *minuend, *subtrahend;
@@ -1788,11 +1836,11 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
1788 if (a->len == 0) { 1836 if (a->len == 0) {
1789 bc_num_copy(c, b); 1837 bc_num_copy(c, b);
1790 if (sub && c->len) c->neg = !c->neg; 1838 if (sub && c->len) c->neg = !c->neg;
1791 return BC_STATUS_SUCCESS; 1839 RETURN_STATUS(BC_STATUS_SUCCESS);
1792 } 1840 }
1793 else if (b->len == 0) { 1841 if (b->len == 0) {
1794 bc_num_copy(c, a); 1842 bc_num_copy(c, a);
1795 return BC_STATUS_SUCCESS; 1843 RETURN_STATUS(BC_STATUS_SUCCESS);
1796 } 1844 }
1797 1845
1798 aneg = a->neg; 1846 aneg = a->neg;
@@ -1806,9 +1854,9 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
1806 1854
1807 if (cmp == 0) { 1855 if (cmp == 0) {
1808 bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx)); 1856 bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx));
1809 return BC_STATUS_SUCCESS; 1857 RETURN_STATUS(BC_STATUS_SUCCESS);
1810 } 1858 }
1811 else if (cmp > 0) { 1859 if (cmp > 0) {
1812 neg = a->neg; 1860 neg = a->neg;
1813 minuend = a; 1861 minuend = a;
1814 subtrahend = b; 1862 subtrahend = b;
@@ -1834,11 +1882,14 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
1834 1882
1835 bc_num_clean(c); 1883 bc_num_clean(c);
1836 1884
1837 return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() 1885 RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
1838} 1886}
1839 1887
1840static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, 1888static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b,
1841 BcNum *restrict c) 1889 BcNum *restrict c)
1890#if ERRORS_ARE_FATAL
1891# define zbc_num_k(...) (zbc_num_k(__VA_ARGS__), BC_STATUS_SUCCESS)
1892#endif
1842{ 1893{
1843 BcStatus s; 1894 BcStatus s;
1844 size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; 1895 size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2;
@@ -1847,12 +1898,12 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b,
1847 1898
1848 if (a->len == 0 || b->len == 0) { 1899 if (a->len == 0 || b->len == 0) {
1849 bc_num_zero(c); 1900 bc_num_zero(c);
1850 return BC_STATUS_SUCCESS; 1901 RETURN_STATUS(BC_STATUS_SUCCESS);
1851 } 1902 }
1852 aone = BC_NUM_ONE(a); 1903 aone = BC_NUM_ONE(a);
1853 if (aone || BC_NUM_ONE(b)) { 1904 if (aone || BC_NUM_ONE(b)) {
1854 bc_num_copy(c, aone ? b : a); 1905 bc_num_copy(c, aone ? b : a);
1855 return BC_STATUS_SUCCESS; 1906 RETURN_STATUS(BC_STATUS_SUCCESS);
1856 } 1907 }
1857 1908
1858 if (a->len + b->len < BC_NUM_KARATSUBA_LEN || 1909 if (a->len + b->len < BC_NUM_KARATSUBA_LEN ||
@@ -1880,14 +1931,16 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b,
1880 c->num[i + j] += (BcDig) carry; 1931 c->num[i + j] += (BcDig) carry;
1881 len = BC_MAX(len, i + j + !!carry); 1932 len = BC_MAX(len, i + j + !!carry);
1882 1933
1934#if ENABLE_FEATURE_BC_SIGNALS
1883 // a=2^1000000 1935 // a=2^1000000
1884 // a*a <- without check below, this will not be interruptible 1936 // a*a <- without check below, this will not be interruptible
1885 if (G_interrupt) return BC_STATUS_FAILURE; 1937 if (G_interrupt) return BC_STATUS_FAILURE;
1938#endif
1886 } 1939 }
1887 1940
1888 c->len = len; 1941 c->len = len;
1889 1942
1890 return BC_STATUS_SUCCESS; 1943 RETURN_STATUS(BC_STATUS_SUCCESS);
1891 } 1944 }
1892 1945
1893 bc_num_init(&l1, max); 1946 bc_num_init(&l1, max);
@@ -1940,10 +1993,10 @@ err:
1940 bc_num_free(&l2); 1993 bc_num_free(&l2);
1941 bc_num_free(&h1); 1994 bc_num_free(&h1);
1942 bc_num_free(&l1); 1995 bc_num_free(&l1);
1943 return s; 1996 RETURN_STATUS(s);
1944} 1997}
1945 1998
1946static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) 1999static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1947{ 2000{
1948 BcStatus s; 2001 BcStatus s;
1949 BcNum cpa, cpb; 2002 BcNum cpa, cpb;
@@ -1982,10 +2035,13 @@ static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_
1982err: 2035err:
1983 bc_num_free(&cpb); 2036 bc_num_free(&cpb);
1984 bc_num_free(&cpa); 2037 bc_num_free(&cpa);
1985 return s; 2038 RETURN_STATUS(s);
1986} 2039}
2040#if ERRORS_ARE_FATAL
2041# define zbc_num_m(...) (zbc_num_m(__VA_ARGS__), BC_STATUS_SUCCESS)
2042#endif
1987 2043
1988static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) 2044static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1989{ 2045{
1990 BcStatus s = BC_STATUS_SUCCESS; 2046 BcStatus s = BC_STATUS_SUCCESS;
1991 BcDig *n, *p, q; 2047 BcDig *n, *p, q;
@@ -1994,15 +2050,15 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
1994 bool zero = true; 2050 bool zero = true;
1995 2051
1996 if (b->len == 0) 2052 if (b->len == 0)
1997 return bc_error("divide by zero"); 2053 RETURN_STATUS(bc_error("divide by zero"));
1998 else if (a->len == 0) { 2054 if (a->len == 0) {
1999 bc_num_setToZero(c, scale); 2055 bc_num_setToZero(c, scale);
2000 return BC_STATUS_SUCCESS; 2056 RETURN_STATUS(BC_STATUS_SUCCESS);
2001 } 2057 }
2002 else if (BC_NUM_ONE(b)) { 2058 if (BC_NUM_ONE(b)) {
2003 bc_num_copy(c, a); 2059 bc_num_copy(c, a);
2004 bc_num_retireMul(c, scale, a->neg, b->neg); 2060 bc_num_retireMul(c, scale, a->neg, b->neg);
2005 return BC_STATUS_SUCCESS; 2061 RETURN_STATUS(BC_STATUS_SUCCESS);
2006 } 2062 }
2007 2063
2008 bc_num_init(&cp, BC_NUM_MREQ(a, b, scale)); 2064 bc_num_init(&cp, BC_NUM_MREQ(a, b, scale));
@@ -2042,6 +2098,7 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
2042 for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) 2098 for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
2043 bc_num_subArrays(n, p, len); 2099 bc_num_subArrays(n, p, len);
2044 c->num[i] = q; 2100 c->num[i] = q;
2101#if ENABLE_FEATURE_BC_SIGNALS
2045 // a=2^100000 2102 // a=2^100000
2046 // scale=40000 2103 // scale=40000
2047 // 1/a <- without check below, this will not be interruptible 2104 // 1/a <- without check below, this will not be interruptible
@@ -2049,15 +2106,19 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
2049 s = BC_STATUS_FAILURE; 2106 s = BC_STATUS_FAILURE;
2050 break; 2107 break;
2051 } 2108 }
2109#endif
2052 } 2110 }
2053 2111
2054 bc_num_retireMul(c, scale, a->neg, b->neg); 2112 bc_num_retireMul(c, scale, a->neg, b->neg);
2055 bc_num_free(&cp); 2113 bc_num_free(&cp);
2056 2114
2057 return s; 2115 RETURN_STATUS(s);
2058} 2116}
2117#if ERRORS_ARE_FATAL
2118# define zbc_num_d(...) (zbc_num_d(__VA_ARGS__), BC_STATUS_SUCCESS)
2119#endif
2059 2120
2060static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, 2121static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
2061 BcNum *restrict d, size_t scale, size_t ts) 2122 BcNum *restrict d, size_t scale, size_t ts)
2062{ 2123{
2063 BcStatus s; 2124 BcStatus s;
@@ -2065,11 +2126,11 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
2065 bool neg; 2126 bool neg;
2066 2127
2067 if (b->len == 0) 2128 if (b->len == 0)
2068 return bc_error("divide by zero"); 2129 RETURN_STATUS(bc_error("divide by zero"));
2069 2130
2070 if (a->len == 0) { 2131 if (a->len == 0) {
2071 bc_num_setToZero(d, ts); 2132 bc_num_setToZero(d, ts);
2072 return BC_STATUS_SUCCESS; 2133 RETURN_STATUS(BC_STATUS_SUCCESS);
2073 } 2134 }
2074 2135
2075 bc_num_init(&temp, d->cap); 2136 bc_num_init(&temp, d->cap);
@@ -2091,10 +2152,13 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
2091 2152
2092err: 2153err:
2093 bc_num_free(&temp); 2154 bc_num_free(&temp);
2094 return s; 2155 RETURN_STATUS(s);
2095} 2156}
2157#if ERRORS_ARE_FATAL
2158# define zbc_num_r(...) (zbc_num_r(__VA_ARGS__), BC_STATUS_SUCCESS)
2159#endif
2096 2160
2097static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) 2161static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
2098{ 2162{
2099 BcStatus s; 2163 BcStatus s;
2100 BcNum c1; 2164 BcNum c1;
@@ -2104,10 +2168,13 @@ static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, siz
2104 s = zbc_num_r(a, b, &c1, c, scale, ts); 2168 s = zbc_num_r(a, b, &c1, c, scale, ts);
2105 bc_num_free(&c1); 2169 bc_num_free(&c1);
2106 2170
2107 return s; 2171 RETURN_STATUS(s);
2108} 2172}
2173#if ERRORS_ARE_FATAL
2174# define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__), BC_STATUS_SUCCESS)
2175#endif
2109 2176
2110static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) 2177static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
2111{ 2178{
2112 BcStatus s = BC_STATUS_SUCCESS; 2179 BcStatus s = BC_STATUS_SUCCESS;
2113 BcNum copy; 2180 BcNum copy;
@@ -2115,29 +2182,29 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_
2115 size_t i, powrdx, resrdx; 2182 size_t i, powrdx, resrdx;
2116 bool neg, zero; 2183 bool neg, zero;
2117 2184
2118 if (b->rdx) return bc_error("non integer number"); 2185 if (b->rdx) RETURN_STATUS(bc_error("non integer number"));
2119 2186
2120 if (b->len == 0) { 2187 if (b->len == 0) {
2121 bc_num_one(c); 2188 bc_num_one(c);
2122 return BC_STATUS_SUCCESS; 2189 RETURN_STATUS(BC_STATUS_SUCCESS);
2123 } 2190 }
2124 else if (a->len == 0) { 2191 if (a->len == 0) {
2125 bc_num_setToZero(c, scale); 2192 bc_num_setToZero(c, scale);
2126 return BC_STATUS_SUCCESS; 2193 RETURN_STATUS(BC_STATUS_SUCCESS);
2127 } 2194 }
2128 else if (BC_NUM_ONE(b)) { 2195 if (BC_NUM_ONE(b)) {
2129 if (!b->neg) 2196 if (!b->neg)
2130 bc_num_copy(c, a); 2197 bc_num_copy(c, a);
2131 else 2198 else
2132 s = zbc_num_inv(a, c, scale); 2199 s = zbc_num_inv(a, c, scale);
2133 return s; 2200 RETURN_STATUS(s);
2134 } 2201 }
2135 2202
2136 neg = b->neg; 2203 neg = b->neg;
2137 b->neg = false; 2204 b->neg = false;
2138 2205
2139 s = zbc_num_ulong(b, &pow); 2206 s = zbc_num_ulong(b, &pow);
2140 if (s) return s; 2207 if (s) RETURN_STATUS(s);
2141 2208
2142 bc_num_init(&copy, a->len); 2209 bc_num_init(&copy, a->len);
2143 bc_num_copy(&copy, a); 2210 bc_num_copy(&copy, a);
@@ -2195,10 +2262,13 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_
2195 2262
2196err: 2263err:
2197 bc_num_free(&copy); 2264 bc_num_free(&copy);
2198 return s; 2265 RETURN_STATUS(s);
2199} 2266}
2267#if ERRORS_ARE_FATAL
2268# define zbc_num_p(...) (zbc_num_p(__VA_ARGS__), BC_STATUS_SUCCESS)
2269#endif
2200 2270
2201static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, 2271static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
2202 BcNumBinaryOp op, size_t req) 2272 BcNumBinaryOp op, size_t req)
2203{ 2273{
2204 BcStatus s; 2274 BcStatus s;
@@ -2228,183 +2298,19 @@ static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
2228 else 2298 else
2229 bc_num_expand(c, req); 2299 bc_num_expand(c, req);
2230 2300
2301#if !ERRORS_ARE_FATAL
2231 s = op(ptr_a, ptr_b, c, scale); 2302 s = op(ptr_a, ptr_b, c, scale);
2232 2303#else
2233 if (init) bc_num_free(&num2); 2304 op(ptr_a, ptr_b, c, scale);
2234 2305 s = BC_STATUS_SUCCESS;
2235 return s;
2236}
2237
2238static void bc_num_printNewline(void)
2239{
2240 if (G.prog.nchars == G.prog.len - 1) {
2241 bb_putchar('\\');
2242 bb_putchar('\n');
2243 G.prog.nchars = 0;
2244 }
2245}
2246
2247#if ENABLE_DC
2248static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix)
2249{
2250 (void) radix;
2251 bb_putchar((char) num);
2252 G.prog.nchars += width;
2253}
2254#endif
2255
2256static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix)
2257{
2258 size_t exp, pow;
2259
2260 bc_num_printNewline();
2261 bb_putchar(radix ? '.' : ' ');
2262 ++G.prog.nchars;
2263
2264 bc_num_printNewline();
2265 for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
2266 continue;
2267
2268 for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) {
2269 size_t dig;
2270 bc_num_printNewline();
2271 dig = num / pow;
2272 num -= dig * pow;
2273 bb_putchar(((char) dig) + '0');
2274 }
2275}
2276
2277static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix)
2278{
2279 if (radix) {
2280 bc_num_printNewline();
2281 bb_putchar('.');
2282 G.prog.nchars += 1;
2283 }
2284
2285 bc_num_printNewline();
2286 bb_putchar(bb_hexdigits_upcase[num]);
2287 G.prog.nchars += width;
2288}
2289
2290static void bc_num_printDecimal(BcNum *n)
2291{
2292 size_t i, rdx = n->rdx - 1;
2293
2294 if (n->neg) bb_putchar('-');
2295 G.prog.nchars += n->neg;
2296
2297 for (i = n->len - 1; i < n->len; --i)
2298 bc_num_printHex((size_t) n->num[i], 1, i == rdx);
2299}
2300
2301static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print)
2302{
2303 BcStatus s;
2304 BcVec stack;
2305 BcNum intp, fracp, digit, frac_len;
2306 unsigned long dig, *ptr;
2307 size_t i;
2308 bool radix;
2309
2310 if (n->len == 0) {
2311 print(0, width, false);
2312 RETURN_STATUS(BC_STATUS_SUCCESS);
2313 }
2314
2315 bc_vec_init(&stack, sizeof(long), NULL);
2316 bc_num_init(&intp, n->len);
2317 bc_num_init(&fracp, n->rdx);
2318 bc_num_init(&digit, width);
2319 bc_num_init(&frac_len, BC_NUM_INT(n));
2320 bc_num_copy(&intp, n);
2321 bc_num_one(&frac_len);
2322
2323 bc_num_truncate(&intp, intp.rdx);
2324 s = zbc_num_sub(n, &intp, &fracp, 0);
2325 if (s) goto err;
2326
2327 while (intp.len != 0) {
2328 s = zbc_num_divmod(&intp, base, &intp, &digit, 0);
2329 if (s) goto err;
2330 s = zbc_num_ulong(&digit, &dig);
2331 if (s) goto err;
2332 bc_vec_push(&stack, &dig);
2333 }
2334
2335 for (i = 0; i < stack.len; ++i) {
2336 ptr = bc_vec_item_rev(&stack, i);
2337 print(*ptr, width, false);
2338 }
2339
2340 if (!n->rdx) goto err;
2341
2342 for (radix = true; frac_len.len <= n->rdx; radix = false) {
2343 s = zbc_num_mul(&fracp, base, &fracp, n->rdx);
2344 if (s) goto err;
2345 s = zbc_num_ulong(&fracp, &dig);
2346 if (s) goto err;
2347 bc_num_ulong2num(&intp, dig);
2348 s = zbc_num_sub(&fracp, &intp, &fracp, 0);
2349 if (s) goto err;
2350 print(dig, width, radix);
2351 s = zbc_num_mul(&frac_len, base, &frac_len, 0);
2352 if (s) goto err;
2353 }
2354
2355err:
2356 bc_num_free(&frac_len);
2357 bc_num_free(&digit);
2358 bc_num_free(&fracp);
2359 bc_num_free(&intp);
2360 bc_vec_free(&stack);
2361 RETURN_STATUS(s);
2362}
2363#if ERRORS_ARE_FATAL
2364# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS)
2365#endif 2306#endif
2366 2307
2367static BC_STATUS zbc_num_printBase(BcNum *n) 2308 if (init) bc_num_free(&num2);
2368{
2369 BcStatus s;
2370 size_t width, i;
2371 BcNumDigitOp print;
2372 bool neg = n->neg;
2373
2374 if (neg) {
2375 bb_putchar('-');
2376 G.prog.nchars++;
2377 }
2378
2379 n->neg = false;
2380
2381 if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
2382 width = 1;
2383 print = bc_num_printHex;
2384 }
2385 else {
2386 for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width)
2387 continue;
2388 print = bc_num_printDigits;
2389 }
2390
2391 s = zbc_num_printNum(n, &G.prog.ob, width, print);
2392 n->neg = neg;
2393 2309
2394 RETURN_STATUS(s); 2310 RETURN_STATUS(s);
2395} 2311}
2396#if ERRORS_ARE_FATAL 2312#if ERRORS_ARE_FATAL
2397# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) 2313# define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__), BC_STATUS_SUCCESS)
2398#endif
2399
2400#if ENABLE_DC
2401static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base)
2402{
2403 RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar));
2404}
2405#if ERRORS_ARE_FATAL
2406# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS)
2407#endif
2408#endif 2314#endif
2409 2315
2410static bool bc_num_strValid(const char *val, size_t base) 2316static bool bc_num_strValid(const char *val, size_t base)
@@ -2557,70 +2463,7 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base,
2557# define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) 2463# define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS)
2558#endif 2464#endif
2559 2465
2560static BC_STATUS zbc_num_print(BcNum *n, bool newline) 2466static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2561{
2562 BcStatus s = BC_STATUS_SUCCESS;
2563
2564 bc_num_printNewline();
2565
2566 if (n->len == 0) {
2567 bb_putchar('0');
2568 ++G.prog.nchars;
2569 }
2570 else if (G.prog.ob_t == 10)
2571 bc_num_printDecimal(n);
2572 else
2573 s = zbc_num_printBase(n);
2574
2575 if (newline) {
2576 bb_putchar('\n');
2577 G.prog.nchars = 0;
2578 }
2579
2580 RETURN_STATUS(s);
2581}
2582#if ERRORS_ARE_FATAL
2583# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS)
2584#endif
2585
2586static FAST_FUNC BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2587{
2588 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s;
2589 (void) scale;
2590 return zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b));
2591}
2592
2593static FAST_FUNC BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2594{
2595 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a;
2596 (void) scale;
2597 return zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b));
2598}
2599
2600static FAST_FUNC BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2601{
2602 size_t req = BC_NUM_MREQ(a, b, scale);
2603 return zbc_num_binary(a, b, c, scale, zbc_num_m, req);
2604}
2605
2606static FAST_FUNC BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2607{
2608 size_t req = BC_NUM_MREQ(a, b, scale);
2609 return zbc_num_binary(a, b, c, scale, zbc_num_d, req);
2610}
2611
2612static FAST_FUNC BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2613{
2614 size_t req = BC_NUM_MREQ(a, b, scale);
2615 return zbc_num_binary(a, b, c, scale, zbc_num_rem, req);
2616}
2617
2618static FAST_FUNC BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2619{
2620 return zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1);
2621}
2622
2623static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2624{ 2467{
2625 BcStatus s; 2468 BcStatus s;
2626 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; 2469 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
@@ -2632,14 +2475,14 @@ static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2632 2475
2633 if (a->len == 0) { 2476 if (a->len == 0) {
2634 bc_num_setToZero(b, scale); 2477 bc_num_setToZero(b, scale);
2635 return BC_STATUS_SUCCESS; 2478 RETURN_STATUS(BC_STATUS_SUCCESS);
2636 } 2479 }
2637 else if (a->neg) 2480 else if (a->neg)
2638 return bc_error("negative number"); 2481 RETURN_STATUS(bc_error("negative number"));
2639 else if (BC_NUM_ONE(a)) { 2482 else if (BC_NUM_ONE(a)) {
2640 bc_num_one(b); 2483 bc_num_one(b);
2641 bc_num_extend(b, scale); 2484 bc_num_extend(b, scale);
2642 return BC_STATUS_SUCCESS; 2485 RETURN_STATUS(BC_STATUS_SUCCESS);
2643 } 2486 }
2644 2487
2645 scale = BC_MAX(scale, a->rdx) + 1; 2488 scale = BC_MAX(scale, a->rdx) + 1;
@@ -2719,10 +2562,13 @@ err:
2719 bc_num_free(&half); 2562 bc_num_free(&half);
2720 bc_num_free(&num2); 2563 bc_num_free(&num2);
2721 bc_num_free(&num1); 2564 bc_num_free(&num1);
2722 return s; 2565 RETURN_STATUS(s);
2723} 2566}
2567#if ERRORS_ARE_FATAL
2568# define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__), BC_STATUS_SUCCESS)
2569#endif
2724 2570
2725static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, 2571static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2726 size_t scale) 2572 size_t scale)
2727{ 2573{
2728 BcStatus s; 2574 BcStatus s;
@@ -2745,21 +2591,24 @@ static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2745 2591
2746 if (init) bc_num_free(&num2); 2592 if (init) bc_num_free(&num2);
2747 2593
2748 return s; 2594 RETURN_STATUS(s);
2749} 2595}
2596#if ERRORS_ARE_FATAL
2597# define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__), BC_STATUS_SUCCESS)
2598#endif
2750 2599
2751#if ENABLE_DC 2600#if ENABLE_DC
2752static BcStatus zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) 2601static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2753{ 2602{
2754 BcStatus s; 2603 BcStatus s;
2755 BcNum base, exp, two, temp; 2604 BcNum base, exp, two, temp;
2756 2605
2757 if (c->len == 0) 2606 if (c->len == 0)
2758 return bc_error("divide by zero"); 2607 RETURN_STATUS(bc_error("divide by zero"));
2759 if (a->rdx || b->rdx || c->rdx) 2608 if (a->rdx || b->rdx || c->rdx)
2760 return bc_error("non integer number"); 2609 RETURN_STATUS(bc_error("non integer number"));
2761 if (b->neg) 2610 if (b->neg)
2762 return bc_error("negative number"); 2611 RETURN_STATUS(bc_error("negative number"));
2763 2612
2764 bc_num_expand(d, c->len); 2613 bc_num_expand(d, c->len);
2765 bc_num_init(&base, c->len); 2614 bc_num_init(&base, c->len);
@@ -2798,8 +2647,11 @@ err:
2798 bc_num_free(&two); 2647 bc_num_free(&two);
2799 bc_num_free(&exp); 2648 bc_num_free(&exp);
2800 bc_num_free(&base); 2649 bc_num_free(&base);
2801 return s; 2650 RETURN_STATUS(s);
2802} 2651}
2652#if ERRORS_ARE_FATAL
2653# define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__), BC_STATUS_SUCCESS)
2654#endif
2803#endif // ENABLE_DC 2655#endif // ENABLE_DC
2804 2656
2805#if ENABLE_BC 2657#if ENABLE_BC
@@ -5630,7 +5482,11 @@ static BcStatus bc_program_op(char inst)
5630 if (s) return s; 5482 if (s) return s;
5631 bc_num_init_DEF_SIZE(&res.d.n); 5483 bc_num_init_DEF_SIZE(&res.d.n);
5632 5484
5633 s = zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); 5485 s = BC_STATUS_SUCCESS;
5486#if !ERRORS_ARE_FATAL
5487 s =
5488#endif
5489 zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
5634 if (s) goto err; 5490 if (s) goto err;
5635 bc_program_binOpRetire(&res); 5491 bc_program_binOpRetire(&res);
5636 5492
@@ -5810,6 +5666,204 @@ static void bc_program_printString(const char *str)
5810 } 5666 }
5811} 5667}
5812 5668
5669static void bc_num_printNewline(void)
5670{
5671 if (G.prog.nchars == G.prog.len - 1) {
5672 bb_putchar('\\');
5673 bb_putchar('\n');
5674 G.prog.nchars = 0;
5675 }
5676}
5677
5678#if ENABLE_DC
5679static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix)
5680{
5681 (void) radix;
5682 bb_putchar((char) num);
5683 G.prog.nchars += width;
5684}
5685#endif
5686
5687static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix)
5688{
5689 size_t exp, pow;
5690
5691 bc_num_printNewline();
5692 bb_putchar(radix ? '.' : ' ');
5693 ++G.prog.nchars;
5694
5695 bc_num_printNewline();
5696 for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
5697 continue;
5698
5699 for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) {
5700 size_t dig;
5701 bc_num_printNewline();
5702 dig = num / pow;
5703 num -= dig * pow;
5704 bb_putchar(((char) dig) + '0');
5705 }
5706}
5707
5708static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix)
5709{
5710 if (radix) {
5711 bc_num_printNewline();
5712 bb_putchar('.');
5713 G.prog.nchars += 1;
5714 }
5715
5716 bc_num_printNewline();
5717 bb_putchar(bb_hexdigits_upcase[num]);
5718 G.prog.nchars += width;
5719}
5720
5721static void bc_num_printDecimal(BcNum *n)
5722{
5723 size_t i, rdx = n->rdx - 1;
5724
5725 if (n->neg) bb_putchar('-');
5726 G.prog.nchars += n->neg;
5727
5728 for (i = n->len - 1; i < n->len; --i)
5729 bc_num_printHex((size_t) n->num[i], 1, i == rdx);
5730}
5731
5732static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print)
5733{
5734 BcStatus s;
5735 BcVec stack;
5736 BcNum intp, fracp, digit, frac_len;
5737 unsigned long dig, *ptr;
5738 size_t i;
5739 bool radix;
5740
5741 if (n->len == 0) {
5742 print(0, width, false);
5743 RETURN_STATUS(BC_STATUS_SUCCESS);
5744 }
5745
5746 bc_vec_init(&stack, sizeof(long), NULL);
5747 bc_num_init(&intp, n->len);
5748 bc_num_init(&fracp, n->rdx);
5749 bc_num_init(&digit, width);
5750 bc_num_init(&frac_len, BC_NUM_INT(n));
5751 bc_num_copy(&intp, n);
5752 bc_num_one(&frac_len);
5753
5754 bc_num_truncate(&intp, intp.rdx);
5755 s = zbc_num_sub(n, &intp, &fracp, 0);
5756 if (s) goto err;
5757
5758 while (intp.len != 0) {
5759 s = zbc_num_divmod(&intp, base, &intp, &digit, 0);
5760 if (s) goto err;
5761 s = zbc_num_ulong(&digit, &dig);
5762 if (s) goto err;
5763 bc_vec_push(&stack, &dig);
5764 }
5765
5766 for (i = 0; i < stack.len; ++i) {
5767 ptr = bc_vec_item_rev(&stack, i);
5768 print(*ptr, width, false);
5769 }
5770
5771 if (!n->rdx) goto err;
5772
5773 for (radix = true; frac_len.len <= n->rdx; radix = false) {
5774 s = zbc_num_mul(&fracp, base, &fracp, n->rdx);
5775 if (s) goto err;
5776 s = zbc_num_ulong(&fracp, &dig);
5777 if (s) goto err;
5778 bc_num_ulong2num(&intp, dig);
5779 s = zbc_num_sub(&fracp, &intp, &fracp, 0);
5780 if (s) goto err;
5781 print(dig, width, radix);
5782 s = zbc_num_mul(&frac_len, base, &frac_len, 0);
5783 if (s) goto err;
5784 }
5785
5786err:
5787 bc_num_free(&frac_len);
5788 bc_num_free(&digit);
5789 bc_num_free(&fracp);
5790 bc_num_free(&intp);
5791 bc_vec_free(&stack);
5792 RETURN_STATUS(s);
5793}
5794#if ERRORS_ARE_FATAL
5795# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS)
5796#endif
5797
5798static BC_STATUS zbc_num_printBase(BcNum *n)
5799{
5800 BcStatus s;
5801 size_t width, i;
5802 BcNumDigitOp print;
5803 bool neg = n->neg;
5804
5805 if (neg) {
5806 bb_putchar('-');
5807 G.prog.nchars++;
5808 }
5809
5810 n->neg = false;
5811
5812 if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
5813 width = 1;
5814 print = bc_num_printHex;
5815 }
5816 else {
5817 for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width)
5818 continue;
5819 print = bc_num_printDigits;
5820 }
5821
5822 s = zbc_num_printNum(n, &G.prog.ob, width, print);
5823 n->neg = neg;
5824
5825 RETURN_STATUS(s);
5826}
5827#if ERRORS_ARE_FATAL
5828# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS)
5829#endif
5830
5831#if ENABLE_DC
5832static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base)
5833{
5834 RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar));
5835}
5836#if ERRORS_ARE_FATAL
5837# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS)
5838#endif
5839#endif
5840
5841static BC_STATUS zbc_num_print(BcNum *n, bool newline)
5842{
5843 BcStatus s = BC_STATUS_SUCCESS;
5844
5845 bc_num_printNewline();
5846
5847 if (n->len == 0) {
5848 bb_putchar('0');
5849 ++G.prog.nchars;
5850 }
5851 else if (G.prog.ob_t == 10)
5852 bc_num_printDecimal(n);
5853 else
5854 s = zbc_num_printBase(n);
5855
5856 if (newline) {
5857 bb_putchar('\n');
5858 G.prog.nchars = 0;
5859 }
5860
5861 RETURN_STATUS(s);
5862}
5863#if ERRORS_ARE_FATAL
5864# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS)
5865#endif
5866
5813static BC_STATUS zbc_program_print(char inst, size_t idx) 5867static BC_STATUS zbc_program_print(char inst, size_t idx)
5814{ 5868{
5815 BcStatus s; 5869 BcStatus s;
@@ -6022,7 +6076,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var)
6022# define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) 6076# define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS)
6023#endif 6077#endif
6024 6078
6025static BcStatus bc_program_assign(char inst) 6079static BC_STATUS zbc_program_assign(char inst)
6026{ 6080{
6027 BcStatus s; 6081 BcStatus s;
6028 BcResult *left, *right, res; 6082 BcResult *left, *right, res;
@@ -6030,7 +6084,7 @@ static BcStatus bc_program_assign(char inst)
6030 bool assign = inst == BC_INST_ASSIGN, ib, sc; 6084 bool assign = inst == BC_INST_ASSIGN, ib, sc;
6031 6085
6032 s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); 6086 s = zbc_program_binOpPrep(&left, &l, &right, &r, assign);
6033 if (s) return s; 6087 if (s) RETURN_STATUS(s);
6034 6088
6035 ib = left->t == BC_RESULT_IBASE; 6089 ib = left->t == BC_RESULT_IBASE;
6036 sc = left->t == BC_RESULT_SCALE; 6090 sc = left->t == BC_RESULT_SCALE;
@@ -6042,30 +6096,34 @@ static BcStatus bc_program_assign(char inst)
6042 BcVec *v; 6096 BcVec *v;
6043 6097
6044 if (left->t != BC_RESULT_VAR) 6098 if (left->t != BC_RESULT_VAR)
6045 return bc_error_variable_is_wrong_type(); 6099 RETURN_STATUS(bc_error_variable_is_wrong_type());
6046 v = bc_program_search(left->d.id.name, true); 6100 v = bc_program_search(left->d.id.name, true);
6047 6101
6048 return zbc_program_assignStr(right, v, false); 6102 RETURN_STATUS(zbc_program_assignStr(right, v, false));
6049 } 6103 }
6050#endif 6104#endif
6051 6105
6052 if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) 6106 if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP)
6053 return bc_error("bad assignment:" 6107 RETURN_STATUS(("bad assignment:"
6054 " left side must be scale," 6108 " left side must be scale,"
6055 " ibase, obase, last, var," 6109 " ibase, obase, last, var,"
6056 " or array element" 6110 " or array element"
6057 ); 6111 ));
6058 6112
6059#if ENABLE_BC 6113#if ENABLE_BC
6060 if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) 6114 if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
6061 return bc_error("divide by zero"); 6115 RETURN_STATUS(bc_error("divide by zero"));
6062 6116
6063 if (assign) 6117 if (assign)
6064 bc_num_copy(l, r); 6118 bc_num_copy(l, r);
6065 else 6119 else {
6066 s = zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); 6120 s = BC_STATUS_SUCCESS;
6067 6121#if !ERRORS_ARE_FATAL
6068 if (s) return s; 6122 s =
6123#endif
6124 zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
6125 }
6126 if (s) RETURN_STATUS(s);
6069#else 6127#else
6070 bc_num_copy(l, r); 6128 bc_num_copy(l, r);
6071#endif 6129#endif
@@ -6083,8 +6141,7 @@ static BcStatus bc_program_assign(char inst)
6083 unsigned long val, max; 6141 unsigned long val, max;
6084 6142
6085 s = zbc_num_ulong(l, &val); 6143 s = zbc_num_ulong(l, &val);
6086 if (s) 6144 if (s) RETURN_STATUS(s);
6087 return s;
6088 s = left->t - BC_RESULT_IBASE; 6145 s = left->t - BC_RESULT_IBASE;
6089 if (sc) { 6146 if (sc) {
6090 max = BC_MAX_SCALE; 6147 max = BC_MAX_SCALE;
@@ -6092,13 +6149,13 @@ static BcStatus bc_program_assign(char inst)
6092 } 6149 }
6093 else { 6150 else {
6094 if (val < BC_NUM_MIN_BASE) 6151 if (val < BC_NUM_MIN_BASE)
6095 return bc_error(msg[s]); 6152 RETURN_STATUS(bc_error(msg[s]));
6096 max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; 6153 max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
6097 ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; 6154 ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
6098 } 6155 }
6099 6156
6100 if (val > max) 6157 if (val > max)
6101 return bc_error(msg[s]); 6158 RETURN_STATUS(bc_error(msg[s]));
6102 if (!sc) 6159 if (!sc)
6103 bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); 6160 bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l);
6104 6161
@@ -6110,8 +6167,11 @@ static BcStatus bc_program_assign(char inst)
6110 bc_num_copy(&res.d.n, l); 6167 bc_num_copy(&res.d.n, l);
6111 bc_program_binOpRetire(&res); 6168 bc_program_binOpRetire(&res);
6112 6169
6113 return s; 6170 RETURN_STATUS(s);
6114} 6171}
6172#if ERRORS_ARE_FATAL
6173# define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__), BC_STATUS_SUCCESS)
6174#endif
6115 6175
6116#if !ENABLE_DC 6176#if !ENABLE_DC
6117#define bc_program_pushVar(code, bgn, pop, copy) \ 6177#define bc_program_pushVar(code, bgn, pop, copy) \
@@ -6232,7 +6292,8 @@ static BC_STATUS zbc_program_incdec(char inst)
6232 BC_INST_ASSIGN_MINUS; 6292 BC_INST_ASSIGN_MINUS;
6233 6293
6234 bc_vec_push(&G.prog.results, &res); 6294 bc_vec_push(&G.prog.results, &res);
6235 bc_program_assign(inst); 6295 s = zbc_program_assign(inst);
6296 if (s) RETURN_STATUS(s);
6236 6297
6237 if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { 6298 if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
6238 bc_vec_pop(&G.prog.results); 6299 bc_vec_pop(&G.prog.results);
@@ -6369,7 +6430,7 @@ static unsigned long bc_program_len(BcNum *n)
6369 return len; 6430 return len;
6370} 6431}
6371 6432
6372static BcStatus bc_program_builtin(char inst) 6433static BC_STATUS zbc_program_builtin(char inst)
6373{ 6434{
6374 BcStatus s; 6435 BcStatus s;
6375 BcResult *opnd; 6436 BcResult *opnd;
@@ -6378,15 +6439,15 @@ static BcStatus bc_program_builtin(char inst)
6378 bool len = inst == BC_INST_LENGTH; 6439 bool len = inst == BC_INST_LENGTH;
6379 6440
6380 if (!BC_PROG_STACK(&G.prog.results, 1)) 6441 if (!BC_PROG_STACK(&G.prog.results, 1))
6381 return bc_error_stack_has_too_few_elements(); 6442 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6382 opnd = bc_vec_top(&G.prog.results); 6443 opnd = bc_vec_top(&G.prog.results);
6383 6444
6384 s = zbc_program_num(opnd, &num, false); 6445 s = zbc_program_num(opnd, &num, false);
6385 if (s) return s; 6446 if (s) RETURN_STATUS(s);
6386 6447
6387#if ENABLE_DC 6448#if ENABLE_DC
6388 if (!BC_PROG_NUM(opnd, num) && !len) 6449 if (!BC_PROG_NUM(opnd, num) && !len)
6389 return bc_error_variable_is_wrong_type(); 6450 RETURN_STATUS(bc_error_variable_is_wrong_type());
6390#endif 6451#endif
6391 6452
6392 bc_num_init_DEF_SIZE(&res.d.n); 6453 bc_num_init_DEF_SIZE(&res.d.n);
@@ -6399,7 +6460,6 @@ static BcStatus bc_program_builtin(char inst)
6399#endif 6460#endif
6400#if ENABLE_DC 6461#if ENABLE_DC
6401 else if (len != 0 && !BC_PROG_NUM(opnd, num)) { 6462 else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
6402
6403 char **str; 6463 char **str;
6404 size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; 6464 size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6405 6465
@@ -6413,18 +6473,21 @@ static BcStatus bc_program_builtin(char inst)
6413 6473
6414 bc_program_retire(&res, BC_RESULT_TEMP); 6474 bc_program_retire(&res, BC_RESULT_TEMP);
6415 6475
6416 return s; 6476 RETURN_STATUS(s);
6417} 6477}
6478#if ERRORS_ARE_FATAL
6479# define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__), BC_STATUS_SUCCESS)
6480#endif
6418 6481
6419#if ENABLE_DC 6482#if ENABLE_DC
6420static BcStatus bc_program_divmod(void) 6483static BC_STATUS zbc_program_divmod(void)
6421{ 6484{
6422 BcStatus s; 6485 BcStatus s;
6423 BcResult *opd1, *opd2, res, res2; 6486 BcResult *opd1, *opd2, res, res2;
6424 BcNum *n1, *n2 = NULL; 6487 BcNum *n1, *n2 = NULL;
6425 6488
6426 s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); 6489 s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
6427 if (s) return s; 6490 if (s) RETURN_STATUS(s);
6428 6491
6429 bc_num_init_DEF_SIZE(&res.d.n); 6492 bc_num_init_DEF_SIZE(&res.d.n);
6430 bc_num_init(&res2.d.n, n2->len); 6493 bc_num_init(&res2.d.n, n2->len);
@@ -6436,42 +6499,45 @@ static BcStatus bc_program_divmod(void)
6436 res.t = BC_RESULT_TEMP; 6499 res.t = BC_RESULT_TEMP;
6437 bc_vec_push(&G.prog.results, &res); 6500 bc_vec_push(&G.prog.results, &res);
6438 6501
6439 return s; 6502 RETURN_STATUS(s);
6440 6503
6441err: 6504err:
6442 bc_num_free(&res2.d.n); 6505 bc_num_free(&res2.d.n);
6443 bc_num_free(&res.d.n); 6506 bc_num_free(&res.d.n);
6444 return s; 6507 RETURN_STATUS(s);
6445} 6508}
6509#if ERRORS_ARE_FATAL
6510# define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__), BC_STATUS_SUCCESS)
6511#endif
6446 6512
6447static BcStatus bc_program_modexp(void) 6513static BC_STATUS zbc_program_modexp(void)
6448{ 6514{
6449 BcStatus s; 6515 BcStatus s;
6450 BcResult *r1, *r2, *r3, res; 6516 BcResult *r1, *r2, *r3, res;
6451 BcNum *n1, *n2, *n3; 6517 BcNum *n1, *n2, *n3;
6452 6518
6453 if (!BC_PROG_STACK(&G.prog.results, 3)) 6519 if (!BC_PROG_STACK(&G.prog.results, 3))
6454 return bc_error_stack_has_too_few_elements(); 6520 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6455 s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false); 6521 s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
6456 if (s) return s; 6522 if (s) RETURN_STATUS(s);
6457 6523
6458 r1 = bc_vec_item_rev(&G.prog.results, 2); 6524 r1 = bc_vec_item_rev(&G.prog.results, 2);
6459 s = zbc_program_num(r1, &n1, false); 6525 s = zbc_program_num(r1, &n1, false);
6460 if (s) return s; 6526 if (s) RETURN_STATUS(s);
6461 if (!BC_PROG_NUM(r1, n1)) 6527 if (!BC_PROG_NUM(r1, n1))
6462 return bc_error_variable_is_wrong_type(); 6528 RETURN_STATUS(bc_error_variable_is_wrong_type());
6463 6529
6464 // Make sure that the values have their pointers updated, if necessary. 6530 // Make sure that the values have their pointers updated, if necessary.
6465 if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { 6531 if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
6466 6532
6467 if (r1->t == r2->t) { 6533 if (r1->t == r2->t) {
6468 s = zbc_program_num(r2, &n2, false); 6534 s = zbc_program_num(r2, &n2, false);
6469 if (s) return s; 6535 if (s) RETURN_STATUS(s);
6470 } 6536 }
6471 6537
6472 if (r1->t == r3->t) { 6538 if (r1->t == r3->t) {
6473 s = zbc_program_num(r3, &n3, false); 6539 s = zbc_program_num(r3, &n3, false);
6474 if (s) return s; 6540 if (s) RETURN_STATUS(s);
6475 } 6541 }
6476 } 6542 }
6477 6543
@@ -6482,12 +6548,15 @@ static BcStatus bc_program_modexp(void)
6482 bc_vec_pop(&G.prog.results); 6548 bc_vec_pop(&G.prog.results);
6483 bc_program_binOpRetire(&res); 6549 bc_program_binOpRetire(&res);
6484 6550
6485 return s; 6551 RETURN_STATUS(s);
6486 6552
6487err: 6553err:
6488 bc_num_free(&res.d.n); 6554 bc_num_free(&res.d.n);
6489 return s; 6555 RETURN_STATUS(s);
6490} 6556}
6557#if ERRORS_ARE_FATAL
6558# define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__), BC_STATUS_SUCCESS)
6559#endif
6491 6560
6492static void bc_program_stackLen(void) 6561static void bc_program_stackLen(void)
6493{ 6562{
@@ -6857,7 +6926,7 @@ static BcStatus bc_program_exec(void)
6857 case BC_INST_SCALE_FUNC: 6926 case BC_INST_SCALE_FUNC:
6858 case BC_INST_LENGTH: 6927 case BC_INST_LENGTH:
6859 case BC_INST_SQRT: 6928 case BC_INST_SQRT:
6860 s = bc_program_builtin(inst); 6929 s = zbc_program_builtin(inst);
6861 break; 6930 break;
6862 case BC_INST_NUM: 6931 case BC_INST_NUM:
6863 r.t = BC_RESULT_CONSTANT; 6932 r.t = BC_RESULT_CONSTANT;
@@ -6912,14 +6981,14 @@ static BcStatus bc_program_exec(void)
6912 case BC_INST_ASSIGN_MINUS: 6981 case BC_INST_ASSIGN_MINUS:
6913#endif 6982#endif
6914 case BC_INST_ASSIGN: 6983 case BC_INST_ASSIGN:
6915 s = bc_program_assign(inst); 6984 s = zbc_program_assign(inst);
6916 break; 6985 break;
6917#if ENABLE_DC 6986#if ENABLE_DC
6918 case BC_INST_MODEXP: 6987 case BC_INST_MODEXP:
6919 s = bc_program_modexp(); 6988 s = zbc_program_modexp();
6920 break; 6989 break;
6921 case BC_INST_DIVMOD: 6990 case BC_INST_DIVMOD:
6922 s = bc_program_divmod(); 6991 s = zbc_program_divmod();
6923 break; 6992 break;
6924 case BC_INST_EXECUTE: 6993 case BC_INST_EXECUTE:
6925 case BC_INST_EXEC_COND: 6994 case BC_INST_EXEC_COND: