1 /*
2 Copyright (C) 2014 Fredrik Johansson
3
4 This file is part of Arb.
5
6 Arb is free software: you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version. See <http://www.gnu.org/licenses/>.
10 */
11
12 #include "arb.h"
13
14 void
arb_submul_arf(arb_t z,const arb_t x,const arf_t y,slong prec)15 arb_submul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
16 {
17 mag_t ym;
18 int inexact;
19
20 if (arb_is_exact(x))
21 {
22 inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
23
24 if (inexact)
25 arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
26 }
27 else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
28 {
29 mag_fast_init_set_arf(ym, y);
30 mag_fast_addmul(arb_radref(z), ym, arb_radref(x));
31 inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
32
33 if (inexact)
34 arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
35 }
36 else
37 {
38 mag_init_set_arf(ym, y);
39 mag_addmul(arb_radref(z), ym, arb_radref(x));
40
41 inexact = arf_submul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
42 if (inexact)
43 arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
44
45 mag_clear(ym);
46 }
47 }
48
49 void
arb_submul(arb_t z,const arb_t x,const arb_t y,slong prec)50 arb_submul(arb_t z, const arb_t x, const arb_t y, slong prec)
51 {
52 mag_t zr, xm, ym;
53 int inexact;
54
55 if (arb_is_exact(y))
56 {
57 arb_submul_arf(z, x, arb_midref(y), prec);
58 }
59 else if (arb_is_exact(x))
60 {
61 arb_submul_arf(z, y, arb_midref(x), prec);
62 }
63 else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
64 {
65 mag_fast_init_set_arf(xm, arb_midref(x));
66 mag_fast_init_set_arf(ym, arb_midref(y));
67
68 mag_fast_init_set(zr, arb_radref(z));
69 mag_fast_addmul(zr, xm, arb_radref(y));
70 mag_fast_addmul(zr, ym, arb_radref(x));
71 mag_fast_addmul(zr, arb_radref(x), arb_radref(y));
72
73 inexact = arf_submul(arb_midref(z), arb_midref(x), arb_midref(y),
74 prec, ARF_RND_DOWN);
75
76 if (inexact)
77 arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec);
78
79 *arb_radref(z) = *zr;
80 }
81 else
82 {
83 mag_init_set_arf(xm, arb_midref(x));
84 mag_init_set_arf(ym, arb_midref(y));
85
86 mag_init_set(zr, arb_radref(z));
87 mag_addmul(zr, xm, arb_radref(y));
88 mag_addmul(zr, ym, arb_radref(x));
89 mag_addmul(zr, arb_radref(x), arb_radref(y));
90
91 inexact = arf_submul(arb_midref(z), arb_midref(x), arb_midref(y),
92 prec, ARF_RND_DOWN);
93
94 if (inexact)
95 arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
96 else
97 mag_set(arb_radref(z), zr);
98
99 mag_clear(zr);
100 mag_clear(xm);
101 mag_clear(ym);
102 }
103 }
104
105 void
arb_submul_si(arb_t z,const arb_t x,slong y,slong prec)106 arb_submul_si(arb_t z, const arb_t x, slong y, slong prec)
107 {
108 arf_t t;
109 arf_init_set_si(t, y); /* no need to free */
110 arb_submul_arf(z, x, t, prec);
111 }
112
113 void
arb_submul_ui(arb_t z,const arb_t x,ulong y,slong prec)114 arb_submul_ui(arb_t z, const arb_t x, ulong y, slong prec)
115 {
116 arf_t t;
117 arf_init_set_ui(t, y); /* no need to free */
118 arb_submul_arf(z, x, t, prec);
119 }
120
121 void
arb_submul_fmpz(arb_t z,const arb_t x,const fmpz_t y,slong prec)122 arb_submul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec)
123 {
124 arf_t t;
125
126 if (!COEFF_IS_MPZ(*y))
127 {
128 arf_init_set_si(t, *y); /* no need to free */
129 arb_submul_arf(z, x, t, prec);
130 }
131 else
132 {
133 arf_init(t);
134 arf_set_fmpz(t, y);
135 arb_submul_arf(z, x, t, prec);
136 arf_clear(t);
137 }
138 }
139