1 /*
2  *  sbasis.cpp - S-power basis function class + supporting classes
3  *
4  *  Authors:
5  *   Nathan Hurst <njh@mail.csse.monash.edu.au>
6  *   Michael Sloan <mgsloan@gmail.com>
7  *
8  * Copyright (C) 2006-2007 authors
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it either under the terms of the GNU Lesser General Public
12  * License version 2.1 as published by the Free Software Foundation
13  * (the "LGPL") or, at your option, under the terms of the Mozilla
14  * Public License Version 1.1 (the "MPL"). If you do not alter this
15  * notice, a recipient may use your version of this file under either
16  * the MPL or the LGPL.
17  *
18  * You should have received a copy of the LGPL along with this library
19  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  * You should have received a copy of the MPL along with this library
22  * in the file COPYING-MPL-1.1
23  *
24  * The contents of this file are subject to the Mozilla Public License
25  * Version 1.1 (the "License"); you may not use this file except in
26  * compliance with the License. You may obtain a copy of the License at
27  * http://www.mozilla.org/MPL/
28  *
29  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
30  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
31  * the specific language governing rights and limitations.
32  */
33 
34 #include <cmath>
35 
36 #include <2geom/sbasis.h>
37 #include <2geom/math-utils.h>
38 
39 namespace Geom {
40 
41 #ifndef M_PI
42 # define M_PI 3.14159265358979323846
43 #endif
44 
45 /** bound the error from term truncation
46  \param tail first term to chop
47  \returns the largest possible error this truncation could give
48 */
tailError(unsigned tail) const49 double SBasis::tailError(unsigned tail) const {
50   Interval bs = *bounds_fast(*this, tail);
51   return std::max(fabs(bs.min()),fabs(bs.max()));
52 }
53 
54 /** test all coefficients are finite
55 */
isFinite() const56 bool SBasis::isFinite() const {
57     for(unsigned i = 0; i < size(); i++) {
58         if(!(*this)[i].isFinite())
59             return false;
60     }
61     return true;
62 }
63 
64 /** Compute the value and the first n derivatives
65  \param t position to evaluate
66  \param n number of derivatives (not counting value)
67  \returns a vector with the value and the n derivative evaluations
68 
69 There is an elegant way to compute the value and n derivatives for a polynomial using a variant of horner's rule.  Someone will someday work out how for sbasis.
70 */
valueAndDerivatives(double t,unsigned n) const71 std::vector<double> SBasis::valueAndDerivatives(double t, unsigned n) const {
72     std::vector<double> ret(n+1);
73     ret[0] = valueAt(t);
74     SBasis tmp = *this;
75     for(unsigned i = 1; i < n+1; i++) {
76         tmp.derive();
77         ret[i] = tmp.valueAt(t);
78     }
79     return ret;
80 }
81 
82 
83 /** Compute the pointwise sum of a and b (Exact)
84  \param a,b sbasis functions
85  \returns sbasis equal to a+b
86 
87 */
operator +(const SBasis & a,const SBasis & b)88 SBasis operator+(const SBasis& a, const SBasis& b) {
89     const unsigned out_size = std::max(a.size(), b.size());
90     const unsigned min_size = std::min(a.size(), b.size());
91     SBasis result(out_size, Linear());
92 
93     for(unsigned i = 0; i < min_size; i++) {
94         result[i] = a[i] + b[i];
95     }
96     for(unsigned i = min_size; i < a.size(); i++)
97         result[i] = a[i];
98     for(unsigned i = min_size; i < b.size(); i++)
99         result[i] = b[i];
100 
101     assert(result.size() == out_size);
102     return result;
103 }
104 
105 /** Compute the pointwise difference of a and b (Exact)
106  \param a,b sbasis functions
107  \returns sbasis equal to a-b
108 
109 */
operator -(const SBasis & a,const SBasis & b)110 SBasis operator-(const SBasis& a, const SBasis& b) {
111     const unsigned out_size = std::max(a.size(), b.size());
112     const unsigned min_size = std::min(a.size(), b.size());
113     SBasis result(out_size, Linear());
114 
115     for(unsigned i = 0; i < min_size; i++) {
116         result[i] = a[i] - b[i];
117     }
118     for(unsigned i = min_size; i < a.size(); i++)
119         result[i] = a[i];
120     for(unsigned i = min_size; i < b.size(); i++)
121         result[i] = -b[i];
122 
123     assert(result.size() == out_size);
124     return result;
125 }
126 
127 /** Compute the pointwise sum of a and b and store in a (Exact)
128  \param a,b sbasis functions
129  \returns sbasis equal to a+b
130 
131 */
operator +=(SBasis & a,const SBasis & b)132 SBasis& operator+=(SBasis& a, const SBasis& b) {
133     const unsigned out_size = std::max(a.size(), b.size());
134     const unsigned min_size = std::min(a.size(), b.size());
135     a.resize(out_size);
136 
137     for(unsigned i = 0; i < min_size; i++)
138         a[i] += b[i];
139     for(unsigned i = min_size; i < b.size(); i++)
140         a[i] = b[i];
141 
142     assert(a.size() == out_size);
143     return a;
144 }
145 
146 /** Compute the pointwise difference of a and b and store in a (Exact)
147  \param a,b sbasis functions
148  \returns sbasis equal to a-b
149 
150 */
operator -=(SBasis & a,const SBasis & b)151 SBasis& operator-=(SBasis& a, const SBasis& b) {
152     const unsigned out_size = std::max(a.size(), b.size());
153     const unsigned min_size = std::min(a.size(), b.size());
154     a.resize(out_size);
155 
156     for(unsigned i = 0; i < min_size; i++)
157         a[i] -= b[i];
158     for(unsigned i = min_size; i < b.size(); i++)
159         a[i] = -b[i];
160 
161     assert(a.size() == out_size);
162     return a;
163 }
164 
165 /** Compute the pointwise product of a and b (Exact)
166  \param a,b sbasis functions
167  \returns sbasis equal to a*b
168 
169 */
operator *(SBasis const & a,double k)170 SBasis operator*(SBasis const &a, double k) {
171     SBasis c(a.size(), Linear());
172     for(unsigned i = 0; i < a.size(); i++)
173         c[i] = a[i] * k;
174     return c;
175 }
176 
177 /** Compute the pointwise product of a and b and store the value in a (Exact)
178  \param a,b sbasis functions
179  \returns sbasis equal to a*b
180 
181 */
operator *=(SBasis & a,double b)182 SBasis& operator*=(SBasis& a, double b) {
183     if (a.isZero()) return a;
184     if (b == 0)
185         a.clear();
186     else
187         for(auto & i : a)
188             i *= b;
189     return a;
190 }
191 
192 /** multiply a by x^sh in place (Exact)
193  \param a sbasis function
194  \param sh power
195  \returns a
196 
197 */
shift(SBasis const & a,int sh)198 SBasis shift(SBasis const &a, int sh) {
199     size_t n = a.size()+sh;
200     SBasis c(n, Linear());
201     size_t m = std::max(0, sh);
202 
203     for(int i = 0; i < sh; i++)
204         c[i] = Linear(0,0);
205     for(size_t i = m, j = std::max(0,-sh); i < n; i++, j++)
206         c[i] = a[j];
207     return c;
208 }
209 
210 /** multiply a by x^sh  (Exact)
211  \param a linear function
212  \param sh power
213  \returns a* x^sh
214 
215 */
shift(Linear const & a,int sh)216 SBasis shift(Linear const &a, int sh) {
217     size_t n = 1+sh;
218     SBasis c(n, Linear());
219 
220     for(int i = 0; i < sh; i++)
221         c[i] = Linear(0,0);
222     if(sh >= 0)
223         c[sh] = a;
224     return c;
225 }
226 
227 #if 0
228 SBasis multiply(SBasis const &a, SBasis const &b) {
229     // c = {a0*b0 - shift(1, a.Tri*b.Tri), a1*b1 - shift(1, a.Tri*b.Tri)}
230 
231     // shift(1, a.Tri*b.Tri)
232     SBasis c(a.size() + b.size(), Linear(0,0));
233     if(a.isZero() || b.isZero())
234         return c;
235     for(unsigned j = 0; j < b.size(); j++) {
236         for(unsigned i = j; i < a.size()+j; i++) {
237             double tri = b[j].tri()*a[i-j].tri();
238             c[i+1/*shift*/] += Linear(-tri);
239         }
240     }
241     for(unsigned j = 0; j < b.size(); j++) {
242         for(unsigned i = j; i < a.size()+j; i++) {
243             for(unsigned dim = 0; dim < 2; dim++)
244                 c[i][dim] += b[j][dim]*a[i-j][dim];
245         }
246     }
247     c.normalize();
248     //assert(!(0 == c.back()[0] && 0 == c.back()[1]));
249     return c;
250 }
251 #else
252 
253 /** Compute the pointwise product of a and b adding c (Exact)
254  \param a,b,c sbasis functions
255  \returns sbasis equal to a*b+c
256 
257 The added term is almost free
258 */
multiply_add(SBasis const & a,SBasis const & b,SBasis c)259 SBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c) {
260     if(a.isZero() || b.isZero())
261         return c;
262     c.resize(a.size() + b.size(), Linear(0,0));
263     for(unsigned j = 0; j < b.size(); j++) {
264         for(unsigned i = j; i < a.size()+j; i++) {
265             double tri = b[j].tri()*a[i-j].tri();
266             c[i+1/*shift*/] += Linear(-tri);
267         }
268     }
269     for(unsigned j = 0; j < b.size(); j++) {
270         for(unsigned i = j; i < a.size()+j; i++) {
271             for(unsigned dim = 0; dim < 2; dim++)
272                 c[i][dim] += b[j][dim]*a[i-j][dim];
273         }
274     }
275     c.normalize();
276     //assert(!(0 == c.back()[0] && 0 == c.back()[1]));
277     return c;
278 }
279 
280 /** Compute the pointwise product of a and b (Exact)
281  \param a,b sbasis functions
282  \returns sbasis equal to a*b
283 
284 */
multiply(SBasis const & a,SBasis const & b)285 SBasis multiply(SBasis const &a, SBasis const &b) {
286     if(a.isZero() || b.isZero()) {
287         SBasis c(1, Linear(0,0));
288         return c;
289     }
290     SBasis c(a.size() + b.size(), Linear(0,0));
291     return multiply_add(a, b, c);
292 }
293 #endif
294 /** Compute the integral of a (Exact)
295  \param a sbasis functions
296  \returns sbasis integral(a)
297 
298 */
integral(SBasis const & c)299 SBasis integral(SBasis const &c) {
300     SBasis a;
301     a.resize(c.size() + 1, Linear(0,0));
302     a[0] = Linear(0,0);
303 
304     for(unsigned k = 1; k < c.size() + 1; k++) {
305         double ahat = -c[k-1].tri()/(2*k);
306         a[k][0] = a[k][1] = ahat;
307     }
308     double aTri = 0;
309     for(int k = c.size()-1; k >= 0; k--) {
310         aTri = (c[k].hat() + (k+1)*aTri/2)/(2*k+1);
311         a[k][0] -= aTri/2;
312         a[k][1] += aTri/2;
313     }
314     a.normalize();
315     return a;
316 }
317 
318 /** Compute the derivative of a (Exact)
319  \param a sbasis functions
320  \returns sbasis da/dt
321 
322 */
derivative(SBasis const & a)323 SBasis derivative(SBasis const &a) {
324     SBasis c;
325     c.resize(a.size(), Linear(0,0));
326     if(a.isZero())
327         return c;
328 
329     for(unsigned k = 0; k < a.size()-1; k++) {
330         double d = (2*k+1)*(a[k][1] - a[k][0]);
331 
332         c[k][0] = d + (k+1)*a[k+1][0];
333         c[k][1] = d - (k+1)*a[k+1][1];
334     }
335     int k = a.size()-1;
336     double d = (2*k+1)*(a[k][1] - a[k][0]);
337     if (d == 0 && k > 0) {
338         c.pop_back();
339     } else {
340         c[k][0] = d;
341         c[k][1] = d;
342     }
343 
344     return c;
345 }
346 
347 /** Compute the derivative of this inplace (Exact)
348 
349 */
derive()350 void SBasis::derive() { // in place version
351     if(isZero()) return;
352     for(unsigned k = 0; k < size()-1; k++) {
353         double d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
354 
355         (*this)[k][0] = d + (k+1)*(*this)[k+1][0];
356         (*this)[k][1] = d - (k+1)*(*this)[k+1][1];
357     }
358     int k = size()-1;
359     double d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
360     if (d == 0 && k > 0) {
361         pop_back();
362     } else {
363         (*this)[k][0] = d;
364         (*this)[k][1] = d;
365     }
366 }
367 
368 /** Compute the sqrt of a
369  \param a sbasis functions
370  \returns sbasis \f[ \sqrt{a} \f]
371 
372 It is recommended to use the piecewise version unless you have good reason.
373 TODO: convert int k to unsigned k, and remove cast
374 */
sqrt(SBasis const & a,int k)375 SBasis sqrt(SBasis const &a, int k) {
376     SBasis c;
377     if(a.isZero() || k == 0)
378         return c;
379     c.resize(k, Linear(0,0));
380     c[0] = Linear(std::sqrt(a[0][0]), std::sqrt(a[0][1]));
381     SBasis r = a - multiply(c, c); // remainder
382 
383     for(unsigned i = 1; i <= (unsigned)k && i<r.size(); i++) {
384         Linear ci(r[i][0]/(2*c[0][0]), r[i][1]/(2*c[0][1]));
385         SBasis cisi = shift(ci, i);
386         r -= multiply(shift((c*2 + cisi), i), SBasis(ci));
387         r.truncate(k+1);
388         c += cisi;
389         if(r.tailError(i) == 0) // if exact
390             break;
391     }
392 
393     return c;
394 }
395 
396 /** Compute the recpirocal of a
397  \param a sbasis functions
398  \returns sbasis 1/a
399 
400 It is recommended to use the piecewise version unless you have good reason.
401 */
reciprocal(Linear const & a,int k)402 SBasis reciprocal(Linear const &a, int k) {
403     SBasis c;
404     assert(!a.isZero());
405     c.resize(k, Linear(0,0));
406     double r_s0 = (a.tri()*a.tri())/(-a[0]*a[1]);
407     double r_s0k = 1;
408     for(unsigned i = 0; i < (unsigned)k; i++) {
409         c[i] = Linear(r_s0k/a[0], r_s0k/a[1]);
410         r_s0k *= r_s0;
411     }
412     return c;
413 }
414 
415 /** Compute  a / b to k terms
416  \param a,b sbasis functions
417  \returns sbasis a/b
418 
419 It is recommended to use the piecewise version unless you have good reason.
420 */
divide(SBasis const & a,SBasis const & b,int k)421 SBasis divide(SBasis const &a, SBasis const &b, int k) {
422     SBasis c;
423     assert(!a.isZero());
424     SBasis r = a; // remainder
425 
426     k++;
427     r.resize(k, Linear(0,0));
428     c.resize(k, Linear(0,0));
429 
430     for(unsigned i = 0; i < (unsigned)k; i++) {
431         Linear ci(r[i][0]/b[0][0], r[i][1]/b[0][1]); //H0
432         c[i] += ci;
433         r -= shift(multiply(ci,b), i);
434         r.truncate(k+1);
435         if(r.tailError(i) == 0) // if exact
436             break;
437     }
438 
439     return c;
440 }
441 
442 /** Compute  a composed with b
443  \param a,b sbasis functions
444  \returns sbasis a(b(t))
445 
446  return a0 + s(a1 + s(a2 +...  where s = (1-u)u; ak =(1 - u)a^0_k + ua^1_k
447 */
compose(SBasis const & a,SBasis const & b)448 SBasis compose(SBasis const &a, SBasis const &b) {
449     SBasis s = multiply((SBasis(Linear(1,1))-b), b);
450     SBasis r;
451 
452     for(int i = a.size()-1; i >= 0; i--) {
453         r = multiply_add(r, s, SBasis(Linear(a[i][0])) - b*a[i][0] + b*a[i][1]);
454     }
455     return r;
456 }
457 
458 /** Compute  a composed with b to k terms
459  \param a,b sbasis functions
460  \returns sbasis a(b(t))
461 
462  return a0 + s(a1 + s(a2 +...  where s = (1-u)u; ak =(1 - u)a^0_k + ua^1_k
463 */
compose(SBasis const & a,SBasis const & b,unsigned k)464 SBasis compose(SBasis const &a, SBasis const &b, unsigned k) {
465     SBasis s = multiply((SBasis(Linear(1,1))-b), b);
466     SBasis r;
467 
468     for(int i = a.size()-1; i >= 0; i--) {
469         r = multiply_add(r, s, SBasis(Linear(a[i][0])) - b*a[i][0] + b*a[i][1]);
470     }
471     r.truncate(k);
472     return r;
473 }
474 
portion(const SBasis & t,double from,double to)475 SBasis portion(const SBasis &t, double from, double to) {
476     double fv = t.valueAt(from);
477     double tv = t.valueAt(to);
478     SBasis ret = compose(t, Linear(from, to));
479     ret.at0() = fv;
480     ret.at1() = tv;
481     return ret;
482 }
483 
484 /*
485 Inversion algorithm. The notation is certainly very misleading. The
486 pseudocode should say:
487 
488 c(v) := 0
489 r(u) := r_0(u) := u
490 for i:=0 to k do
491   c_i(v) := H_0(r_i(u)/(t_1)^i; u)
492   c(v) := c(v) + c_i(v)*t^i
493   r(u) := r(u) ? c_i(u)*(t(u))^i
494 endfor
495 */
496 
497 //#define DEBUG_INVERSION 1
498 
499 /** find the function a^-1 such that a^-1 composed with a to k terms is the identity function
500  \param a sbasis function
501  \returns sbasis a^-1 s.t. a^-1(a(t)) = 1
502 
503  The function must have 'unit range'("a00 = 0 and a01 = 1") and be monotonic.
504 */
inverse(SBasis a,int k)505 SBasis inverse(SBasis a, int k) {
506     assert(a.size() > 0);
507     double a0 = a[0][0];
508     if(a0 != 0) {
509         a -= a0;
510     }
511     double a1 = a[0][1];
512     assert(a1 != 0); // not invertable.
513 
514     if(a1 != 1) {
515         a /= a1;
516     }
517     SBasis c(k, Linear());                           // c(v) := 0
518     if(a.size() >= 2 && k == 2) {
519         c[0] = Linear(0,1);
520         Linear t1(1+a[1][0], 1-a[1][1]);    // t_1
521         c[1] = Linear(-a[1][0]/t1[0], -a[1][1]/t1[1]);
522     } else if(a.size() >= 2) {                      // non linear
523         SBasis r = Linear(0,1);             // r(u) := r_0(u) := u
524         Linear t1(1./(1+a[1][0]), 1./(1-a[1][1]));    // 1./t_1
525         Linear one(1,1);
526         Linear t1i = one;                   // t_1^0
527         SBasis one_minus_a = SBasis(one) - a;
528         SBasis t = multiply(one_minus_a, a); // t(u)
529         SBasis ti(one);                     // t(u)^0
530 #ifdef DEBUG_INVERSION
531         std::cout << "a=" << a << std::endl;
532         std::cout << "1-a=" << one_minus_a << std::endl;
533         std::cout << "t1=" << t1 << std::endl;
534         //assert(t1 == t[1]);
535 #endif
536 
537         //c.resize(k+1, Linear(0,0));
538         for(unsigned i = 0; i < (unsigned)k; i++) {   // for i:=0 to k do
539 #ifdef DEBUG_INVERSION
540             std::cout << "-------" << i << ": ---------" <<std::endl;
541             std::cout << "r=" << r << std::endl
542                       << "c=" << c << std::endl
543                       << "ti=" << ti << std::endl
544                       << std::endl;
545 #endif
546             if(r.size() <= i)                // ensure enough space in the remainder, probably not needed
547                 r.resize(i+1, Linear(0,0));
548             Linear ci(r[i][0]*t1i[0], r[i][1]*t1i[1]); // c_i(v) := H_0(r_i(u)/(t_1)^i; u)
549 #ifdef DEBUG_INVERSION
550             std::cout << "t1i=" << t1i << std::endl;
551             std::cout << "ci=" << ci << std::endl;
552 #endif
553             for(int dim = 0; dim < 2; dim++) // t1^-i *= 1./t1
554                 t1i[dim] *= t1[dim];
555             c[i] = ci; // c(v) := c(v) + c_i(v)*t^i
556             // change from v to u parameterisation
557             SBasis civ = one_minus_a*ci[0] + a*ci[1];
558             // r(u) := r(u) - c_i(u)*(t(u))^i
559             // We can truncate this to the number of final terms, as no following terms can
560             // contribute to the result.
561             r -= multiply(civ,ti);
562             r.truncate(k);
563             if(r.tailError(i) == 0)
564                 break; // yay!
565             ti = multiply(ti,t);
566         }
567 #ifdef DEBUG_INVERSION
568         std::cout << "##########################" << std::endl;
569 #endif
570     } else
571         c = Linear(0,1); // linear
572     c -= a0; // invert the offset
573     c /= a1; // invert the slope
574     return c;
575 }
576 
577 /** Compute the sine of a to k terms
578  \param b linear function
579  \returns sbasis sin(a)
580 
581 It is recommended to use the piecewise version unless you have good reason.
582 */
sin(Linear b,int k)583 SBasis sin(Linear b, int k) {
584     SBasis s(k+2, Linear());
585     s[0] = Linear(std::sin(b[0]), std::sin(b[1]));
586     double tr = s[0].tri();
587     double t2 = b.tri();
588     s[1] = Linear(std::cos(b[0])*t2 - tr, -std::cos(b[1])*t2 + tr);
589 
590     t2 *= t2;
591     for(int i = 0; i < k; i++) {
592         Linear bo(4*(i+1)*s[i+1][0] - 2*s[i+1][1],
593                   -2*s[i+1][0] + 4*(i+1)*s[i+1][1]);
594         bo -= s[i]*(t2/(i+1));
595 
596 
597         s[i+2] = bo/double(i+2);
598     }
599 
600     return s;
601 }
602 
603 /** Compute the cosine of a
604  \param b linear function
605  \returns sbasis cos(a)
606 
607 It is recommended to use the piecewise version unless you have good reason.
608 */
cos(Linear bo,int k)609 SBasis cos(Linear bo, int k) {
610     return sin(Linear(bo[0] + M_PI/2,
611                       bo[1] + M_PI/2),
612                k);
613 }
614 
615 /** compute fog^-1.
616  \param f,g sbasis functions
617  \returns sbasis f(g^-1(t)).
618 
619 ("zero" = double comparison threshold. *!*we might divide by "zero"*!*)
620 TODO: compute order according to tol?
621 TODO: requires g(0)=0 & g(1)=1 atm... adaptation to other cases should be obvious!
622 */
compose_inverse(SBasis const & f,SBasis const & g,unsigned order,double zero)623 SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero){
624     SBasis result(order, Linear(0.)); //result
625     SBasis r=f; //remainder
626     SBasis Pk=Linear(1)-g,Qk=g,sg=Pk*Qk;
627     Pk.truncate(order);
628     Qk.truncate(order);
629     Pk.resize(order,Linear(0.));
630     Qk.resize(order,Linear(0.));
631     r.resize(order,Linear(0.));
632 
633     int vs = valuation(sg,zero);
634     if (vs == 0) { // to prevent infinite loop
635         return result;
636     }
637 
638     for (unsigned k=0; k<order; k+=vs){
639         double p10 = Pk.at(k)[0];// we have to solve the linear system:
640         double p01 = Pk.at(k)[1];//
641         double q10 = Qk.at(k)[0];//   p10*a + q10*b = r10
642         double q01 = Qk.at(k)[1];// &
643         double r10 =  r.at(k)[0];//   p01*a + q01*b = r01
644         double r01 =  r.at(k)[1];//
645         double a,b;
646         double det = p10*q01-p01*q10;
647 
648         //TODO: handle det~0!!
649         if (fabs(det)<zero){
650             a=b=0;
651         }else{
652             a=( q01*r10-q10*r01)/det;
653             b=(-p01*r10+p10*r01)/det;
654         }
655         result[k] = Linear(a,b);
656         r=r-Pk*a-Qk*b;
657 
658         Pk=Pk*sg;
659         Qk=Qk*sg;
660 
661         Pk.resize(order,Linear(0.)); // truncates if too high order, expands with zeros if too low
662         Qk.resize(order,Linear(0.));
663         r.resize(order,Linear(0.));
664 
665     }
666     result.normalize();
667     return result;
668 }
669 
670 }
671 
672 /*
673   Local Variables:
674   mode:c++
675   c-file-style:"stroustrup"
676   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
677   indent-tabs-mode:nil
678   fill-column:99
679   End:
680 */
681 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
682