sbasis-math.cpp
Go to the documentation of this file.
00001 /* 00002 * sbasis-math.cpp - some std functions to work with (pw)s-basis 00003 * 00004 * Authors: 00005 * Jean-Francois Barraud 00006 * 00007 * Copyright (C) 2006-2007 authors 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it either under the terms of the GNU Lesser General Public 00011 * License version 2.1 as published by the Free Software Foundation 00012 * (the "LGPL") or, at your option, under the terms of the Mozilla 00013 * Public License Version 1.1 (the "MPL"). If you do not alter this 00014 * notice, a recipient may use your version of this file under either 00015 * the MPL or the LGPL. 00016 * 00017 * You should have received a copy of the LGPL along with this library 00018 * in the file COPYING-LGPL-2.1; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * You should have received a copy of the MPL along with this library 00021 * in the file COPYING-MPL-1.1 00022 * 00023 * The contents of this file are subject to the Mozilla Public License 00024 * Version 1.1 (the "License"); you may not use this file except in 00025 * compliance with the License. You may obtain a copy of the License at 00026 * http://www.mozilla.org/MPL/ 00027 * 00028 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY 00029 * OF ANY KIND, either express or implied. See the LGPL or the MPL for 00030 * the specific language governing rights and limitations. 00031 */ 00032 00033 //this a first try to define sqrt, cos, sin, etc... 00034 //TODO: define a truncated compose(sb,sb, order) and extend it to pw<sb>. 00035 //TODO: in all these functions, compute 'order' according to 'tol'. 00036 00037 #include <2geom/sbasis-math.h> 00038 00039 #include <2geom/d2-sbasis.h> 00040 #include <stdio.h> 00041 #include <math.h> 00042 //#define ZERO 1e-3 00043 00044 00045 namespace Geom { 00046 00047 00048 //-|x|----------------------------------------------------------------------- 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 //-max(x,y), min(x,y)-------------------------------------------------------- 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 //-sign(x)--------------------------------------------------------------- 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 //-Sqrt---------------------------------------------------------- 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); // remainder 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) // if exact 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 //-Yet another sin/cos-------------------------------------------------------------- 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 //estimate cos(x)-sum_0^order (-1)^k x^2k/2k! by the first neglicted term 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 //take also truncature errors into account... 00250 err+=xk.tailError(order); 00251 xk.truncate(order); 00252 s+=xk; 00253 xk*=-x/(k+1); 00254 //take also truncature errors into account... 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 //--1/x------------------------------------------------------------ 00273 //TODO: this implementation is just wrong. Remove or redo! 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 //TODO: deduce R from tol... 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 //TODO: define reverse(pw<sb>); 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]);//what about time?? 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 Local Variables: 00373 mode:c++ 00374 c-file-style:"stroustrup" 00375 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) 00376 indent-tabs-mode:nil 00377 fill-column:99 00378 End: 00379 */ 00380 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
