00001 #include "interval.h"
00002
00003 #include "error.h"
00004 #include "defines.h"
00005 #include "geom.h"
00006
00007 #include <math.h>
00008
00026 double NormalizeAngle(double a);
00027
00028
00029
00030
00031 double NormalizeAngle(double a)
00032 {
00033 double new_a;
00034
00035 new_a=a;
00036 if ((new_a>M_PI)||(new_a<-M_PI))
00037 new_a=atan2(sin(new_a),cos(new_a));
00038
00039 if (new_a<0.0) new_a+=M_2PI;
00040
00041 return(new_a);
00042 }
00043
00044
00045
00046
00047 void NewInterval(double lower,
00048 double upper,
00049 Tinterval *i
00050 )
00051 {
00052 i->lower_limit=lower;
00053 i->upper_limit=upper;
00054 }
00055
00056
00057
00058
00059 void CopyInterval(Tinterval *i_dst,Tinterval *i_org)
00060 {
00061 i_dst->lower_limit=i_org->lower_limit;
00062 i_dst->upper_limit=i_org->upper_limit;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 boolean CmpIntervals(Tinterval *i1,Tinterval *i2)
00073 {
00074 return((i1->lower_limit==i2->lower_limit)&&
00075 (i1->upper_limit==i2->upper_limit));
00076 }
00077
00078
00079
00080
00081 double LowerLimit(Tinterval *i)
00082 {
00083 return(i->lower_limit);
00084 }
00085
00086
00087
00088
00089 double UpperLimit(Tinterval *i)
00090 {
00091 return(i->upper_limit);
00092 }
00093
00094
00095
00096
00097
00098 double IntervalSize(Tinterval *i)
00099 {
00100 double s;
00101
00102 ROUNDUP;
00103 s=i->upper_limit-i->lower_limit;
00104 ROUNDNEAR;
00105
00106 return(s);
00107 }
00108
00109
00110
00111
00112 double IntervalCenter(Tinterval *i)
00113 {
00114 double c;
00115
00116 if (i->upper_limit==i->lower_limit)
00117 c=i->upper_limit;
00118 else
00119 {
00120 if ((i->lower_limit==-INF)&&(i->upper_limit==INF))
00121 c=0.0;
00122 else
00123 {
00124 c=(i->upper_limit+i->lower_limit)/2.0;
00125
00126
00127 if (c<i->lower_limit) c=i->lower_limit;
00128 if (c>i->upper_limit) c=i->upper_limit;
00129 }
00130 }
00131 return(c);
00132 }
00133
00134 void SetLowerLimit(double v,Tinterval *i)
00135 {
00136 i->lower_limit=v;
00137 }
00138
00139 void SetUpperLimit(double v,Tinterval *i)
00140 {
00141 i->upper_limit=v;
00142 }
00143
00144
00145
00146
00147 boolean IntervalInclusion(Tinterval *i1,Tinterval *i2)
00148 {
00149 return((i2->lower_limit<i1->lower_limit)&&(i1->upper_limit<i2->upper_limit));
00150 }
00151
00152
00153
00154
00155
00156
00157 boolean Intersect(Tinterval *i1,Tinterval *i2)
00158 {
00159 Tinterval i3;
00160
00161 return(Intersection(i1,i2,&i3));
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 boolean Intersection(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00171 {
00172 i_out->lower_limit=(i1->lower_limit>i2->lower_limit?i1->lower_limit:i2->lower_limit);
00173 i_out->upper_limit=(i1->upper_limit<i2->upper_limit?i1->upper_limit:i2->upper_limit);
00174
00175 return(i_out->lower_limit<=i_out->upper_limit);
00176 }
00177
00178
00179
00180
00181
00182 boolean Union(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00183 {
00184 boolean full;
00185
00186 full=TRUE;
00187
00188 if (i1->lower_limit>i1->upper_limit)
00189 {
00190 if (i2->lower_limit>i2->upper_limit)
00191 full=FALSE;
00192 else
00193 {
00194 i_out->lower_limit=i2->lower_limit;
00195 i_out->upper_limit=i2->upper_limit;
00196 }
00197 }
00198 else
00199 {
00200 if (i2->lower_limit>i2->upper_limit)
00201 {
00202 i_out->lower_limit=i1->lower_limit;
00203 i_out->upper_limit=i1->upper_limit;
00204 }
00205 else
00206 {
00207 i_out->lower_limit=(i1->lower_limit<i2->lower_limit?i1->lower_limit:i2->lower_limit);
00208 i_out->upper_limit=(i1->upper_limit>i2->upper_limit?i1->upper_limit:i2->upper_limit);
00209 }
00210 }
00211 return(full);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220 boolean EmptyInterval(Tinterval *i)
00221 {
00222 return(i->lower_limit>i->upper_limit);
00223 }
00224
00225
00226
00227
00228 boolean IsInside(double p,Tinterval *i)
00229 {
00230 return((p>=i->lower_limit)&&(p<=i->upper_limit));
00231 }
00232
00233
00234
00235
00236
00237 void IntervalScale(Tinterval *i1,double e,Tinterval *i_out)
00238 {
00239 double e1,e2;
00240
00241 if (e>0)
00242 {
00243
00244 ROUNDDOWN;
00245 e1=i1->lower_limit*e;
00246
00247 ROUNDUP;
00248 e2=i1->upper_limit*e;
00249 }
00250 else
00251 {
00252
00253 ROUNDDOWN;
00254 e1=i1->upper_limit*e;
00255
00256 ROUNDUP;
00257 e2=i1->lower_limit*e;
00258 }
00259 ROUNDNEAR;
00260
00261 i_out->lower_limit=e1;
00262 i_out->upper_limit=e2;
00263 }
00264
00265
00266
00267
00268
00269 void IntervalProduct(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00270 {
00271 double e[3];
00272 unsigned int i;
00273 double a,b;
00274
00275 ROUNDDOWN;
00276 e[0]=i1->lower_limit*i2->upper_limit;
00277 e[1]=i1->upper_limit*i2->lower_limit;
00278 e[2]=i1->upper_limit*i2->upper_limit;
00279
00280 a=i1->lower_limit*i2->lower_limit;
00281 for(i=0;i<3;i++)
00282 if (e[i]<a) a=e[i];
00283
00284 ROUNDUP;
00285 e[0]=i1->lower_limit*i2->upper_limit;
00286 e[1]=i1->upper_limit*i2->lower_limit;
00287 e[2]=i1->upper_limit*i2->upper_limit;
00288
00289 b=i1->lower_limit*i2->lower_limit;
00290 for(i=0;i<3;i++)
00291 if (e[i]>b) b=e[i];
00292
00293 ROUNDNEAR;
00294
00295 i_out->lower_limit=a;
00296 i_out->upper_limit=b;
00297 }
00298
00299
00300
00301
00302
00303 void IntervalAdd(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00304 {
00305 double a,b;
00306
00307 ROUNDDOWN;
00308 a=i1->lower_limit+i2->lower_limit;
00309
00310 ROUNDUP;
00311 b=i1->upper_limit+i2->upper_limit;
00312
00313 ROUNDNEAR;
00314
00315 i_out->lower_limit=a;
00316 i_out->upper_limit=b;
00317 }
00318
00319
00320
00321
00322 void IntervalSubstract(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00323 {
00324 double a,b;
00325
00326 ROUNDDOWN;
00327 a=i1->lower_limit-i2->upper_limit;
00328
00329 ROUNDUP;
00330 b=i1->upper_limit-i2->lower_limit;
00331
00332 ROUNDNEAR;
00333
00334 i_out->lower_limit=a;
00335 i_out->upper_limit=b;
00336 }
00337
00338
00339
00340
00341 void IntervalInvert(Tinterval *i,Tinterval *i_out)
00342 {
00343 double a,b;
00344
00345 a=-i->upper_limit;
00346 b=-i->lower_limit;
00347
00348 i_out->lower_limit=a;
00349 i_out->upper_limit=b;
00350 }
00351
00352 void IntervalPow(Tinterval *i,unsigned int p,Tinterval *i_out)
00353 {
00354 double a,b,e1,e2;
00355
00356 ROUNDDOWN;
00357 e1=pow(i->lower_limit,(double)p);
00358 e2=pow(i->upper_limit,(double)p);
00359
00360 if (e1<e2)
00361 a=e1;
00362 else
00363 a=e2;
00364
00365 ROUNDUP;
00366 e1=pow(i->lower_limit,(double)p);
00367 e2=pow(i->upper_limit,(double)p);
00368
00369 if (e1>e2)
00370 b=e1;
00371 else
00372 b=e2;
00373
00374 ROUNDNEAR;
00375
00376 if (((p%2)==0)&&(IsInside(0,i)))
00377 a=0;
00378
00379 i_out->lower_limit=a;
00380 i_out->upper_limit=b;
00381 }
00382
00383
00384
00385
00386 boolean IntervalSqrt(Tinterval *i,Tinterval *i_out)
00387 {
00388 double a,b;
00389
00390 if (i->upper_limit<0.0)
00391 return(FALSE);
00392
00393 ROUNDDOWN;
00394 if (i->lower_limit<=0.0)
00395 a=0.0;
00396 else
00397 a=sqrt(i->lower_limit);
00398
00399 ROUNDUP;
00400 b=sqrt(i->upper_limit);
00401
00402 ROUNDNEAR;
00403
00404 i_out->lower_limit=a;
00405 i_out->upper_limit=b;
00406
00407 return(TRUE);
00408 }
00409
00410
00411
00412 void IntervalDivision(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
00413 {
00414 double e[3];
00415 unsigned int i;
00416 double a,b;
00417
00418 if ((i2->lower_limit<=0.0)&&(i2->upper_limit>=0.0))
00419 Error("Interval division by Zero");
00420
00421 ROUNDDOWN;
00422 e[0]=i1->lower_limit/i2->upper_limit;
00423 e[1]=i1->upper_limit/i2->lower_limit;
00424 e[2]=i1->upper_limit/i2->upper_limit;
00425
00426 a=i1->lower_limit/i2->lower_limit;
00427 for(i=0;i<3;i++)
00428 if (e[i]<a) a=e[i];
00429
00430 ROUNDUP;
00431 e[0]=i1->lower_limit/i2->upper_limit;
00432 e[1]=i1->upper_limit/i2->lower_limit;
00433 e[2]=i1->upper_limit/i2->upper_limit;
00434
00435 b=i1->lower_limit/i2->lower_limit;
00436 for(i=0;i<3;i++)
00437 if (e[i]>b) b=e[i];
00438
00439 ROUNDNEAR;
00440
00441 i_out->lower_limit=a;
00442 i_out->upper_limit=b;
00443 }
00444
00445
00446
00447
00448 void IntervalOffset(Tinterval *i,double offset,Tinterval *i_out)
00449 {
00450 double a,b;
00451
00452 ROUNDDOWN;
00453 a=i->lower_limit+offset;
00454
00455 ROUNDUP;
00456 b=i->upper_limit+offset;
00457
00458 ROUNDNEAR;
00459
00460 i_out->lower_limit=a;
00461 i_out->upper_limit=b;
00462 }
00463
00464
00465
00466
00467
00468 void IntervalSinus(Tinterval *i,Tinterval *i_out)
00469 {
00470 double l,u;
00471
00472 if (IntervalSize(i)>=M_2PI)
00473 NewInterval(-1,1,i_out);
00474 else
00475 {
00476 l=NormalizeAngle(i->lower_limit);
00477 u=NormalizeAngle(i->upper_limit);
00478
00479 if (u<l)
00480 {
00481 Tinterval i_in;
00482 Tinterval i_out1,i_out2;
00483
00484 i_in.lower_limit=l;
00485 i_in.upper_limit=M_2PI;
00486
00487 IntervalSinus(&i_in,&i_out1);
00488
00489 i_in.lower_limit=0.0;
00490 i_in.upper_limit=u;
00491
00492 IntervalSinus(&i_in,&i_out2);
00493
00494 i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
00495 i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
00496 }
00497 else
00498 {
00499
00500 double a,b;
00501
00502 ROUNDUP;
00503 a=sin(l);
00504 b=sin(u);
00505 ROUNDNEAR;
00506
00507 if ((l<=M_PI_2)&&(M_PI_2<=u))
00508 i_out->upper_limit=1.0;
00509 else
00510 i_out->upper_limit=(a>b?a:b);
00511
00512 ROUNDDOWN;
00513 a=sin(l);
00514 b=sin(u);
00515 ROUNDNEAR;
00516
00517 if ((l<=(3.0*M_PI_2))&&((3.0*M_PI_2)<=u))
00518 i_out->lower_limit=-1.0;
00519 else
00520 i_out->lower_limit=(a<b?a:b);
00521 }
00522 }
00523 }
00524
00525
00526
00527
00528 void IntervalCosinus(Tinterval *i,Tinterval *i_out)
00529 {
00530 double l,u;
00531
00532 if (IntervalSize(i)>=M_2PI)
00533 NewInterval(-1,1,i_out);
00534 else
00535 {
00536 l=NormalizeAngle(i->lower_limit);
00537 u=NormalizeAngle(i->upper_limit);
00538
00539 if (u<l)
00540 {
00541 Tinterval i_in;
00542 Tinterval i_out1,i_out2;
00543
00544 i_in.lower_limit=l;
00545 i_in.upper_limit=M_2PI;
00546
00547 IntervalCosinus(&i_in,&i_out1);
00548
00549 i_in.lower_limit=0.0;
00550 i_in.upper_limit=u;
00551
00552 IntervalCosinus(&i_in,&i_out2);
00553
00554 i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
00555 i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
00556 }
00557 else
00558 {
00559 double a,b;
00560
00561 a=cos(l);
00562 b=cos(u);
00563
00564 if ((l<=0.0)&&(0.0<=u))
00565 i_out->upper_limit=1.0;
00566 else
00567 i_out->upper_limit=(a>b?a:b);
00568
00569 if ((l<=M_PI)&&(M_PI<=u))
00570 i_out->lower_limit=-1.0;
00571 else
00572 i_out->lower_limit=(a<b?a:b);
00573 }
00574 }
00575 }
00576
00577
00578 void IntervalAtan2(Tinterval *is,Tinterval *ic,Tinterval *i_out)
00579 {
00580 double a[4];
00581 unsigned int i;
00582 double t1,t2;
00583
00584 if ((IntervalSize(is)>0.5)||(IntervalSize(ic)>0.5))
00585 Error ("Interval atan2 only works for small intervals");
00586
00587 a[0]=atan2(is->lower_limit,ic->lower_limit);
00588 a[1]=atan2(is->lower_limit,ic->upper_limit);
00589 a[2]=atan2(is->upper_limit,ic->lower_limit);
00590 a[3]=atan2(is->upper_limit,ic->upper_limit);
00591
00592 t1=t2=a[0];
00593 for(i=1;i<4;i++)
00594 {
00595 if (a[i]<t1) t1=a[i];
00596 else {if (a[i]>t2) t2=a[i];}
00597 }
00598
00599 i_out->lower_limit=t1;
00600 i_out->upper_limit=t2;
00601
00602 if ((i_out->upper_limit-i_out->lower_limit)>M_PI)
00603 {
00604 double d;
00605
00606 d=i_out->lower_limit;
00607 i_out->lower_limit=i_out->upper_limit;
00608 i_out->upper_limit=d+M_2PI;
00609 }
00610 }
00611
00612
00613
00614
00615
00616 void PrintInterval(FILE *f,Tinterval *i)
00617 {
00618 if (EmptyInterval(i))
00619 fprintf(f,"(Empty Interval)");
00620
00621 fprintf(f,"[");
00622
00623 if (i->lower_limit==-INF) fprintf(f,"-inf");
00624 else fprintf(f,"%.12g",i->lower_limit);
00625
00626 fprintf(f,",");
00627
00628 if (i->upper_limit==+INF) fprintf(f,"+inf");
00629 else fprintf(f,"%.12g",i->upper_limit);
00630
00631 fprintf(f,"]");
00632 }
00633
00634
00635
00636
00637 void DeleteInterval(Tinterval *i)
00638 {
00639 }