1 /*
2 Copyright (C) 2010 Sebastian Pancratz
3
4 This file is part of FLINT.
5
6 FLINT 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 <https://www.gnu.org/licenses/>.
10 */
11
12 #include <gmp.h>
13 #include "flint.h"
14 #include "fmpz.h"
15 #include "fmpz_vec.h"
16 #include "fmpq_poly.h"
17
_fmpq_poly_add_can(fmpz * rpoly,fmpz_t rden,const fmpz * poly1,const fmpz_t den1,slong len1,const fmpz * poly2,const fmpz_t den2,slong len2,int can)18 void _fmpq_poly_add_can(fmpz * rpoly, fmpz_t rden,
19 const fmpz * poly1, const fmpz_t den1, slong len1,
20 const fmpz * poly2, const fmpz_t den2, slong len2, int can)
21 {
22 slong max = FLINT_MAX(len1, len2);
23 slong min = FLINT_MIN(len1, len2);
24
25 fmpz_t d;
26
27 if (fmpz_equal(den1, den2))
28 {
29 _fmpz_poly_add(rpoly, poly1, len1, poly2, len2);
30
31 if (fmpz_is_one(den1) || !can)
32 fmpz_set(rden, den1);
33 else
34 {
35 fmpz_init(d);
36 _fmpz_vec_content_chained(d, rpoly, max, den1);
37 if (fmpz_is_one(d))
38 fmpz_set(rden, den1);
39 else
40 {
41 _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d);
42 fmpz_divexact(rden, den1, d);
43 }
44 fmpz_clear(d);
45 }
46
47 return;
48 }
49
50 fmpz_init(d);
51 fmpz_one(d);
52 if (!fmpz_is_one(den1) && !fmpz_is_one(den2))
53 fmpz_gcd(d, den1, den2);
54
55 if (fmpz_is_one(d))
56 {
57 _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2);
58 _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, min, den1);
59 if (len1 < len2)
60 _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1);
61 fmpz_mul(rden, den1, den2);
62 }
63 else
64 {
65 fmpz_t den11;
66 fmpz_t den22;
67 fmpz_init(den11);
68 fmpz_init(den22);
69 fmpz_divexact(den11, den1, d);
70 fmpz_divexact(den22, den2, d);
71
72 _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22);
73 _fmpz_vec_scalar_addmul_fmpz(rpoly, poly2, len2, den11);
74 if (len1 < len2)
75 _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11);
76
77 if (_fmpz_vec_is_zero(rpoly, max))
78 fmpz_one(rden);
79 else
80 {
81 if (can)
82 {
83 fmpz_t e;
84 fmpz_init(e);
85 _fmpz_vec_content_chained(e, rpoly, max, d);
86 if (fmpz_is_one(e))
87 fmpz_mul(rden, den1, den22);
88 else
89 {
90 _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e);
91 fmpz_divexact(den11, den1, e);
92 fmpz_mul(rden, den11, den22);
93 }
94 fmpz_clear(e);
95 } else
96 fmpz_mul(rden, den1, den22);
97 }
98 fmpz_clear(den11);
99 fmpz_clear(den22);
100 }
101 fmpz_clear(d);
102 }
103
_fmpq_poly_add(fmpz * rpoly,fmpz_t rden,const fmpz * poly1,const fmpz_t den1,slong len1,const fmpz * poly2,const fmpz_t den2,slong len2)104 void _fmpq_poly_add(fmpz * rpoly, fmpz_t rden,
105 const fmpz * poly1, const fmpz_t den1, slong len1,
106 const fmpz * poly2, const fmpz_t den2, slong len2)
107 {
108 _fmpq_poly_add_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, 1);
109 }
110
fmpq_poly_add_can(fmpq_poly_t res,const fmpq_poly_t poly1,const fmpq_poly_t poly2,int can)111 void fmpq_poly_add_can(fmpq_poly_t res, const fmpq_poly_t poly1,
112 const fmpq_poly_t poly2, int can)
113 {
114 slong len1 = poly1->length, len2, max;
115
116 if (poly1 == poly2) /* Set res = 2 * poly1 */
117 {
118 fmpq_poly_fit_length(res, len1);
119 _fmpq_poly_set_length(res, len1);
120
121 if (fmpz_is_even(poly1->den))
122 {
123 _fmpz_vec_set(res->coeffs, poly1->coeffs, len1);
124 fmpz_fdiv_q_2exp(res->den, poly1->den, 1);
125 }
126 else
127 {
128 _fmpz_vec_scalar_mul_2exp(res->coeffs, poly1->coeffs, len1, 1);
129 fmpz_set(res->den, poly1->den);
130 }
131 return;
132 }
133
134 len2 = poly2->length;
135 max = FLINT_MAX(len1, len2);
136 fmpq_poly_fit_length(res, max);
137
138 if (res != poly2)
139 _fmpq_poly_add_can(res->coeffs, res->den,
140 poly1->coeffs, poly1->den, len1,
141 poly2->coeffs, poly2->den, len2, can);
142 else
143 _fmpq_poly_add_can(res->coeffs, res->den,
144 poly2->coeffs, poly2->den, len2,
145 poly1->coeffs, poly1->den, len1, can);
146
147 _fmpq_poly_set_length(res, max);
148 _fmpq_poly_normalise(res);
149 }
150
fmpq_poly_add(fmpq_poly_t res,const fmpq_poly_t poly1,const fmpq_poly_t poly2)151 void fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t poly1,
152 const fmpq_poly_t poly2)
153 {
154 fmpq_poly_add_can(res, poly1, poly2, 1);
155 }
156
fmpq_poly_add_si(fmpq_poly_t res,const fmpq_poly_t poly,slong c)157 void fmpq_poly_add_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c)
158 {
159 if (c == 0)
160 {
161 fmpq_poly_set(res, poly);
162 }
163 else if (poly->length == 0)
164 {
165 fmpq_poly_set_si(res, c);
166 }
167 else
168 {
169 fmpz_t p, q;
170 fmpz_init_set_si(p, c);
171 *q = 1;
172 fmpq_poly_fit_length(res, poly->length);
173 _fmpq_poly_set_length(res, poly->length);
174 _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, p, q, 1);
175 _fmpq_poly_normalise(res);
176 fmpz_clear(p);
177 }
178 }
179
fmpq_poly_add_fmpz(fmpq_poly_t res,const fmpq_poly_t poly,const fmpz_t c)180 void fmpq_poly_add_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c)
181 {
182 if (fmpz_is_zero(c))
183 {
184 fmpq_poly_set(res, poly);
185 }
186 else if (poly->length == 0)
187 {
188 fmpq_poly_set_fmpz(res, c);
189 }
190 else
191 {
192 fmpz_t q;
193 *q = 1;
194 fmpq_poly_fit_length(res, poly->length);
195 _fmpq_poly_set_length(res, poly->length);
196 _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, c, q, 1);
197 _fmpq_poly_normalise(res);
198 }
199 }
200
fmpq_poly_add_fmpq(fmpq_poly_t res,const fmpq_poly_t poly,const fmpq_t c)201 void fmpq_poly_add_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c)
202 {
203 if (fmpq_is_zero(c))
204 {
205 fmpq_poly_set(res, poly);
206 }
207 else if (poly->length == 0)
208 {
209 fmpq_poly_set_fmpq(res, c);
210 }
211 else
212 {
213 fmpq_poly_fit_length(res, poly->length);
214 _fmpq_poly_set_length(res, poly->length);
215 _fmpq_poly_add(res->coeffs, res->den, poly->coeffs, poly->den, poly->length, fmpq_numref(c), fmpq_denref(c), 1);
216 _fmpq_poly_normalise(res);
217 }
218 }
219