cheshirekow  v0.1.0
SturmSequence.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
27 #ifndef MPBLOCKS_CUDA_POLYNOMIAL_STURMSEQUENCE_H_
28 #define MPBLOCKS_CUDA_POLYNOMIAL_STURMSEQUENCE_H_
29 
30 #include <iostream>
31 #include <vector>
32 #include <list>
33 
35 
36 namespace mpblocks {
37 namespace cuda {
38 namespace polynomial {
39 
40 template < typename Scalar, int max>
42 
43 namespace sturm_detail
44 {
45 
47 template <typename T>
49 int sgn(T val)
50 {
51  return (T(0) < val) - (val < T(0));
52 }
53 
54 
56 template < typename Scalar, int size>
57 struct Storage:
58  public Storage<Scalar,size-1>
59 {
61 };
62 
63 template < typename Scalar>
64 struct Storage<Scalar,-1>{};
65 
66 
67 template <class Scalar, int i, int max>
69 
70 template <class Scalar, int i, int max>
72 
73 template <class Scalar, int max>
75 void rebuild( SturmSequence<Scalar,max>& sturm );
76 
77 template <class Scalar, int max>
79 int signChanges( SturmSequence<Scalar,max>& sturm, Scalar s, Scalar prev );
80 
81 
82 } // namespace sturm_detail
83 
84 
87 template < int i, typename Scalar, int max >
89 Polynomial<Scalar, typename intlist::range<0,max-i>::result>&
90  get( SturmSequence<Scalar,max>& sturm);
91 
92 
93 
97 template < typename Scalar, int max>
98 struct SturmSequence:
99  public sturm_detail::Storage<Scalar, max >
100 {
103  {}
104 
106  template < class Exp, class Spec >
109  {
110  rebuild(rhs);
111  }
112 
113  template <class Exp, class Spec>
115  void rebuild( const RValue<Scalar,Exp,Spec>& rhs )
116  {
117  typedef typename intlist::range<0,max-1>::result Spec1;
118  typedef Polynomial< Scalar, Spec1 > Poly1;
119  Poly1 p1 = d_ds<1>( rhs );
120 
121 // std::cout << "Building sturm sequence:\n";
122  get<0>(*this) = normalized(rhs);
123 // std::cout << "\n spec: " << Printer<Spec>()
124 // << "\n max : " << intlist::max<Spec>::value
125 // << "\n input: " << rhs
126 // << "\n d/ds: " << p1
127 // << "\n p0: " << get<0>(*this);
128  get<1>(*this) = normalized(p1);
129 // std::cout << "\n p0: " << get<0>(*this)
130 // << "\n p1: " << get<1>(*this)
131 // << "\n";
132 
133  sturm_detail::rebuild(*this);
134  }
135 
138  int signChanges( Scalar s )
139  {
140  Scalar y0 = polyval( get<0>(*this),s );
141  return sturm_detail::signChanges(*this,s,y0);
142  }
143 };
144 
145 
146 template < int i, typename Scalar, int max >
148 Polynomial<Scalar, typename intlist::range<0,max-i>::result>&
150 {
151  return static_cast< sturm_detail::Storage<Scalar,max-i>& >(sturm).poly;
152 }
153 
154 
155 namespace sturm_detail
156 {
157 
158 template <class Scalar, int i, int size>
159 struct RebuildHelper
160 {
161  enum{ max = size-1 };
163  static void rebuild( SturmSequence<Scalar,max>& sturm )
164  {
165  typedef typename intlist::range<0,max-(i-2)>::result Spec1;
166  typedef typename intlist::range<0,max-(i-1)>::result Spec2;
167 
168  typedef Quotient<Scalar,
170  Polynomial<Scalar,Spec2>,Spec2 > Quotient_t;
171  Quotient_t q( get<i-2>(sturm) / get<i-1>(sturm) );
172  get<i>(sturm) = -q.r;
173 
174 // std::cout << "Building sturm seq " << i ;
175 // std::cout << "\np[" << (i-2) << "] : " << get<i-2>(sturm)
176 // << "\np[" << (i-1) << "] : " << get<i-1>(sturm)
177 // << "\n q : " << q.q
178 // << "\n r : " << q.r
179 // << "\np[" << i << "] : " << get<i>(sturm)
180 // << "\n\n";
181 
183  }
184 };
185 
186 
187 template <class Scalar, int size>
188 struct RebuildHelper<Scalar,size,size>
189 {
190  enum{ max = size-1 };
192  static void rebuild( SturmSequence<Scalar,size-1>& sturm )
193  {
194  typedef typename intlist::range<0,2>::result Spec1;
195  typedef typename intlist::range<0,1>::result Spec2;
196 
197  typedef Quotient<Scalar,
199  Polynomial<Scalar,Spec2>,Spec2 > Quotient_t;
200  Quotient_t q( get<max-2>(sturm) / get<max-1>(sturm) );
201  get<max>(sturm) = -q.r;
202 
203 // std::cout << "Building sturm seq " << i ;
204 // std::cout << "\np[" << (i-2) << "] : " << get<i-2>(sturm)
205 // << "\np[" << (i-1) << "] : " << get<i-1>(sturm)
206 // << "\n q : " << q.q
207 // << "\n r : " << q.r
208 // << "\np[" << i << "] : " << get<i>(sturm)
209 // << "\n\n";
210  }
211 };
212 
213 template <class Scalar, int i, int size>
214 struct SignChangeHelper
215 {
216  enum{ max = size-1 };
218  static int count( SturmSequence<Scalar,size-1>& sturm, Scalar s, Scalar prev )
219  {
220  Scalar next = polyval( get<i>(sturm), s );
221  if( sgn(next) )
222  {
223  return ( sgn(next) == sgn(prev) ? 0 : 1 )
225  }
226  else
227  return SignChangeHelper<Scalar,i+1,size>::count(sturm,s,prev);
228  }
229 };
230 
231 template <class Scalar, int size>
232 struct SignChangeHelper<Scalar,size,size>
233 {
234  enum{ max = size-1 };
236  static int count(SturmSequence<Scalar,max>& sturm, Scalar s, Scalar prev)
237  {
238  return 0;
239  }
240 };
241 
242 template <class Scalar, int max>
245 {
247 }
248 
249 template <class Scalar, int max>
251 int signChanges( SturmSequence<Scalar,max>& sturm, Scalar s, Scalar y0)
252 {
253  return SignChangeHelper<Scalar,1,max+1>::count(sturm,s, y0);
254 }
255 
256 
257 } // namespace sturm_detail
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 } // namespace polynomial
268 } // namespace cuda
269 } // namespace mpblocks
270 
271 
272 
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286 #endif // STURMSEQUENCE_H_
A sparse, statically sized polynomial.
Definition: Polynomial.h:266
__host__ __device__ static __forceinline__ int count(SturmSequence< Scalar, size-1 > &sturm, Scalar s, Scalar prev)
Polynomial< Scalar, typename intlist::range< 0, size >::result > poly
Definition: SturmSequence.h:60
__host__ __device__ __forceinline__ SturmSequence()
#define __forceinline__
Definition: fakecuda.h:38
__host__ __device__ __forceinline__ void rebuild(SturmSequence< Scalar, max > &sturm)
__host__ __device__ __forceinline__ int signChanges(SturmSequence< Scalar, max > &sturm, Scalar s, Scalar prev)
expression template for polynomial long division
Definition: Quotient.h:60
expression template for rvalues
Definition: RValue.h:40
__host__ __device__ static __forceinline__ int count(SturmSequence< Scalar, max > &sturm, Scalar s, Scalar prev)
stores a squence of polynomials which satisfy the properties of sturms theorem and provides methods f...
Definition: SturmSequence.h:41
__host__ __device__ static __forceinline__ void rebuild(SturmSequence< Scalar, max > &sturm)
__host__ __device__ __forceinline__ void rebuild(const RValue< Scalar, Exp, Spec > &rhs)
__host__ __device__ static __forceinline__ void rebuild(SturmSequence< Scalar, size-1 > &sturm)
Storage class, stores one polynomial in teh sequence.
Definition: SturmSequence.h:57
__host__ __device__ __forceinline__ int signChanges(Scalar s)
return the number of sign changes at the specified point
__host__ __device__ __forceinline__ int sgn(T val)
signum
Definition: SturmSequence.h:49
#define __device__
Definition: fakecuda.h:34
__host__ __device__ Normalized< Scalar, Exp, Spec > normalized(const RValue< Scalar, Exp, Spec > &exp)
Definition: Normalized.h:72
#define __host__
Definition: fakecuda.h:37
__host__ __device__ Scalar polyval(const RValue< Scalar, Exp, Spec > &exp, Scalar2 x)
evaluate a polynomial
Definition: polyval.h:62
creates an integer list from i to j (including both i and j)
Definition: IntList.h:453
__host__ __device__ __forceinline__ SturmSequence(const RValue< Scalar, Exp, Spec > &rhs)
builds a sturm sequence from a polynomial