00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019
00020
00021 int ON_FindLocalMinimum(
00022 int (*f)(void*,double,double*,double*), void* farg,
00023 double ax, double bx, double cx,
00024 double rel_stepsize_tol, double abs_stepsize_tol, int max_it,
00025 double *t_addr
00026 )
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 {
00065
00066 int rc,ok1,ok2;
00067 double a,b,d,d1,d2,du,dv,dw,dx,e,fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm;
00068
00069 d=e=0.0;
00070
00071 if ( 0 == t_addr )
00072 {
00073 ON_ERROR("t_addr is NULL");
00074 return 0;
00075 }
00076
00077 *t_addr = bx;
00078
00079 if ( max_it < 2 )
00080 {
00081 ON_ERROR("max_it must be >= 2");
00082 return 0;
00083 }
00084 if ( !ON_IsValid(rel_stepsize_tol) || rel_stepsize_tol <= 0.0 || rel_stepsize_tol >= 1.0 )
00085 {
00086 ON_ERROR("rel_stepsize_tol must be strictly between 0.0 and 1.0");
00087 return 0;
00088 }
00089 if ( !ON_IsValid(abs_stepsize_tol) || abs_stepsize_tol <= 0.0 )
00090 {
00091 ON_ERROR("abs_stepsize_tol must be > 0");
00092 return 0;
00093 }
00094
00095 a=(ax < cx ? ax : cx);
00096 b=(ax > cx ? ax : cx);
00097 x=w=v=bx;
00098 rc = f(farg,x,&fx,&dx);
00099 if (rc) {
00100
00101 if ( rc < 0 ) {
00102 ON_ERROR("ON_FindLocalMinimum() f() failed to evaluate.");
00103 }
00104 *t_addr = x;
00105 return rc>0 ? 1 : 0;
00106 }
00107 fw=fv=fx;
00108 dw=dv=dx;
00109 while(max_it--) {
00110 xm=0.5*(a+b);
00111 tol1=rel_stepsize_tol*fabs(x)+abs_stepsize_tol;
00112 tol2=2.0*tol1;
00113 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00114
00115 *t_addr=x;
00116 return 1;
00117 }
00118 if (fabs(e) > tol1) {
00119 d1=2.0*(b-a);
00120 d2=d1;
00121 if (dw != dx) d1=(w-x)*dx/(dx-dw);
00122 if (dv != dx) d2=(v-x)*dx/(dx-dv);
00123 u1=x+d1;
00124 u2=x+d2;
00125 ok1 = (a-u1)*(u1-b) > 0.0 && dx*d1 <= 0.0;
00126 ok2 = (a-u2)*(u2-b) > 0.0 && dx*d2 <= 0.0;
00127 olde=e;
00128 e=d;
00129 if (ok1 || ok2) {
00130 if (ok1 && ok2)
00131 d=(fabs(d1) < fabs(d2) ? d1 : d2);
00132 else if (ok1)
00133 d=d1;
00134 else
00135 d=d2;
00136 if (fabs(d) <= fabs(0.5*olde)) {
00137 u=x+d;
00138 if (u-a < tol2 || b-u < tol2)
00139 {d = (xm >= x) ? tol1 : -tol1;}
00140 } else {
00141 d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
00142 }
00143 } else {
00144 d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
00145 }
00146 } else {
00147 d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
00148 }
00149 if (fabs(d) >= tol1) {
00150 u=x+d;
00151 rc = f(farg,u,&fu,&du);
00152 }
00153 else {
00154 u = (d >= 0.0) ? x+tol1 : x-tol1;
00155 rc = f(farg,u,&fu,&du);
00156 if (rc >= 0 && fu > fx) {
00157
00158 *t_addr=x;
00159 return 1;
00160 }
00161 }
00162 if (rc) {
00163
00164 if ( rc < 0 ) {
00165 ON_ERROR("ON_FindLocalMinimum() f() failed to evaluate.");
00166 }
00167 else {
00168 *t_addr = (fu < fx) ? u : x;
00169 }
00170 return rc>0 ? 1 : 0;
00171 }
00172 if (fu <= fx) {
00173 if (u >= x) a=x; else b=x;
00174 v=w;fv=fw;dv=dw;
00175 w=x;fw=fx;dw=dx;
00176 x=u;fx=fu;dx=du;
00177 } else {
00178 if (u < x) a=u; else b=u;
00179 if (fu <= fw || w == x) {
00180 v=w;fv=fw;dv=dw;
00181 w=u;fw=fu;dw=du;
00182 } else if (fu < fv || v == x || v == w) {
00183 v=u;fv=fu;dv=du;
00184 }
00185 }
00186 }
00187 *t_addr = x;
00188 ON_ERROR("ON_FindLocalMinimum() failed to converge");
00189 return 2;
00190 }
00191
00192
00193 ON_LocalZero1::ON_LocalZero1()
00194 : m_t0(ON_UNSET_VALUE), m_t1(ON_UNSET_VALUE),
00195 m_f_tolerance(0.0), m_t_tolerance(0.0),
00196 m_k(NULL), m_k_count(0)
00197 {}
00198
00199 ON_LocalZero1::~ON_LocalZero1()
00200 {}
00201
00202 ON_BOOL32
00203 ON_LocalZero1::BracketZero( double s0, double f0,
00204 double s1, double f1,
00205 int level )
00206 {
00207 double s, f, d;
00208
00209
00210 if ( (f0 <= 0.0 && f1 >= 0.0) || (f0 >= 0.0 && f1 <= 0.0)
00211 || fabs(f0) <= m_f_tolerance || fabs(f1) <= m_f_tolerance ) {
00212 m_t0 = s0;
00213 m_t1 = s1;
00214 return true;
00215 }
00216
00217 if ( level++ <= 8 ) {
00218 s = 0.5*s0+s1;
00219 if ( s0 < s && s < s1 && Evaluate(s,&f,&d,0) ) {
00220 if ( f*d >= 0.0 ) {
00221
00222 if ( BracketZero(s0,f0,s,f,level ) ) {
00223 m_s0 = s0;
00224 m_f0 = f0;
00225 m_s1 = s;
00226 m_f1 = f;
00227 return true;
00228 }
00229 if ( BracketZero(s,f,s1,f1,level ) ) {
00230 m_s0 = s;
00231 m_f0 = f;
00232 m_s1 = s1;
00233 m_f1 = f1;
00234 return true;
00235 }
00236 }
00237 else {
00238
00239 if ( BracketZero(s,f,s1,f1,level ) ) {
00240 m_s0 = s;
00241 m_f0 = f;
00242 m_s1 = s1;
00243 m_f1 = f1;
00244 return true;
00245 }
00246 if ( BracketZero(s0,f0,s,f,level ) ) {
00247 m_s0 = s0;
00248 m_f0 = f0;
00249 m_s1 = s;
00250 m_f1 = f;
00251 return true;
00252 }
00253 }
00254 }
00255 }
00256 return false;
00257 }
00258
00259 ON_BOOL32
00260 ON_LocalZero1::BracketSpan( double s0, double f0, double s1, double f1 )
00261 {
00262 int i0, i1, i;
00263 double fm, fp;
00264 ON_BOOL32 rc = true;
00265 if ( m_k && m_k_count >= 3 ) {
00266 i0 = ON_SearchMonotoneArray(m_k,m_k_count,s0);
00267 if ( i0 < 0 )
00268 i0 = 0;
00269 i1 = ON_SearchMonotoneArray(m_k,m_k_count,s1);
00270 if ( i1 >= m_k_count )
00271 i1 = m_k_count-1;
00272 while ( i1 >= 0 && s1 == m_k[i1] ) {
00273 i1--;
00274 }
00275 i0++;
00276 while ( i0 < m_k_count-1 && m_k[i0] == m_k[i0+1] )
00277 i0++;
00278 if ( i0 <= i1 ) {
00279
00280 Evaluate( m_k[i0], &fm, NULL,-1 );
00281 Evaluate( m_k[i0], &fp, NULL, 1 );
00282 if ( (f0 <= 0.0 && fm >= 0.0) || (f0 >= 0.0 && fm <= 0.0) ) {
00283 m_s1 = m_k[i0];
00284 m_f1 = fm;
00285 }
00286 else if ( (f1 <= 0.0 && fp >= 0.0) || (f1 >= 0.0 && fp <= 0.0) ) {
00287 m_s0 = m_k[i0];
00288 m_f0 = fp;
00289 if ( i0 < i1 ) {
00290 Evaluate( m_k[i1], &fm, NULL, -1 );
00291 Evaluate( m_k[i1], &fp, NULL, 1 );
00292 if ( (f1 <= 0.0 && fp >= 0.0) || (f1 >= 0.0 && fp <= 0.0) ) {
00293 m_s0 = m_k[i1];
00294 m_f0 = fp;
00295 }
00296 else if ( (f0 <= 0.0 && fm >= 0.0) || (f0 >= 0.0 && fm <= 0.0) ) {
00297 m_s1 = m_k[i1];
00298 m_f1 = fm;
00299
00300 while (i0+1 < i1) {
00301
00302
00303
00304 i = (i0+i1)>>1;
00305 Evaluate( m_k[i], &fm, NULL, -1 );
00306 Evaluate( m_k[i], &fp, NULL, 1 );
00307 if ( (f0 <= 0.0 && fm >= 0.0) || (f0 >= 0.0 && fm <= 0.0) ) {
00308 m_s1 = m_k[i];
00309 m_f1 = fm;
00310 i1 = i;
00311 while ( i1>0 && m_k[i1-1]==m_k[i1])
00312 i1--;
00313 }
00314 else if ( (f1 <= 0.0 && fp >= 0.0) || (f1 >= 0.0 && fp <= 0.0) ) {
00315 m_s0 = m_k[i];
00316 m_f0 = fp;
00317 i0 = i;
00318 while ( i0 < m_k_count-2 && m_k[i0] == m_k[i0+1] )
00319 i0++;
00320 }
00321 else {
00322
00323 rc = false;
00324 break;
00325 }
00326 }
00327 }
00328 else {
00329
00330 rc = false;
00331 }
00332 }
00333 }
00334 else {
00335
00336 rc = false;
00337 }
00338 }
00339 }
00340 return rc;
00341 }
00342
00343 ON_BOOL32 ON_LocalZero1::FindZero( double* t )
00344 {
00345
00346
00347 ON_BOOL32 rc = ( m_t0 == ON_UNSET_VALUE || m_t0 == ON_UNSET_VALUE ) ? true : false;
00348
00349 if ( rc ) {
00350 if ( m_t0 < m_t0 ) {
00351 m_s0 = m_t0;
00352 m_s1 = m_t0;
00353 }
00354 else {
00355 m_s0 = m_t1;
00356 m_s1 = m_t0;
00357 if ( m_t0 == m_t1 ) {
00358 if ( Evaluate( m_t0, &m_f0, NULL, 1 ) ) {
00359 m_f1 = m_f0;
00360 if ( fabs(m_f0) <= m_f_tolerance ) {
00361 *t = m_t0;
00362 return true;
00363 }
00364 }
00365 ON_ERROR("Illegal input");
00366 return false;
00367 }
00368 }
00369 }
00370
00371 if (rc)
00372 rc = Evaluate( m_s0, &m_f0, NULL, 1 );
00373 if (rc)
00374 rc = Evaluate( m_s1, &m_f1, NULL, -1 );
00375
00376 if (rc)
00377 rc = BracketZero( m_s0, m_f0, m_s1, m_f1 );
00378 if ( rc ) {
00379 if ( fabs(m_f0) <= m_f_tolerance && fabs(m_f0) <= fabs(m_f1) ) {
00380
00381 *t = m_s0;
00382 }
00383 else if ( fabs(m_f1) <= m_f_tolerance ) {
00384
00385 *t = m_s1;
00386 }
00387 else {
00388 if (rc)
00389 rc = BracketSpan( m_s0, m_f0, m_s1, m_f1 );
00390 if (rc)
00391 rc = NewtonRaphson( m_s0, m_f0, m_s1, m_f1, 128, t );
00392 }
00393 }
00394 if (!rc) {
00395 ON_ERROR("ON_LocalZero1::FindZero() failed");
00396 }
00397
00398 return rc;
00399 }
00400
00401 ON_BOOL32 ON_LocalZero1::NewtonRaphson( double s0, double f0,
00402 double s1, double f1,
00403 int maxit, double* t )
00404 {
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 double s, f, d, x, ds, prevds;
00427
00428 if ( fabs(f0) <= m_f_tolerance && fabs(f0) <= fabs(f1) ) {
00429
00430 *t = s0;
00431 return true;
00432 }
00433 if ( fabs(f1) <= m_f_tolerance ) {
00434
00435 *t = s1;
00436 return true;
00437 }
00438
00439 if ( f0 > 0.0 ) {
00440 x = s0; s0 = s1; s1 = x;
00441 x = f0; f0 = f1; f1 = x;
00442 }
00443
00444 s = 0.5*(s0+s1);
00445 if ( !Evaluate( s, &f, &d, 0 ) ) {
00446 *t = (fabs(f0) <= fabs(f1)) ? s0 : s1;
00447 return false;
00448 }
00449
00450 if ( fabs(f) <= m_f_tolerance ) {
00451
00452 *t = s;
00453 return true;
00454 }
00455
00456 if ( f1 <= 0.0 ) {
00457 *t = (fabs(f0) <= fabs(f1)) ? s0 : s1;
00458 return false;
00459 }
00460
00461 ds = fabs(s1-s0);
00462 prevds = 0.0;
00463
00464 while (maxit--) {
00465 if ( (f+(s0-s)*d)*(f+(s1-s)*d) > 0.0
00466 || fabs(2.0*f) > fabs(prevds*d)
00467 ) {
00468
00469 prevds = ds;
00470 ds = 0.5*(s1-s0);
00471 s = s0+ds;
00472 if ( s == s0 ) {
00473
00474 if ( fabs(f1) < fabs(f0) ) {
00475 s = s1;
00476 }
00477 *t = s;
00478 return true;
00479 }
00480 }
00481 else {
00482
00483 prevds = ds;
00484 ds = -f/d;
00485 x = s;
00486 s += ds;
00487 if ( s == x ) {
00488
00489 if ( fabs(f0) < fabs(f) ) {
00490 f = f0;
00491 s = s0;
00492 }
00493 if ( fabs(f1) < fabs(f) ) {
00494 s = s1;
00495 }
00496 *t = s;
00497 return true;
00498 }
00499 }
00500
00501 if ( !Evaluate( s, &f, &d, 0 ) ) {
00502 *t = (fabs(f0) <= fabs(f1)) ? s0 : s1;
00503 return false;
00504 }
00505
00506 if ( fabs(f) <= m_f_tolerance ) {
00507
00508 if ( fabs(f0) < fabs(f) ) {
00509 f = f0;
00510 *t = s0;
00511 }
00512 if ( fabs(f1) < fabs(f) ) {
00513 *t = s1;
00514 }
00515 return true;
00516 }
00517
00518 if ( f < 0.0 ) {
00519 f0 = f;
00520 s0 = s;
00521 }
00522 else {
00523 f1 = f;
00524 s1 = s;
00525 }
00526
00527 if ( fabs(s1-s0) <= m_t_tolerance ) {
00528
00529
00530 *t = (fabs(f0) <= fabs(f1)) ? s0 : s1;
00531 return true;
00532 }
00533 }
00534
00535 *t = (fabs(f0) <= fabs(f1)) ? s0 : s1;
00536 return false;
00537 }
00538