diff options
-rw-r--r-- | miscutils/bc.c | 779 |
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) | ||
949 | static /*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) | ||
954 | static /*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 | |||
945 | typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; | 959 | typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; |
946 | 960 | ||
947 | typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; | 961 | typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; |
948 | 962 | ||
949 | static BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 963 | static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, |
950 | static BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 964 | BcNumBinaryOp op, size_t req); |
951 | static BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 965 | static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
952 | static BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 966 | static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
953 | static BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 967 | static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
954 | static BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; | 968 | static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
955 | static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, | 969 | static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
956 | size_t scale); | 970 | static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); |
971 | |||
972 | static 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 | |||
979 | static 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 | |||
986 | static 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 | |||
992 | static 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 | |||
998 | static 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 | |||
1004 | static 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 | ||
958 | static const BcNumBinaryOp zbc_program_ops[] = { | 1009 | static 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 | ||
962 | static void fflush_and_check(void) | 1021 | static 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) | ||
1534 | static /*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) | ||
1539 | static /*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 | |||
1544 | static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) | 1589 | static 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 | ||
1695 | static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale) | 1740 | static 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 | ||
1707 | static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) | 1755 | static 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 | ||
1778 | static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) | 1826 | static 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 | ||
1840 | static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, | 1888 | static 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 | ||
1946 | static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) | 1999 | static 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_ | |||
1982 | err: | 2035 | err: |
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 | ||
1988 | static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) | 2044 | static 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 | ||
2060 | static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, | 2121 | static 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 | ||
2092 | err: | 2153 | err: |
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 | ||
2097 | static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) | 2161 | static 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 | ||
2110 | static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) | 2177 | static 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(©, a->len); | 2209 | bc_num_init(©, a->len); |
2143 | bc_num_copy(©, a); | 2210 | bc_num_copy(©, a); |
@@ -2195,10 +2262,13 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_ | |||
2195 | 2262 | ||
2196 | err: | 2263 | err: |
2197 | bc_num_free(©); | 2264 | bc_num_free(©); |
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 | ||
2201 | static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | 2271 | static 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 | |||
2238 | static 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 | ||
2248 | static 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 | |||
2256 | static 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 | |||
2277 | static 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 | |||
2290 | static 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 | |||
2301 | static 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 | |||
2355 | err: | ||
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 | ||
2367 | static 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 | ||
2401 | static 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 | ||
2410 | static bool bc_num_strValid(const char *val, size_t base) | 2316 | static 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 | ||
2560 | static BC_STATUS zbc_num_print(BcNum *n, bool newline) | 2466 | static 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 | |||
2586 | static 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 | |||
2593 | static 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 | |||
2600 | static 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 | |||
2606 | static 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 | |||
2612 | static 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 | |||
2618 | static 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 | |||
2623 | static 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 | ||
2725 | static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, | 2571 | static 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 |
2752 | static BcStatus zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) | 2601 | static 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 | ||
5669 | static 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 | ||
5679 | static 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 | |||
5687 | static 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 | |||
5708 | static 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 | |||
5721 | static 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 | |||
5732 | static 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 | |||
5786 | err: | ||
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 | |||
5798 | static 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 | ||
5832 | static 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 | |||
5841 | static 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 | |||
5813 | static BC_STATUS zbc_program_print(char inst, size_t idx) | 5867 | static 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 | ||
6025 | static BcStatus bc_program_assign(char inst) | 6079 | static 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 | ||
6372 | static BcStatus bc_program_builtin(char inst) | 6433 | static 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 |
6420 | static BcStatus bc_program_divmod(void) | 6483 | static 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 | ||
6441 | err: | 6504 | err: |
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 | ||
6447 | static BcStatus bc_program_modexp(void) | 6513 | static 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 | ||
6487 | err: | 6553 | err: |
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 | ||
6492 | static void bc_program_stackLen(void) | 6561 | static 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: |