00001
00002
00003
00004
00005
00006 #ifndef SYNAPS_UPOL_SQUAREFREE_H_
00007 #define SYNAPS_UPOL_SQUAREFREE_H_
00008
00009 #include <list>
00010 #include <vector>
00011 #include <synaps/init.h>
00012 #include <synaps/arithm/pow.h>
00013 #include <synaps/arithm/sign.h>
00014 #include <synaps/arithm/gmp.h>
00015 #include <synaps/base/Seq.h>
00016 #include <synaps/upol/UPolDse.h>
00017 #include <synaps/upol/gcd.h>
00018
00019
00020 __BEGIN_NAMESPACE_SYNAPS
00021
00022
00026 template<class C>
00027 UPolDse<C> square_free(const UPolDse<C> & p)
00028 {
00029 if(p==0)
00030 return UPolDse<C>(0);
00031 else
00032 {
00033 typedef UPolDse<C> Pol;
00034 Pol h = p, dp = diff(h);
00035 Pol g = gcd(h,dp);
00036 h/=g;
00037 return h;
00038 }
00039 }
00040
00041 template<class C>
00042 UPolDse<UPolDse<C> > square_free(const UPolDse<UPolDse<C> > & p)
00043 {
00044 typedef UPolDse<UPolDse<C> > PolPol;
00045 typedef UPolDse<C> Pol;
00046 PolPol h = p;
00047 PolPol dp = diff(p);
00048 PolPol g = gcd(h,dp);
00049 if (degree(g) >= 0){
00050 C tmp = content(g[0]);
00051 for(int i=1;i <= degree(g);++i){
00052 tmp = gcd(tmp,content(g[i]));
00053 }
00054 for(int i=0;i<=degree(g);i++)
00055 g[i]/=tmp;
00056 }
00057 h/=g;
00058 return h;
00059 }
00060
00061
00068 template < typename RT >
00069 Seq< UPolDse<RT> >
00070 square_free_factorisation( const UPolDse<RT>& f)
00071 {
00072
00073 typedef UPolDse<RT> Poly;
00074
00075 Seq< Poly > res;
00076
00077 res.resize( UPOLDAR::degree(f) );
00078
00079 Poly df = UPOLDAR::diff(f);
00080
00081 Poly c = gcd(f, df);
00082
00083 if ( UPOLDAR::degree( c) <= 0) {
00084 res[0] = f;
00085 res.resize(1);
00086 return res;
00087 }
00088
00089 int i = 1;
00090 int n = 0;
00091 Poly w = f / c;
00092 Poly y = df / c;
00093 Poly z = y - UPOLDAR::diff(w);
00094 Poly g;
00095
00096 while ( true ) {
00097 g = gcd( w, z);
00098 if ( UPOLDAR::degree( g) > 0) {
00099 res[i] = g;
00100 }
00101 ++i;
00102 w /= g;
00103 y = z / g;
00104 z = y - UPOLDAR::diff( w);
00105 if ( UPOLDAR::degree(z) <= 0) break;
00106 }
00107 res[i] = w;
00108 res.resize(i+1);
00109 return res;
00110 }
00111
00112
00113 template < typename RT >
00114 Seq< UPolDse<RT> >
00115 square_free_factorization( const UPolDse<RT>& f, SturmSeq<RT>& sth)
00116 {
00117
00118 typedef UPolDse<RT> Poly;
00119 Seq< Poly > res;
00120
00121 res.resize( UPOLDAR::degree(f) );
00122
00123 Poly df = UPOLDAR::diff(f);
00124
00125 Poly c;
00126 sth = SturmSeq<RT>( f / content(f), df, SUBRES());
00127
00128 typename SturmSeq<RT>::reverse_iterator it = sth.rep().rbegin();
00129
00130 for (int i = 0; i < sth.size(); ++i) {
00131 if ( degree( sth[i]) >= 0 ) sth[i] /= content(sth[i]);
00132 }
00133
00134 for(; (it!= sth.rep().rend()) && (*it == 0) ; ++it);
00135 RT temp = content( *it);
00136 c = (*it) / temp;
00137
00138 if ( UPOLDAR::degree(c) <= 0) {
00139 res[0] = f;
00140 res.resize(1);
00141 return res;
00142 }
00143
00144 int i = 1;
00145 int n = 0;
00146
00147 Poly w = f / c;
00148 Poly y = df / c;
00149 Poly z = y - UPOLDAR::diff(w);
00150 Poly g;
00151
00152 while ( true ) {
00153 g = gcd( w, z);
00154 if ( UPOLDAR::degree( g) > 0) {
00155 res[i] = g;
00156 }
00157 ++i;
00158 w /= g;
00159 y = z / g;
00160 z = y - UPOLDAR::diff( w);
00161 if ( UPOLDAR::degree(z) <= 0) break;
00162 }
00163 res[i] = w;
00164 res.resize(i+1);
00165 return res;
00166
00167 }
00168
00169 __END_NAMESPACE_SYNAPS
00170
00171 #endif // SYNAPS_UPOL_SQUAREFREE_H_