codac 2.0.0
Loading...
Searching...
No Matches
codac2_atan2.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#include "codac2_atan2.h"
16#include "codac2_arith_div.h"
17
18namespace codac2
19{
20 struct Atan2Op
21 {
22 template<typename X1,typename X2>
23 static std::string str(const X1& x1, const X2& x2)
24 {
25 return "atan2(" + x1->str() + "," + x2->str() + ")";
26 }
27
28 template<typename X1, typename X2>
29 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1, [[maybe_unused]] const X2& s2)
30 {
31 return {1,1};
32 }
33
34 static Interval fwd(const Interval& x1, const Interval& x2);
35 static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2);
36 static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2);
37 static void bwd(const Interval& y, Interval& x1, Interval& x2);
38 };
39
40 // Analytic operator
41 // The following function can be used to build analytic expressions.
42
43 inline ScalarExpr
44 atan2(const ScalarExpr& x1, const ScalarExpr& x2)
45 {
46 return { std::make_shared<AnalyticOperationExpr<Atan2Op,ScalarType,ScalarType,ScalarType>>(x1,x2) };
47 }
48
49 // Inline functions
50
51 inline Interval Atan2Op::fwd(const Interval& x1, const Interval& x2)
52 {
53 return atan2(x1,x2);
54 }
55
56 inline ScalarType Atan2Op::fwd_natural(const ScalarType& x1, const ScalarType& x2)
57 {
58 return {
59 fwd(x1.a, x2.a),
60 x1.def_domain && x2.def_domain
61 && !(x1.a == 0. && x2.a == 0.) // def domain of the derivative of atan2
62 };
63 }
64
65 inline ScalarType Atan2Op::fwd_centered(const ScalarType& x1, const ScalarType& x2)
66 {
67 if(centered_form_not_available_for_args(x1,x2))
68 return fwd_natural(x1,x2);
69
70 assert(x1.da.rows() == 1);
71 assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols());
72
73 IntervalMatrix d(1,x1.da.cols());
74 for(Index i = 0 ; i < d.size() ; i++)
75 d(0,i) = (-x1.a*x2.da(0,i)/(sqr(x2.a)+sqr(x1.a)))+(x2.a*x1.da(0,i)/(sqr(x2.a)+sqr(x1.a)));
76
77 return {
78 fwd(x1.m, x2.m),
79 fwd(x1.a, x2.a),
80 d,
81 x1.def_domain && x2.def_domain
82 && !(x1.a == 0. && x2.a == 0.) // def domain of the derivative of atan2
83 };
84 }
85
86 inline void Atan2Op::bwd(const Interval& y, Interval& x1, Interval& x2)
87 {
88 // The content of this function comes from the IBEX library.
89 // See ibex::Interval (IBEX lib, main author: Gilles Chabert)
90 // https://ibex-lib.readthedocs.io
91
92 // Probably not the most efficient implementation ever...
93
94 // half-plane x2>0
95 Interval y_x2pos = y & Interval(-1,1)*Interval::half_pi();
96 // upper left quadrant
97 Interval y_x2neg_x1pos = y & (Interval::half_pi() | Interval::pi());
98 // lower left quadrant
99 Interval y_x2neg_x1neg = y & -(Interval::half_pi() | Interval::pi());
100
101 Interval xres = Interval::empty();
102 Interval yres = Interval::empty();
103
104 if(!y_x2pos.is_empty())
105 {
106 Interval xpos = x2 & Interval(0,oo);
107 Interval yall = x1;
108
109 if(y_x2neg_x1pos.is_empty() || y_x2neg_x1neg.is_empty())
110 {
111 Interval z = yall/xpos;
112 AtanOp::bwd(y_x2pos,z);
113 DivOp::bwd(z,yall,xpos);
114 } // Otherwise, all is valid (useless to contract)
115
116 xres |= xpos;
117 yres |= yall;
118
119 // Because atan is not defined for pi/2 and -pi/2
120 if(y_x2pos.lb() >= Interval::half_pi().lb())
121 {
122 xres |= (x2 & Interval::zero());
123 yres |= (x1 & Interval(0,oo));
124 }
125 else if(y_x2pos.ub() <= -Interval::half_pi().lb())
126 {
127 xres |= (x2 & Interval::zero());
128 yres |= (x1 & Interval(-oo,0));
129 }
130 }
131
132 if(!y_x2neg_x1pos.is_empty())
133 {
134 Interval xneg = x2 & Interval(-oo,0);
135 Interval ypos = x1 & Interval(0,oo);
136 Interval z = ypos/xneg;
137 AtanOp::bwd(y_x2neg_x1pos - Interval::pi(),z);
138 DivOp::bwd(z,ypos,xneg);
139 xres |= xneg;
140 yres |= ypos;
141 }
142
143 if(!y_x2neg_x1neg.is_empty())
144 {
145 Interval xneg = x2 & Interval(-oo,0);
146 Interval yneg = x1 & Interval(-oo,0);
147 Interval z = yneg/xneg;
148 AtanOp::bwd(y_x2neg_x1neg + Interval::pi(),z);
149 DivOp::bwd(z,yneg,xneg);
150 xres |= xneg;
151 yres |= yneg;
152 }
153
154 x2 = xres;
155 x1 = yres;
156 }
157}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62
static Interval pi()
Provides an interval for .
Definition codac2_Interval_impl.h:555
static Interval zero()
Provides an interval for .
Definition codac2_Interval_impl.h:540
double lb() const
Returns the lower bound of this.
Definition codac2_Interval_impl.h:102
static Interval empty()
Provides an empty interval.
Definition codac2_Interval_impl.h:535
static Interval half_pi()
Provides an interval for .
Definition codac2_Interval_impl.h:550
Interval atan2(const Interval &y, const Interval &x)
Returns .
Definition codac2_Interval_operations_impl.h:140
Interval sqr(const Interval &x)
Returns .
Definition codac2_Interval_operations_impl.h:21