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_mul_arf(arb_t z,const arb_t x,const arf_t y,slong prec)15 arb_mul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
16 {
17     mag_t zr, ym;
18     int inexact;
19 
20     if (arb_is_exact(x))
21     {
22         inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
23 
24         if (inexact)
25             arf_mag_set_ulp(arb_radref(z), arb_midref(z), prec);
26         else
27             mag_zero(arb_radref(z));
28     }
29     else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
30     {
31         mag_fast_init_set_arf(ym, y);
32         mag_init(zr);
33 
34         mag_fast_mul(zr, ym, arb_radref(x));
35 
36         inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
37 
38         if (inexact)
39             arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec);
40 
41         *arb_radref(z) = *zr;
42     }
43     else
44     {
45         mag_init_set_arf(ym, y);
46         mag_init(zr);
47 
48         mag_mul(zr, ym, arb_radref(x));
49 
50         inexact = arf_mul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
51 
52         if (inexact)
53             arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
54         else
55             mag_swap(arb_radref(z), zr);
56 
57         mag_clear(ym);
58         mag_clear(zr);
59 
60     }
61 }
62 
63 void
arb_mul(arb_t z,const arb_t x,const arb_t y,slong prec)64 arb_mul(arb_t z, const arb_t x, const arb_t y, slong prec)
65 {
66     mag_t zr, xm, ym;
67     int inexact;
68 
69     if (arb_is_exact(x))
70     {
71         arb_mul_arf(z, y, arb_midref(x), prec);
72     }
73     else if (arb_is_exact(y))
74     {
75         arb_mul_arf(z, x, arb_midref(y), prec);
76     }
77     else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
78     {
79         mag_fast_init_set_arf(xm, arb_midref(x));
80         mag_fast_init_set_arf(ym, arb_midref(y));
81 
82         mag_init(zr);
83         mag_fast_mul(zr, xm, arb_radref(y));
84         mag_fast_addmul(zr, ym, arb_radref(x));
85         mag_fast_addmul(zr, arb_radref(x), arb_radref(y));
86 
87         inexact = arf_mul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND);
88 
89         if (inexact)
90             arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec);
91 
92         *arb_radref(z) = *zr;
93     }
94     else
95     {
96         mag_init_set_arf(xm, arb_midref(x));
97         mag_init_set_arf(ym, arb_midref(y));
98 
99         mag_init(zr);
100         mag_mul(zr, xm, arb_radref(y));
101         mag_addmul(zr, ym, arb_radref(x));
102         mag_addmul(zr, arb_radref(x), arb_radref(y));
103 
104         inexact = arf_mul(arb_midref(z), arb_midref(x), arb_midref(y), prec, ARB_RND);
105 
106         if (inexact)
107             arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
108         else
109             mag_swap(arb_radref(z), zr);
110 
111         mag_clear(xm);
112         mag_clear(ym);
113         mag_clear(zr);
114     }
115 }
116 
117 void
arb_mul_si(arb_t z,const arb_t x,slong y,slong prec)118 arb_mul_si(arb_t z, const arb_t x, slong y, slong prec)
119 {
120     arf_t t;
121     arf_init_set_si(t, y); /* no need to free */
122     arb_mul_arf(z, x, t, prec);
123 }
124 
125 void
arb_mul_ui(arb_t z,const arb_t x,ulong y,slong prec)126 arb_mul_ui(arb_t z, const arb_t x, ulong y, slong prec)
127 {
128     arf_t t;
129     arf_init_set_ui(t, y); /* no need to free */
130     arb_mul_arf(z, x, t, prec);
131 }
132 
133 void
arb_mul_fmpz(arb_t z,const arb_t x,const fmpz_t y,slong prec)134 arb_mul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec)
135 {
136     arf_t t;
137 
138     if (!COEFF_IS_MPZ(*y))
139     {
140         arf_init_set_si(t, *y); /* no need to free */
141         arb_mul_arf(z, x, t, prec);
142     }
143     else
144     {
145         arf_init(t);
146         arf_set_fmpz(t, y);
147         arb_mul_arf(z, x, t, prec);
148         arf_clear(t);
149     }
150 }
151 
152