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