codac 2.0.0
Loading...
Searching...
No Matches
codac2_atan.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "codac2_Interval.h"
13#include "codac2_AnalyticType.h"
15
16namespace codac2
17{
18 struct AtanOp
19 {
20 template<typename X1>
21 static std::string str(const X1& x1)
22 {
23 return "atan(" + x1->str() + ")";
24 }
25
26 template<typename X1>
27 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1)
28 {
29 return {1,1};
30 }
31
32 static Interval fwd(const Interval& x1);
33 static ScalarType fwd_natural(const ScalarType& x1);
34 static ScalarType fwd_centered(const ScalarType& x1);
35 static void bwd(const Interval& y, Interval& x1);
36 };
37
38 // Analytic operator
39 // The following function can be used to build analytic expressions.
40
41 inline ScalarExpr
42 atan(const ScalarExpr& x1)
43 {
44 return { std::make_shared<AnalyticOperationExpr<AtanOp,ScalarType,ScalarType>>(x1) };
45 }
46
47 // Inline functions
48
49 inline Interval AtanOp::fwd(const Interval& x1)
50 {
51 return atan(x1);
52 }
53
54 inline ScalarType AtanOp::fwd_natural(const ScalarType& x1)
55 {
56 return {
57 fwd(x1.a),
58 x1.def_domain
59 };
60 }
61
62 inline ScalarType AtanOp::fwd_centered(const ScalarType& x1)
63 {
64 if(centered_form_not_available_for_args(x1))
65 return fwd_natural(x1);
66
67 IntervalMatrix d(1,x1.da.size());
68 for(Index i = 0 ; i < d.size() ; i++)
69 d(0,i) = x1.da(0,i)/(1.+sqr(x1.a));
70
71 return {
72 fwd(x1.m),
73 fwd(x1.a),
74 d,
75 x1.def_domain
76 };
77 }
78
79 inline void AtanOp::bwd(const Interval& y, Interval& x1)
80 {
81 // The content of this function comes from the IBEX library.
82 // See ibex::Interval (IBEX lib, main author: Gilles Chabert)
83 // https://ibex-lib.readthedocs.io
84
85 if(y.is_empty())
86 x1.set_empty();
87
88 else
89 {
90 // Note: if y.ub>pi/2 or y.lb<-pi/2, tan(y) gives (-oo,oo).
91 // so the implementation is not as simple as x1 &= tan(y).
92
93 Interval z = y;
94 double pi2l = (Interval::pi()/2).lb();
95 double pi2u = (Interval::pi()/2).ub();
96
97 if(z.ub() >= pi2l) // not pi2u. See comments below.
98 {
99 if(z.lb() >= pi2u)
100 x1.set_empty();
101
102 else
103 {
104 if(z.lb() > -pi2l)
105 {
106 // Note 1: tan(z^-) can give an interval (-oo,+oo) if
107 // z^- is close to -pi/2. Even in this case we keep the
108 // lower bound -oo.
109 //
110 // Note 2: if we had used z.lb()<-pi2u (with pi2u>pi/2)
111 // instead of z.lb()<-pi2l, it may be possible, in theory,
112 // that the calculated lower bound is a high value close to +oo, which would be incorrect.
113 //
114 // Note 3: if z.lb() is close to pi/2, the lower bound of tan(z.lb()) can be -oo. There
115 // is nothing we can do about it (the lower bound cannot be evaluated in this case)
116 //
117 // Note 4: tan(z.lb()) cannot be an empty set since z.lb() cannot be exactly pi/2.
118 x1 &= Interval(tan(Interval(z.lb())).lb(),oo);
119 }
120
121 // else do nothing
122 }
123 }
124
125 else
126 {
127 if(z.ub() <= -pi2u)
128 x1.set_empty();
129
130 else if(z.lb() < -pi2l)
131 // Same comments as above
132 x1 &= Interval(-oo,tan(Interval(z.ub())).ub());
133
134 else
135 x1 &= Interval(tan(Interval(z.lb())).lb(), tan(Interval(z.ub())).ub());
136 }
137 }
138 }
139}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62
double ub() const
Returns the upper bound of this.
Definition codac2_Interval_impl.h:107
static Interval pi()
Provides an interval for .
Definition codac2_Interval_impl.h:555
double lb() const
Returns the lower bound of this.
Definition codac2_Interval_impl.h:102
Interval atan(const Interval &x)
Returns .
Definition codac2_Interval_operations_impl.h:133
Interval sqr(const Interval &x)
Returns .
Definition codac2_Interval_operations_impl.h:21
Interval tan(const Interval &x)
Returns .
Definition codac2_Interval_operations_impl.h:112