interval.c
Go to the documentation of this file.
1 #include "interval.h"
2 
3 #include "error.h"
4 #include "defines.h"
5 #include "geom.h"
6 
7 #include <math.h>
8 
26 double NormalizeAngle(double a);
27 
28 /*
29  * moves the angle 'a' but in the interval [0,2pi]
30  */
31 double NormalizeAngle(double a)
32 {
33  double new_a;
34 
35  new_a=a;
36  if ((new_a>M_PI)||(new_a<-M_PI))
37  new_a=atan2(sin(new_a),cos(new_a));
38 
39  if (new_a<0.0) new_a+=M_2PI;
40 
41  return(new_a);
42 }
43 
44 /*
45  * Defines a new interval with limits: lower and upper
46  */
47 void NewInterval(double lower, /*lower limit of the new interval*/
48  double upper, /*upper limit of the new interval*/
49  Tinterval *i /*new interval*/
50  )
51 {
52  i->lower_limit=INF_CUT(lower);
53  i->upper_limit=INF_CUT(upper);
54 }
55 
56 /*
57  * Copies i_org into i_dst.
58  */
59 void CopyInterval(Tinterval *i_dst,Tinterval *i_org)
60 {
61  i_dst->lower_limit=i_org->lower_limit;
62  i_dst->upper_limit=i_org->upper_limit;
63 }
64 
65 /*
66  * Returns true if i1 and i2 are exactly the same.
67  * This only works for intervals that are exactly the same (copies, the same
68  * initialization,....)
69  */
71 {
72  return((i1->lower_limit==i2->lower_limit)&&
73  (i1->upper_limit==i2->upper_limit));
74 }
75 
76 /*
77  * Returns the lower limit of interval 'i'.
78  */
79 inline double LowerLimit(Tinterval *i)
80 {
81  return(i->lower_limit);
82 }
83 
84 /*
85  * Returns the upper limit of interval 'i'.
86  */
87 inline double UpperLimit(Tinterval *i)
88 {
89  return(i->upper_limit);
90 }
91 
92 /*
93  * Returns the size of interval 'i'.
94  * NOTE: For empty intervals it can return a negative size
95  */
97 {
98  double s;
99 
100  if (IS_INF(i->lower_limit)||IS_INF(i->upper_limit))
101  s=INF;
102  else
103  {
104  ROUNDUP;
105  s=i->upper_limit-i->lower_limit;
106  ROUNDNEAR;
107  }
108 
109  return(s);
110 }
111 
112 double DistanceToInterval(double p,Tinterval *i)
113 {
114  double d=0;
115 
116  if (p<i->lower_limit)
117  d=i->lower_limit-p;
118  else
119  {
120  if (p>i->upper_limit)
121  d=p-i->upper_limit;
122  }
123  return(d);
124 }
125 
126 /*
127  * Returns the center of the interval
128  */
130 {
131  double c;
132 
133  if (i->upper_limit==i->lower_limit)
134  c=i->upper_limit;
135  else
136  {
137  if (IS_INF(i->lower_limit)&&(IS_INF(i->upper_limit)))
138  c=0.0;
139  else
140  {
141  if (IS_INF(i->lower_limit))
142  c=i->upper_limit;
143  else
144  {
145  if (IS_INF(i->upper_limit))
146  c=i->lower_limit;
147  else
148  {
149  c=(i->upper_limit+i->lower_limit)/2.0;
150 
151  /* Conditions below can occur because of roundings */
152  if (c<i->lower_limit) c=i->lower_limit;
153  if (c>i->upper_limit) c=i->upper_limit;
154  }
155  }
156  }
157  }
158  return(c);
159 }
160 
161 /*
162  * Returns the point in the interval by linear interpolation between the extremes.
163  */
164 double PointInInterval(double r,Tinterval *i)
165 {
166  double p;
167 
168  if (i->upper_limit==i->lower_limit)
169  p=i->upper_limit;
170  else
171  {
172  if (IS_INF(i->lower_limit)&&(IS_INF(i->upper_limit)))
173  p=0.0;
174  else
175  {
176  if (IS_INF(i->lower_limit))
177  p=i->upper_limit-1;
178  else
179  {
180  if (IS_INF(i->upper_limit))
181  p=i->lower_limit+1;
182  else
183  {
184  p=i->lower_limit+(i->upper_limit-i->lower_limit)*(r<0?0:(r>1?1:r));
185 
186  /* Conditions below can occur because of roundings */
187  if (p<i->lower_limit) p=i->lower_limit;
188  if (p>i->upper_limit) p=i->upper_limit;
189  }
190  }
191  }
192  }
193  return(p);
194 }
195 
196 void SetLowerLimit(double v,Tinterval *i)
197 {
198  i->lower_limit=INF_CUT(v);
199 }
200 
201 void SetUpperLimit(double v,Tinterval *i)
202 {
203  i->upper_limit=INF_CUT(v);
204 }
205 
206 void EnlargeInterval(double lo,double uo,Tinterval *i)
207 {
208  double v;
209 
210  if (IS_NOT_INF(i->lower_limit))
211  {
212  if (IS_INF(lo))
213  i->lower_limit=lo;
214  else
215  {
216  ROUNDDOWN;
217  v=i->lower_limit+lo;
218  i->lower_limit=INF_CUT(v);
219  }
220  }
221 
222  if (IS_NOT_INF(i->upper_limit))
223  {
224  if (IS_INF(uo))
225  i->upper_limit=uo;
226  else
227  {
228  ROUNDUP;
229  v=i->upper_limit+uo;
230  i->upper_limit=INF_CUT(v);
231  }
232  }
233  ROUNDNEAR;
234 }
235 
236 void ExpandInterval(double v,Tinterval *i)
237 {
238  if (v<i->lower_limit)
239  i->lower_limit=INF_CUT(v);
240  else
241  {
242  if (v>i->upper_limit)
243  i->upper_limit=INF_CUT(v);
244  }
245 }
246 
247 void UpdateLowerLimit(double v,Tinterval *i)
248 {
249  if (v>i->lower_limit)
250  i->lower_limit=INF_CUT(v);
251 }
252 
253 void UpdateUpperLimit(double v,Tinterval *i)
254 {
255  if (v<i->upper_limit)
256  i->upper_limit=INF_CUT(v);
257 }
258 
259 /*
260  * Returns TRUE if i1 is fully included in i2
261  */
263 {
264  return((i2->lower_limit<i1->lower_limit)&&(i1->upper_limit<i2->upper_limit));
265 }
266 
267 /*
268  * Returns TRUE if intervals 'i1' and 'i2' actually intersect.
269  * NOTE: This rutine is only valid for intervals where lower_limit<upper_limit
270  * and thus it fails in the intersection between certain rotational intervals.
271  */
272 boolean Intersect(Tinterval *i1,Tinterval *i2)
273 {
274  Tinterval i3;
275 
276  return(Intersection(i1,i2,&i3));
277 }
278 
279 /*
280  * Returns in 'i_out' the intersection of intervals 'i1' and 'i2'.
281  * NOTE: This rutine is only valid for intervals where lower_limit<upper_limit
282  * and thus it can fail for intersection between certain rotational intervals.
283  * RETURNS true if the intersection is NOT EMPTY
284  */
285 boolean Intersection(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
286 {
287  i_out->lower_limit=(i1->lower_limit>i2->lower_limit?i1->lower_limit:i2->lower_limit);
288  i_out->upper_limit=(i1->upper_limit<i2->upper_limit?i1->upper_limit:i2->upper_limit);
289 
290  return(i_out->lower_limit<=i_out->upper_limit);
291 }
292 
293 /*
294  * Returns in i_out the union of i1 and i2
295  * Returns false if the the input intervals are empty
296 */
297 boolean Union(Tinterval *i1,Tinterval *i2,Tinterval *i_out)
298 {
299  boolean full;
300 
301  full=TRUE;
302 
303  if (i1->lower_limit>i1->upper_limit) /*i1 empty*/
304  {
305  if (i2->lower_limit>i2->upper_limit)/*i2 empty*/
306  full=FALSE;
307  else
308  {
309  i_out->lower_limit=i2->lower_limit;
310  i_out->upper_limit=i2->upper_limit;
311  }
312  }
313  else
314  {
315  if (i2->lower_limit>i2->upper_limit) /*i2 empty*/
316  {
317  i_out->lower_limit=i1->lower_limit;
318  i_out->upper_limit=i1->upper_limit;
319  }
320  else
321  {
322  i_out->lower_limit=(i1->lower_limit<i2->lower_limit?i1->lower_limit:i2->lower_limit);
323  i_out->upper_limit=(i1->upper_limit>i2->upper_limit?i1->upper_limit:i2->upper_limit);
324  }
325  }
326  return(full);
327 }
328 
329 
330 /*
331  * Returns TRUE if interval 'i' is empty
332  * NOTE: This rutine is only valid for intervals where lower_limit<upper_limit
333  * and thus it can return wrong results for certain rotational intervals.
334  */
336 {
337  return(i->lower_limit>i->upper_limit);
338 }
339 
340 /*
341  * returns true if p is inside the interval i
342  */
343 boolean IsInside(double p,double tol,Tinterval *i)
344 {
345  double v;
346 
347  v=INF_CUT(p);
348  return((v>=(i->lower_limit-tol))&&(v<=(i->upper_limit+tol)));
349 }
350 
351 /*
352  * Products and interval and a scalar
353  * Be carefull i_out can be i1 or i2!!!!!
354  */
355 void IntervalScale(Tinterval *i1,double e,Tinterval *i_out)
356 {
357  double e1,e2;
358 
359  if (e>0)
360  {
361  ROUNDDOWN;
362  e1=INF_SCALE(e,i1->lower_limit);
363  ROUNDUP;
364  e2=INF_SCALE(e,i1->upper_limit);
365  }
366  else
367  {
368  /*The sign is changed: extremes are swap */
369  ROUNDDOWN;
370  e1=INF_SCALE(e,i1->upper_limit);
371  ROUNDUP;
372  e2=INF_SCALE(e,i1->lower_limit);
373  }
374  ROUNDNEAR;
375 
376  i_out->lower_limit=INF_CUT(e1);
377  i_out->upper_limit=INF_CUT(e2);
378 }
379 
380 /*
381  * Product of two intervals
382  * Be carefull i_out can be i1 or i2!!!!!
383  */
385 {
386  double e[3];
387  unsigned int i;
388  double a,b;
389 
390  ROUNDDOWN;
391  e[0]=INF_PROD(i1->lower_limit,i2->upper_limit,TRUE);
392  e[1]=INF_PROD(i1->upper_limit,i2->lower_limit,TRUE);
393  e[2]=INF_PROD(i1->upper_limit,i2->upper_limit,TRUE);
394 
396  for(i=0;i<3;i++)
397  if (e[i]<a) a=e[i];
398 
399  ROUNDUP;
400  e[0]=INF_PROD(i1->lower_limit,i2->upper_limit,FALSE);
401  e[1]=INF_PROD(i1->upper_limit,i2->lower_limit,FALSE);
402  e[2]=INF_PROD(i1->upper_limit,i2->upper_limit,FALSE);
403 
405  for(i=0;i<3;i++)
406  if (e[i]>b) b=e[i];
407 
408  ROUNDNEAR;
409 
410  i_out->lower_limit=INF_CUT(a);
411  i_out->upper_limit=INF_CUT(b);
412 }
413 
414 /*
415  * Additon of two intervals
416  * Be carefull i_out can be i1 or i2!!!!!
417  */
419 {
420  double a,b;
421 
422  ROUNDDOWN;
423  a=INF_ADD(i1->lower_limit,i2->lower_limit,TRUE);
424 
425  ROUNDUP;
427 
428  ROUNDNEAR;
429 
430  i_out->lower_limit=INF_CUT(a);
431  i_out->upper_limit=INF_CUT(b);
432 }
433 
434 /*
435  * i_out=i1-i2;
436  */
438 {
439  double a,b;
440 
441  ROUNDDOWN;
443 
444  ROUNDUP;
446 
447  ROUNDNEAR;
448 
449  i_out->lower_limit=INF_CUT(a);
450  i_out->upper_limit=INF_CUT(b);
451 }
452 
453 /*
454  * Changes the sign of a given interval
455  */
457 {
458  double a,b;
459 
460  a=-i->upper_limit;
461  b=-i->lower_limit;
462 
463  i_out->lower_limit=a;
464  i_out->upper_limit=b;
465 }
466 
467 /*
468  * i_out=exo(i)
469  */
471 {
472  double a,b;
473 
474  ROUNDDOWN;
475  a=INF_EXP(i->lower_limit);
476 
477  ROUNDUP;
478  b=INF_EXP(i->upper_limit);
479 
480  ROUNDNEAR;
481 
482  i_out->lower_limit=INF_CUT(a);
483  i_out->upper_limit=INF_CUT(b);
484 }
485 
486 /*
487  * i_out=i^p
488  */
489 void IntervalPow(Tinterval *i,unsigned int p,Tinterval *i_out)
490 {
491  double a,b,e1,e2;
492 
493  ROUNDDOWN;
494  e1=INF_POW(i->lower_limit,p);
495  e2=INF_POW(i->upper_limit,p);
496 
497  if (e1<e2)
498  a=e1;
499  else
500  a=e2;
501 
502  ROUNDUP;
503  e1=INF_POW(i->lower_limit,p);
504  e2=INF_POW(i->upper_limit,p);
505 
506  if (e1>e2)
507  b=e1;
508  else
509  b=e2;
510 
511  ROUNDNEAR;
512 
513  if (((p%2)==0)&&(IsInside(0,0,i)))
514  a=0; /*x^p with p=2*n always have a minimum at 0 (if included in the input interval)*/
515 
516  i_out->lower_limit=INF_CUT(a);
517  i_out->upper_limit=INF_CUT(b);
518 }
519 
520 
521 
522 /*
523  * Square root
524  */
525 boolean IntervalSqrt(Tinterval *i,Tinterval *i_out)
526 {
527  double a,b;
528 
529  if (i->upper_limit<0.0)
530  return(FALSE);
531  else
532  {
533  ROUNDDOWN;
534  a=INF_SQRT(i->lower_limit);
535 
536  ROUNDUP;
537  b=INF_SQRT(i->upper_limit);
538 
539  ROUNDNEAR;
540 
541  i_out->lower_limit=INF_CUT(a);
542  i_out->upper_limit=INF_CUT(b);
543 
544  return(TRUE);
545  }
546 }
547 
548 /*
549  * i_out = i1/i2
550  */
552 {
553  double a,b;
554 
555  if (IsInside(0,0,i2))
556  {
557  if ((i2->lower_limit==0.0)&&(i2->upper_limit>0.0))
558  {
559  ROUNDDOWN;
560  a=i1->lower_limit/i2->upper_limit;
561  b=i1->upper_limit/i2->upper_limit;
562  a=(a<b?a:b);
563  ROUNDNEAR;
564  i_out->lower_limit=INF_CUT(a);
565 
566  i_out->upper_limit=+INF;
567  }
568  else
569  {
570  if ((i2->lower_limit<0.0)&&(i2->upper_limit==0.0))
571  {
572  i_out->lower_limit=-INF;
573 
574  ROUNDUP;
575  a=i1->lower_limit/i2->lower_limit;
576  b=i1->upper_limit/i2->lower_limit;
577  b=(b>a?b:a);
578  ROUNDNEAR;
579  i_out->upper_limit=INF_CUT(b);
580 
581  }
582  else
583  {
584  i_out->lower_limit=-INF;
585  i_out->upper_limit=+INF;
586  }
587  }
588  }
589  else
590  {
591  double e[3];
592  unsigned int i;
593 
594  ROUNDDOWN;
595  e[0]=i1->lower_limit/i2->upper_limit;
596  e[1]=i1->upper_limit/i2->lower_limit;
597  e[2]=i1->upper_limit/i2->upper_limit;
598 
599  a=i1->lower_limit/i2->lower_limit;
600  for(i=0;i<3;i++)
601  if (e[i]<a) a=e[i];
602 
603  ROUNDUP;
604  e[0]=i1->lower_limit/i2->upper_limit;
605  e[1]=i1->upper_limit/i2->lower_limit;
606  e[2]=i1->upper_limit/i2->upper_limit;
607 
608  b=i1->lower_limit/i2->lower_limit;
609  for(i=0;i<3;i++)
610  if (e[i]>b) b=e[i];
611 
612  ROUNDNEAR;
613 
614  i_out->lower_limit=INF_CUT(a);
615  i_out->upper_limit=INF_CUT(b);
616  }
617 }
618 
619 /*
620  * Shifts a interval
621 */
622 void IntervalOffset(Tinterval *i,double offset,Tinterval *i_out)
623 {
624  double a,b;
625 
626  ROUNDDOWN;
627  a=INF_ADD(i->lower_limit,offset,TRUE);
628 
629  ROUNDUP;
630  b=INF_ADD(i->upper_limit,offset,FALSE);
631 
632  ROUNDNEAR;
633 
634  i_out->lower_limit=INF_CUT(a);
635  i_out->upper_limit=INF_CUT(b);
636 }
637 
638 
639 /*
640  * Computes the sinus of an interval
641  */
643 {
644  double l,u;
645 
646  if (IntervalSize(i)>=M_2PI)
647  NewInterval(-1,1,i_out);
648  else
649  {
652 
653  if (u<l)
654  {
655  Tinterval i_in;
656  Tinterval i_out1,i_out2;
657 
658  i_in.lower_limit=l;
659  i_in.upper_limit=M_2PI;
660 
661  IntervalSine(&i_in,&i_out1);
662 
663  i_in.lower_limit=0.0;
664  i_in.upper_limit=u;
665 
666  IntervalSine(&i_in,&i_out2);
667 
668  i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
669  i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
670  }
671  else
672  {
673  double a,b;
674 
675  a=sin(l);
676  b=sin(u);
677 
678  if ((l<=M_PI_2)&&(M_PI_2<=u))
679  i_out->upper_limit=1.0;
680  else
681  /* We +/- 1e-6 to compensate for possible errors
682  introduced by the NormalizeAngle and the
683  computation of trigonometric functions. */
684  i_out->upper_limit=(a>b?a:b)+1e-6;
685 
686  if ((l<=(3.0*M_PI_2))&&((3.0*M_PI_2)<=u))
687  i_out->lower_limit=-1.0;
688  else
689  i_out->lower_limit=(a<b?a:b)-1e-6;
690  }
691  }
692 }
693 
694 /*
695  * Computes the cosinus of an interval
696  */
698 {
699  double l,u;
700 
701  if (IntervalSize(i)>=M_2PI)
702  NewInterval(-1,1,i_out);
703  else
704  {
707 
708  if (u<l)
709  {
710  Tinterval i_in;
711  Tinterval i_out1,i_out2;
712 
713  i_in.lower_limit=l;
714  i_in.upper_limit=M_2PI;
715 
716  IntervalCosine(&i_in,&i_out1);
717 
718  i_in.lower_limit=0.0;
719  i_in.upper_limit=u;
720 
721  IntervalCosine(&i_in,&i_out2);
722 
723  i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
724  i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
725  }
726  else
727  {
728  double a,b;
729 
730  a=cos(l);
731  b=cos(u);
732 
733  if ((l<=0.0)&&(0.0<=u))
734  i_out->upper_limit=1.0;
735  else
736  /* We +/- 1e-6 to compensate for possible errors
737  introduced by the NormalizeAngle and the
738  computation of trigonometric functions. */
739  i_out->upper_limit=(a>b?a:b)+1e-6;
740 
741  if ((l<=M_PI)&&(M_PI<=u))
742  i_out->lower_limit=-1.0;
743  else
744  i_out->lower_limit=(a<b?a:b)-1e-6;
745  }
746  }
747 }
748 
750 {
751  double l,u;
752 
753  if (IntervalSize(i)>=M_2PI)
754  NewInterval(-INF,INF,i_out);
755  else
756  {
759 
760  if (u<l)
761  {
762  Tinterval i_in;
763  Tinterval i_out1,i_out2;
764 
765  i_in.lower_limit=l;
766  i_in.upper_limit=M_2PI;
767 
768  IntervalTangent(&i_in,&i_out1);
769 
770  i_in.lower_limit=0.0;
771  i_in.upper_limit=u;
772 
773  IntervalTangent(&i_in,&i_out2);
774 
775  i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
776  i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
777  }
778  else
779  {
780  if (((l<=M_PI_2)&&(M_PI_2<=u))||((l<=3*M_PI_2)&&(3*M_PI_2<=u)))
781  {
782  /* If the range includes one of the singular points, check
783  if the range is upper/lower bounded by the singularity */
784  if (u==M_PI_2)
785  {
786  i_out->lower_limit=tan(l)-1e-6;
787  i_out->upper_limit=+INF;
788  }
789  else
790  {
791  if (l==3*M_PI_2)
792  {
793  i_out->lower_limit=-INF;
794  i_out->upper_limit=tan(u)+1e-6;
795  }
796  else
797  {
798  if (l==M_PI_2)
799  {
800  if (u==3*M_PI_2)
801  {
802  i_out->lower_limit=-INF;
803  i_out->upper_limit=+INF;
804  }
805  else
806  {
807  i_out->lower_limit=-INF;
808  i_out->upper_limit=tan(u)+1e-6;
809  }
810  }
811  else
812  {
813  if (u==3*M_PI_2)
814  {
815  i_out->lower_limit=tan(l)-1e-6;
816  i_out->upper_limit=+INF;
817  }
818  else
819  {
820  i_out->lower_limit=-INF;
821  i_out->upper_limit=+INF;
822  }
823  }
824  }
825  }
826  }
827  else
828  {
829  double a,b;
830 
831  a=tan(l);
832  b=tan(u);
833 
834  i_out->lower_limit=(a<b?a:b)-1e-6;
835  i_out->upper_limit=(a>b?a:b)+1e-6;
836  }
837  }
838  }
839 }
840 
842 {
843  Tinterval c,one;
844 
845  NewInterval(1,1,&one);
846  IntervalCosine(i,&c);
847  IntervalPow(&c,2,&c);
848  IntervalDivision(&one,&c,i_out);
849 }
850 
852 {
853  double l,u;
854 
855  if (IntervalSize(i)>=M_2PI)
856  NewInterval(-INF,INF,i_out);
857  else
858  {
861 
862  if (u<l)
863  {
864  Tinterval i_in;
865  Tinterval i_out1,i_out2;
866 
867  i_in.lower_limit=l;
868  i_in.upper_limit=M_2PI;
869 
870  IntervalTangent(&i_in,&i_out1);
871 
872  i_in.lower_limit=0.0;
873  i_in.upper_limit=u;
874 
875  IntervalTangent(&i_in,&i_out2);
876 
877  i_out->lower_limit=(i_out1.lower_limit<i_out2.lower_limit?i_out1.lower_limit:i_out2.lower_limit);
878  i_out->upper_limit=(i_out1.upper_limit>i_out2.upper_limit?i_out1.upper_limit:i_out2.upper_limit);
879  }
880  else
881  {
882  double c;
883 
884  if (((l<=M_PI_2)&&(M_PI_2<=u))||((l<=3*M_PI_2)&&(3*M_PI_2<=u)))
885  {
886  /* If the range includes one of the singular points, check
887  if the range is upper/lower bounded by the singularity */
888  if (u==M_PI_2)
889  {
890  c=cos(l);
891  i_out->lower_limit=tan(l)/(c*c)-1e-6;
892  i_out->upper_limit=+INF;
893  }
894  else
895  {
896  if (l==3*M_PI_2)
897  {
898  c=cos(u);
899  i_out->lower_limit=-INF;
900  i_out->upper_limit=tan(u)/(c*c)+1e-6;
901  }
902  else
903  {
904  if (l==M_PI_2)
905  {
906  if (u==3*M_PI_2)
907  {
908  i_out->lower_limit=-INF;
909  i_out->upper_limit=+INF;
910  }
911  else
912  {
913  c=cos(u);
914  i_out->lower_limit=-INF;
915  i_out->upper_limit=tan(u)/(c*c)+1e-6;
916  }
917  }
918  else
919  {
920  if (u==3*M_PI_2)
921  {
922  c=cos(l);
923  i_out->lower_limit=tan(l)/(c*c)-1e-6;
924  i_out->upper_limit=+INF;
925  }
926  else
927  {
928  i_out->lower_limit=-INF;
929  i_out->upper_limit=+INF;
930  }
931  }
932  }
933  }
934  }
935  else
936  {
937  double a,b;
938 
939  c=cos(l);
940  a=tan(l)/(c*c);
941 
942  c=cos(u);
943  b=tan(u)/(c*c);
944 
945  i_out->lower_limit=(a<b?a:b)-1e-6;
946  i_out->upper_limit=(a>b?a:b)+1e-6;
947  }
948  }
949  }
950 }
951 
953 {
954  double a[4];
955  unsigned int i;
956  double t1,t2;
957 
958  if ((IntervalSize(is)>0.5)||(IntervalSize(ic)>0.5))
959  Error ("Interval atan2 only works for small intervals");
960 
961  a[0]=atan2(is->lower_limit,ic->lower_limit);
962  a[1]=atan2(is->lower_limit,ic->upper_limit);
963  a[2]=atan2(is->upper_limit,ic->lower_limit);
964  a[3]=atan2(is->upper_limit,ic->upper_limit);
965 
966  t1=t2=a[0];
967  for(i=1;i<4;i++)
968  {
969  if (a[i]<t1) t1=a[i];
970  else {if (a[i]>t2) t2=a[i];}
971  }
972 
973  i_out->lower_limit=t1;
974  i_out->upper_limit=t2;
975 
976  if ((i_out->upper_limit-i_out->lower_limit)>M_PI)
977  {
978  double d;
979 
980  d=i_out->lower_limit;
981  i_out->lower_limit=i_out->upper_limit;
982  i_out->upper_limit=d+M_2PI;
983  }
984 }
985 
987 {
988  if (EmptyInterval(i))
989  fprintf(f,"(Empty Interval)");
990 
991  fprintf(f,"[");
993  fprintf(f,",");
995  fprintf(f,"]");
996 }
997 
998 /*
999  * Prints the contents of interval 'i' on file 'f'.
1000  */
1001 void PrintInterval(FILE *f,Tinterval *i)
1002 {
1003  if (EmptyInterval(i))
1004  fprintf(f,"(Empty Interval)");
1005 
1006  fprintf(f,"[");
1007  INF_PRINT(f,i->lower_limit);
1008  fprintf(f,",");
1009  INF_PRINT(f,i->upper_limit);
1010  fprintf(f,"]");
1011 }
1012 
1013 /*
1014  * Deletes the internal structures of interval 'i'.
1015  */
1017 {
1018 }
void UpdateLowerLimit(double v, Tinterval *i)
Updates the lower limit.
Definition: interval.c:247
boolean Intersect(Tinterval *i1, Tinterval *i2)
Checks is a two intervals intersect.
Definition: interval.c:272
Definition of basic functions.
void EnlargeInterval(double lo, double uo, Tinterval *i)
Symmetrically increases the size of an interval.
Definition: interval.c:206
#define FALSE
FALSE.
Definition: boolean.h:30
#define INF_SQRT(a)
Sqrt of a number, possibly +/-inf.
Definition: defines.h:334
double IntervalCenter(Tinterval *i)
Gets the interval center.
Definition: interval.c:129
void CopyInterval(Tinterval *i_dst, Tinterval *i_org)
Copy constructor.
Definition: interval.c:59
void SetUpperLimit(double v, Tinterval *i)
Sets a new upper limit.
Definition: interval.c:201
boolean IntervalInclusion(Tinterval *i1, Tinterval *i2)
Checks is a given interval is fully included into another interval.
Definition: interval.c:262
#define ROUNDDOWN
Sets the floating point operations in rounding down mode.
Definition: defines.h:219
#define INF_PRINT(f, a)
Prints a number (possibly +/-inf) to a file.
Definition: defines.h:344
void IntervalSecant2(Tinterval *i, Tinterval *i_out)
Interval squared secant.
Definition: interval.c:841
boolean CmpIntervals(Tinterval *i1, Tinterval *i2)
Compares two intervals.
Definition: interval.c:70
boolean IntervalSqrt(Tinterval *i, Tinterval *i_out)
Interval square root.
Definition: interval.c:525
boolean Union(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Computes the union of two intervals.
Definition: interval.c:297
#define TRUE
TRUE.
Definition: boolean.h:21
void SetLowerLimit(double v, Tinterval *i)
Sets a new lower limit.
Definition: interval.c:196
void Error(const char *s)
General error function.
Definition: error.c:80
double LowerLimit(Tinterval *i)
Gets the lower limit.
Definition: interval.c:79
#define IS_INF(a)
Identifies +/-inf.
Definition: defines.h:246
boolean EmptyInterval(Tinterval *i)
Checks if a given interval is empty.
Definition: interval.c:335
void ExpandInterval(double v, Tinterval *i)
Changes the interval limits to include a given point.
Definition: interval.c:236
boolean IsInside(double p, double tol, Tinterval *i)
Checks if a value is inside an interval.
Definition: interval.c:343
Error and warning functions.
#define INF_SCALE(s, a)
Scales a number, possibly inf or -inf.
Definition: defines.h:267
#define INF_PROD(a, b, d)
Product of two numbers, possibly inf or -inf.
Definition: defines.h:289
#define SYMBOL_PRINT(f, a)
Prints a number (possibly +/-PI, +/-PI/2, or +/-inf) to a file.
Definition: defines.h:376
void PrintSymbolInterval(FILE *f, Tinterval *i)
Prints an angular interval.
Definition: interval.c:986
Definitions of constants and macros used in several parts of the cuik library.
#define M_PI_2
Pi/2.
Definition: defines.h:92
double NormalizeAngle(double a)
Normalizes a angular value so that it is included in [0,2Pi].
Definition: interval.c:31
void IntervalTangent(Tinterval *i, Tinterval *i_out)
Interval tangent.
Definition: interval.c:749
void IntervalSecant2Tangent(Tinterval *i, Tinterval *i_out)
Interval squared secant per tangent.
Definition: interval.c:851
#define ROUNDNEAR
Sets the floating point operations in round near mode.
Definition: defines.h:225
#define INF_SUBS(a, b, d)
Substract two numbers, possibly inf or -inf.
Definition: defines.h:315
void IntervalOffset(Tinterval *i, double offset, Tinterval *i_out)
Interval offset.
Definition: interval.c:622
#define INF_ADD(a, b, d)
Adds two numbers, possibly inf or -inf.
Definition: defines.h:302
void IntervalAtan2(Tinterval *is, Tinterval *ic, Tinterval *i_out)
Interval atan2.
Definition: interval.c:952
#define INF_EXP(a)
Exponentional of a number, possibly inf or -inf.
Definition: defines.h:276
boolean Intersection(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Computes the intersection of two intervals.
Definition: interval.c:285
#define M_2PI
2*Pi.
Definition: defines.h:100
#define M_PI
Pi.
Definition: defines.h:83
void IntervalSubstract(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Substraction of two intervals.
Definition: interval.c:437
#define IS_NOT_INF(a)
Identifies not +/-inf.
Definition: defines.h:255
void IntervalScale(Tinterval *i1, double e, Tinterval *i_out)
Scales an interval.
Definition: interval.c:355
void IntervalProduct(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Product of two intervals.
Definition: interval.c:384
void IntervalInvert(Tinterval *i, Tinterval *i_out)
Change of sign of a given interval.
Definition: interval.c:456
void NewInterval(double lower, double upper, Tinterval *i)
Constructor.
Definition: interval.c:47
#define ROUNDUP
Sets the floating point operations in rounding up mode.
Definition: defines.h:213
double upper_limit
Definition: interval.h:36
void IntervalPow(Tinterval *i, unsigned int p, Tinterval *i_out)
Power of a given interval by a integer power factor.
Definition: interval.c:489
double lower_limit
Definition: interval.h:35
#define INF_CUT(a)
Sets a number, without going beyond +/-inf.
Definition: defines.h:237
#define INF
Infinite.
Definition: defines.h:70
double UpperLimit(Tinterval *i)
Gets the uppser limit.
Definition: interval.c:87
double PointInInterval(double r, Tinterval *i)
Gets a point inside the interval.
Definition: interval.c:164
void IntervalSine(Tinterval *i, Tinterval *i_out)
Interval sine.
Definition: interval.c:642
void IntervalExp(Tinterval *i, Tinterval *i_out)
Exponentional of an interval.
Definition: interval.c:470
void IntervalDivision(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Interval division.
Definition: interval.c:551
Defines a interval.
Definition: interval.h:33
void PrintInterval(FILE *f, Tinterval *i)
Prints an interval.
Definition: interval.c:1001
void UpdateUpperLimit(double v, Tinterval *i)
Updates the upper limit.
Definition: interval.c:253
double DistanceToInterval(double p, Tinterval *i)
Distance to an interval.
Definition: interval.c:112
#define INF_POW(a, p)
Power of a number, possibly +/-inf.
Definition: defines.h:325
void DeleteInterval(Tinterval *i)
Destructor.
Definition: interval.c:1016
double IntervalSize(Tinterval *i)
Gets the uppser limit.
Definition: interval.c:96
void IntervalAdd(Tinterval *i1, Tinterval *i2, Tinterval *i_out)
Addition of two intervals.
Definition: interval.c:418
void IntervalCosine(Tinterval *i, Tinterval *i_out)
Interval cosine.
Definition: interval.c:697
Definition of the Tinterval type and the associated functions.