]> www.ginac.de Git - ginac.git/blob - ginac/polynomial/normalize.h
3b7cd9fee25cbade0d391047d439ba2ce7ef46eb
[ginac.git] / ginac / polynomial / normalize.h
1 /** @file normalize.h
2  *
3  *  Functions to normalize polynomials in a field. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2010 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #ifndef GINAC_UPOLY_NORMALIZE_H
24 #define GINAC_UPOLY_NORMALIZE_H
25
26 #include "upoly.h"
27 #include "ring_traits.h"
28 #include "debug.h"
29
30 namespace GiNaC {
31
32 /// Make the univariate polynomial @a a \in F[x] unit normal.
33 /// F should be a field.
34 /// Returns true if the polynomial @x is already unit normal, and false
35 /// otherwise.
36 static bool normalize_in_field(umodpoly& a, cln::cl_MI* content_ = 0)
37 {
38         if (a.size() == 0)
39                 return true;
40         if (lcoeff(a) == the_one(a[0])) {
41                 if (content_)
42                         *content_ = the_one(a[0]);
43                 return true;
44         }
45
46         const cln::cl_MI lc_1 = recip(lcoeff(a));
47         for (std::size_t k = a.size(); k-- != 0; )
48                 a[k] = a[k]*lc_1;
49         if (content_)
50                 *content_ = lc_1;
51         return false;
52 }
53
54 /// Make the univariate polynomial @a x unit normal. This version is used
55 /// for rings which are not fields. 
56 /// Returns true if the polynomial @x is already unit normal, and false
57 /// otherwise.
58 template<typename T> bool
59 normalize_in_ring(T& x, typename T::value_type* content_ = 0, int* unit_ = 0)
60 {
61         typedef typename T::value_type ring_t;
62         static const ring_t one(1);
63         if (x.empty())
64                 return true;
65
66         bool something_changed = false;
67         if (minusp(lcoeff(x))) {
68                 something_changed = true;
69                 if (unit_)
70                         *unit_ = -1;
71                 for (std::size_t i = x.size(); i-- != 0; )
72                         x[i] = - x[i];
73         }
74
75         if (degree(x) == 0) {
76                 if (content_)
77                         *content_ = x[0];
78                 if (x[0] == one)
79                         return something_changed;
80                 x[0] = one;
81                 return false; // initial polynomial was unit normal
82         }
83                 
84         // Compute the gcd of coefficients
85         ring_t content = lcoeff(x);
86         // We want this function to be fast when applied to unit normal
87         // polynomials. Hence we start from the leading coefficient.
88         for (std::size_t i = x.size() - 1; i-- != 0; ) {
89                 if (content == one) {
90                         if (content_)
91                                 *content_ = one;
92                         return something_changed;
93                 }
94                 content = gcd(x[i], content);
95         }
96
97         if (content == one) {
98                 if (content_)
99                         *content_ = one;
100                 return something_changed;
101         }
102         
103         for (std::size_t i = x.size(); i-- != 0; )
104                 x[i] = exquo(x[i], content);
105
106         if (content_)
107                 *content_ = content;
108         return false; // initial polynomial was not unit normal
109 }
110
111 } // namespace GiNaC
112         
113 #endif // GINAC_UPOLY_NORMALIZE_H