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