00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <2geom/sbasis-math.h>
00038
00039 #include <2geom/d2-sbasis.h>
00040 #include <stdio.h>
00041 #include <math.h>
00042
00043
00044
00045 namespace Geom {
00046
00047
00048
00052 Piecewise<SBasis> abs(SBasis const &f){
00053 return abs(Piecewise<SBasis>(f));
00054 }
00058 Piecewise<SBasis> abs(Piecewise<SBasis> const &f){
00059 Piecewise<SBasis> absf=partition(f,roots(f));
00060 for (unsigned i=0; i<absf.size(); i++){
00061 if (absf.segs[i](.5)<0) absf.segs[i]*=-1;
00062 }
00063 return absf;
00064 }
00065
00066
00070 Piecewise<SBasis> max( SBasis const &f, SBasis const &g){
00071 return max(Piecewise<SBasis>(f),Piecewise<SBasis>(g));
00072 }
00076 Piecewise<SBasis> max(Piecewise<SBasis> const &f, SBasis const &g){
00077 return max(f,Piecewise<SBasis>(g));
00078 }
00082 Piecewise<SBasis> max( SBasis const &f, Piecewise<SBasis> const &g){
00083 return max(Piecewise<SBasis>(f),g);
00084 }
00088 Piecewise<SBasis> max(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g){
00089 Piecewise<SBasis> max=partition(f,roots(f-g));
00090 Piecewise<SBasis> gg =partition(g,max.cuts);
00091 max = partition(max,gg.cuts);
00092 for (unsigned i=0; i<max.size(); i++){
00093 if (max.segs[i](.5)<gg.segs[i](.5)) max.segs[i]=gg.segs[i];
00094 }
00095 return max;
00096 }
00097
00101 Piecewise<SBasis>
00102 min( SBasis const &f, SBasis const &g){ return -max(-f,-g); }
00106 Piecewise<SBasis>
00107 min(Piecewise<SBasis> const &f, SBasis const &g){ return -max(-f,-g); }
00111 Piecewise<SBasis>
00112 min( SBasis const &f, Piecewise<SBasis> const &g){ return -max(-f,-g); }
00116 Piecewise<SBasis>
00117 min(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g){ return -max(-f,-g); }
00118
00119
00120
00124 Piecewise<SBasis> signSb(SBasis const &f){
00125 return signSb(Piecewise<SBasis>(f));
00126 }
00130 Piecewise<SBasis> signSb(Piecewise<SBasis> const &f){
00131 Piecewise<SBasis> sign=partition(f,roots(f));
00132 for (unsigned i=0; i<sign.size(); i++){
00133 sign.segs[i] = (sign.segs[i](.5)<0)? Linear(-1.):Linear(1.);
00134 }
00135 return sign;
00136 }
00137
00138
00139 static Piecewise<SBasis> sqrt_internal(SBasis const &f,
00140 double tol,
00141 int order){
00142 SBasis sqrtf;
00143 if(f.isZero() || order == 0){
00144 return Piecewise<SBasis>(sqrtf);
00145 }
00146 if (f.at0()<-tol*tol && f.at1()<-tol*tol){
00147 return sqrt_internal(-f,tol,order);
00148 }else if (f.at0()>tol*tol && f.at1()>tol*tol){
00149 sqrtf.resize(order+1, Linear(0,0));
00150 sqrtf[0] = Linear(std::sqrt(f[0][0]), std::sqrt(f[0][1]));
00151 SBasis r = f - multiply(sqrtf, sqrtf);
00152 for(unsigned i = 1; int(i) <= order && i<r.size(); i++) {
00153 Linear ci(r[i][0]/(2*sqrtf[0][0]), r[i][1]/(2*sqrtf[0][1]));
00154 SBasis cisi = shift(ci, i);
00155 r -= multiply(shift((sqrtf*2 + cisi), i), SBasis(ci));
00156 r.truncate(order+1);
00157 sqrtf[i] = ci;
00158 if(r.tailError(i) == 0)
00159 break;
00160 }
00161 }else{
00162 sqrtf = Linear(std::sqrt(fabs(f.at0())), std::sqrt(fabs(f.at1())));
00163 }
00164
00165 double err = (f - multiply(sqrtf, sqrtf)).tailError(0);
00166 if (err<tol){
00167 return Piecewise<SBasis>(sqrtf);
00168 }
00169
00170 Piecewise<SBasis> sqrtf0,sqrtf1;
00171 sqrtf0 = sqrt_internal(compose(f,Linear(0.,.5)),tol,order);
00172 sqrtf1 = sqrt_internal(compose(f,Linear(.5,1.)),tol,order);
00173 sqrtf0.setDomain(Interval(0.,.5));
00174 sqrtf1.setDomain(Interval(.5,1.));
00175 sqrtf0.concat(sqrtf1);
00176 return sqrtf0;
00177 }
00178
00182 Piecewise<SBasis> sqrt(SBasis const &f, double tol, int order){
00183 return sqrt(max(f,Linear(tol*tol)),tol,order);
00184 }
00185
00189 Piecewise<SBasis> sqrt(Piecewise<SBasis> const &f, double tol, int order){
00190 Piecewise<SBasis> result;
00191 Piecewise<SBasis> zero = Piecewise<SBasis>(Linear(tol*tol));
00192 zero.setDomain(f.domain());
00193 Piecewise<SBasis> ff=max(f,zero);
00194
00195 for (unsigned i=0; i<ff.size(); i++){
00196 Piecewise<SBasis> sqrtfi = sqrt_internal(ff.segs[i],tol,order);
00197 sqrtfi.setDomain(Interval(ff.cuts[i],ff.cuts[i+1]));
00198 result.concat(sqrtfi);
00199 }
00200 return result;
00201 }
00202
00203
00204
00210 Piecewise<SBasis> sin( SBasis const &f, double tol, int order){return(cos(-f+M_PI/2,tol,order));}
00216 Piecewise<SBasis> sin(Piecewise<SBasis> const &f, double tol, int order){return(cos(-f+M_PI/2,tol,order));}
00217
00223 Piecewise<SBasis> cos(Piecewise<SBasis> const &f, double tol, int order){
00224 Piecewise<SBasis> result;
00225 for (unsigned i=0; i<f.size(); i++){
00226 Piecewise<SBasis> cosfi = cos(f.segs[i],tol,order);
00227 cosfi.setDomain(Interval(f.cuts[i],f.cuts[i+1]));
00228 result.concat(cosfi);
00229 }
00230 return result;
00231 }
00232
00238 Piecewise<SBasis> cos( SBasis const &f, double tol, int order){
00239 double alpha = (f.at0()+f.at1())/2.;
00240 SBasis x = f-alpha;
00241 double d = x.tailError(0),err=1;
00242
00243 for (int i=1; i<=2*order; i++) err*=d/i;
00244
00245 if (err<tol){
00246 SBasis xk=Linear(1), c=Linear(1), s=Linear(0);
00247 for (int k=1; k<=2*order; k+=2){
00248 xk*=x/k;
00249
00250 err+=xk.tailError(order);
00251 xk.truncate(order);
00252 s+=xk;
00253 xk*=-x/(k+1);
00254
00255 err+=xk.tailError(order);
00256 xk.truncate(order);
00257 c+=xk;
00258 }
00259 if (err<tol){
00260 return Piecewise<SBasis>(std::cos(alpha)*c-std::sin(alpha)*s);
00261 }
00262 }
00263 Piecewise<SBasis> c0,c1;
00264 c0 = cos(compose(f,Linear(0.,.5)),tol,order);
00265 c1 = cos(compose(f,Linear(.5,1.)),tol,order);
00266 c0.setDomain(Interval(0.,.5));
00267 c1.setDomain(Interval(.5,1.));
00268 c0.concat(c1);
00269 return c0;
00270 }
00271
00272
00273
00274
00275 void truncateResult(Piecewise<SBasis> &f, int order){
00276 if (order>=0){
00277 for (unsigned k=0; k<f.segs.size(); k++){
00278 f.segs[k].truncate(order);
00279 }
00280 }
00281 }
00282
00283 Piecewise<SBasis> reciprocalOnDomain(Interval range, double tol){
00284 Piecewise<SBasis> reciprocal_fn;
00285
00286 double R=2.;
00287 SBasis reciprocal1_R=reciprocal(Linear(1,R),3);
00288 double a=range.min(), b=range.max();
00289 if (a*b<0){
00290 b=std::max(fabs(a),fabs(b));
00291 a=0;
00292 }else if (b<0){
00293 a=-range.max();
00294 b=-range.min();
00295 }
00296
00297 if (a<=tol){
00298 reciprocal_fn.push_cut(0);
00299 int i0=(int) floor(std::log(tol)/std::log(R));
00300 a=pow(R,i0);
00301 reciprocal_fn.push(Linear(1/a),a);
00302 }else{
00303 int i0=(int) floor(std::log(a)/std::log(R));
00304 a=pow(R,i0);
00305 reciprocal_fn.cuts.push_back(a);
00306 }
00307
00308 while (a<b){
00309 reciprocal_fn.push(reciprocal1_R/a,R*a);
00310 a*=R;
00311 }
00312 if (range.min()<0 || range.max()<0){
00313 Piecewise<SBasis>reciprocal_fn_neg;
00314
00315 reciprocal_fn_neg.cuts.push_back(-reciprocal_fn.cuts.back());
00316 for (unsigned i=0; i<reciprocal_fn.size(); i++){
00317 int idx=reciprocal_fn.segs.size()-1-i;
00318 reciprocal_fn_neg.push_seg(-reverse(reciprocal_fn.segs.at(idx)));
00319 reciprocal_fn_neg.push_cut(-reciprocal_fn.cuts.at(idx));
00320 }
00321 if (range.max()>0){
00322 reciprocal_fn_neg.concat(reciprocal_fn);
00323 }
00324 reciprocal_fn=reciprocal_fn_neg;
00325 }
00326
00327 return(reciprocal_fn);
00328 }
00329
00330 Piecewise<SBasis> reciprocal(SBasis const &f, double tol, int order){
00331 Piecewise<SBasis> reciprocal_fn=reciprocalOnDomain(*bounds_fast(f), tol);
00332 Piecewise<SBasis> result=compose(reciprocal_fn,f);
00333 truncateResult(result,order);
00334 return(result);
00335 }
00336 Piecewise<SBasis> reciprocal(Piecewise<SBasis> const &f, double tol, int order){
00337 Piecewise<SBasis> reciprocal_fn=reciprocalOnDomain(*bounds_fast(f), tol);
00338 Piecewise<SBasis> result=compose(reciprocal_fn,f);
00339 truncateResult(result,order);
00340 return(result);
00341 }
00342
00350 Piecewise<SBasis> interpolate(std::vector<double> times, std::vector<double> values, unsigned smoothness){
00351 assert ( values.size() == times.size() );
00352 if ( values.size() == 0 ) return Piecewise<SBasis>();
00353 if ( values.size() == 1 ) return Piecewise<SBasis>(values[0]);
00354
00355 SBasis sk = shift(Linear(1.),smoothness);
00356 SBasis bump_in = integral(sk);
00357 bump_in -= bump_in.at0();
00358 bump_in /= bump_in.at1();
00359 SBasis bump_out = reverse( bump_in );
00360
00361 Piecewise<SBasis> result;
00362 result.cuts.push_back(times[0]);
00363 for (unsigned i = 0; i<values.size()-1; i++){
00364 result.push(bump_out*values[i]+bump_in*values[i+1],times[i+1]);
00365 }
00366 return result;
00367 }
00368
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380