| 883 | } |
| 884 | |
| 885 | static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, |
| 886 | bf_flags_t flags, int b_neg) |
| 887 | { |
| 888 | const bf_t *tmp; |
| 889 | int is_sub, ret, cmp_res, a_sign, b_sign; |
| 890 | |
| 891 | a_sign = a->sign; |
| 892 | b_sign = b->sign ^ b_neg; |
| 893 | is_sub = a_sign ^ b_sign; |
| 894 | cmp_res = bf_cmpu(a, b); |
| 895 | if (cmp_res < 0) { |
| 896 | tmp = a; |
| 897 | a = b; |
| 898 | b = tmp; |
| 899 | a_sign = b_sign; /* b_sign is never used later */ |
| 900 | } |
| 901 | /* abs(a) >= abs(b) */ |
| 902 | if (cmp_res == 0 && is_sub && a->expn < BF_EXP_INF) { |
| 903 | /* zero result */ |
| 904 | bf_set_zero(r, (flags & BF_RND_MASK) == BF_RNDD); |
| 905 | ret = 0; |
| 906 | } else if (a->len == 0 || b->len == 0) { |
| 907 | ret = 0; |
| 908 | if (a->expn >= BF_EXP_INF) { |
| 909 | if (a->expn == BF_EXP_NAN) { |
| 910 | /* at least one operand is NaN */ |
| 911 | bf_set_nan(r); |
| 912 | } else if (b->expn == BF_EXP_INF && is_sub) { |
| 913 | /* infinities with different signs */ |
| 914 | bf_set_nan(r); |
| 915 | ret = BF_ST_INVALID_OP; |
| 916 | } else { |
| 917 | bf_set_inf(r, a_sign); |
| 918 | } |
| 919 | } else { |
| 920 | /* at least one zero and not subtract */ |
| 921 | bf_set(r, a); |
| 922 | r->sign = a_sign; |
| 923 | goto renorm; |
| 924 | } |
| 925 | } else { |
| 926 | slimb_t d, a_offset, b_bit_offset, i, cancelled_bits; |
| 927 | limb_t carry, v1, v2, u, r_len, carry1, precl, tot_len, z, sub_mask; |
| 928 | |
| 929 | r->sign = a_sign; |
| 930 | r->expn = a->expn; |
| 931 | d = a->expn - b->expn; |
| 932 | /* must add more precision for the leading cancelled bits in |
| 933 | subtraction */ |
| 934 | if (is_sub) { |
| 935 | if (d <= 1) |
| 936 | cancelled_bits = count_cancelled_bits(a, b); |
| 937 | else |
| 938 | cancelled_bits = 1; |
| 939 | } else { |
| 940 | cancelled_bits = 0; |
| 941 | } |
| 942 |
no test coverage detected