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 <http://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_sub_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_sub_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_sub(rpoly, poly1, len1, poly2, len2);
30
31 if (fmpz_is_one(den1) || !can)
32 fmpz_set(rden, den1);
33 else if (can)
34 {
35 fmpz_init(d);
36 _fmpz_vec_content(d, rpoly, max);
37
38 if (!fmpz_is_one(d))
39 fmpz_gcd(d, d, den1);
40
41 if (fmpz_is_one(d))
42 fmpz_set(rden, den1);
43 else
44 {
45 _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, d);
46 fmpz_divexact(rden, den1, d);
47 }
48
49 fmpz_clear(d);
50 }
51
52 return;
53 }
54
55 fmpz_init(d);
56 fmpz_one(d);
57 if (!fmpz_is_one(den1) && !fmpz_is_one(den2))
58 fmpz_gcd(d, den1, den2);
59
60 if (fmpz_is_one(d))
61 {
62 _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den2);
63 _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, min, den1);
64 if (len1 < len2)
65 {
66 _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den1);
67 _fmpz_vec_neg(rpoly + min, rpoly + min, max - min);
68 }
69 fmpz_mul(rden, den1, den2);
70 }
71 else
72 {
73 fmpz_t den11;
74 fmpz_t den22;
75 fmpz_init(den11);
76 fmpz_init(den22);
77 fmpz_divexact(den11, den1, d);
78 fmpz_divexact(den22, den2, d);
79
80 _fmpz_vec_scalar_mul_fmpz(rpoly, poly1, len1, den22);
81 _fmpz_vec_scalar_submul_fmpz(rpoly, poly2, len2, den11);
82 if (len1 < len2)
83 {
84 _fmpz_vec_scalar_mul_fmpz(rpoly + min, poly2 + min, max - min, den11);
85 _fmpz_vec_neg(rpoly + min, rpoly + min, max - min);
86 }
87
88 if (_fmpz_vec_is_zero(rpoly, max))
89 fmpz_one(rden);
90 else
91 {
92 if (can)
93 {
94 fmpz_t e;
95 fmpz_init(e);
96 _fmpz_vec_content(e, rpoly, max);
97 if (!fmpz_is_one(e))
98 fmpz_gcd(e, e, d);
99
100 if (fmpz_is_one(e))
101 fmpz_mul(rden, den1, den22);
102 else
103 {
104 _fmpz_vec_scalar_divexact_fmpz(rpoly, rpoly, max, e);
105 fmpz_divexact(den11, den1, e);
106 fmpz_mul(rden, den11, den22);
107 }
108 fmpz_clear(e);
109 } else
110 fmpz_mul(rden, den1, den22);
111 }
112 fmpz_clear(den11);
113 fmpz_clear(den22);
114 }
115 fmpz_clear(d);
116 }
117
_fmpq_poly_sub(fmpz * rpoly,fmpz_t rden,const fmpz * poly1,const fmpz_t den1,slong len1,const fmpz * poly2,const fmpz_t den2,slong len2)118 void _fmpq_poly_sub(fmpz * rpoly, fmpz_t rden,
119 const fmpz * poly1, const fmpz_t den1, slong len1,
120 const fmpz * poly2, const fmpz_t den2, slong len2)
121 {
122 _fmpq_poly_sub_can(rpoly, rden, poly1, den1, len1, poly2, den2, len2, 1);
123 }
124
fmpq_poly_sub_can(fmpq_poly_t res,const fmpq_poly_t poly1,const fmpq_poly_t poly2,int can)125 void fmpq_poly_sub_can(fmpq_poly_t res, const fmpq_poly_t poly1,
126 const fmpq_poly_t poly2, int can)
127 {
128 slong len1, len2, max;
129
130 if (poly1 == poly2)
131 {
132 fmpq_poly_zero(res);
133 return;
134 }
135
136 len1 = poly1->length;
137 len2 = poly2->length;
138 max = FLINT_MAX(poly1->length, poly2->length);
139 fmpq_poly_fit_length(res, max);
140
141 if (res != poly2)
142 _fmpq_poly_sub_can(res->coeffs, res->den,
143 poly1->coeffs, poly1->den, len1,
144 poly2->coeffs, poly2->den, len2, can);
145 else
146 {
147 _fmpq_poly_sub_can(res->coeffs, res->den,
148 poly2->coeffs, poly2->den, len2,
149 poly1->coeffs, poly1->den, len1, can);
150 _fmpz_vec_neg(res->coeffs, res->coeffs, max);
151 }
152
153 _fmpq_poly_set_length(res, max);
154 _fmpq_poly_normalise(res);
155 }
156
fmpq_poly_sub(fmpq_poly_t res,const fmpq_poly_t poly1,const fmpq_poly_t poly2)157 void fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t poly1,
158 const fmpq_poly_t poly2)
159 {
160 fmpq_poly_sub_can(res, poly1, poly2, 1);
161 }
162