Generated on Tue Feb 11 2025 17:33:26 for Gecode by doxygen 1.12.0
tanatan.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Vincent Barichard <Vincent.Barichard@univ-angers.fr>
5 *
6 * Copyright:
7 * Vincent Barichard, 2012
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34namespace Gecode { namespace Float { namespace Trigonometric {
35 /*
36 * ATan projection function
37 *
38 */
39 template<class V>
40 void
41 aTanProject(Rounding& r, const V& aTanIv, FloatNum& iv_min, FloatNum& iv_max, int& n_min, int& n_max) {
42 #define I0__PI_2I FloatVal(0,pi_half_upper())
43 #define POS(X) ((I0__PI_2I.in(X))?0:1)
44 #define ATANINF_DOWN r.atan_down(aTanIv.min())
45 #define ATANSUP_UP r.atan_up(aTanIv.max())
46
47 // 0 <=> in [0;PI/2]
48 // 1 <=> in [PI/2;PI]
49 switch ( POS(iv_min) )
50 {
51 case 0:
52 if (r.tan_down(iv_min) > aTanIv.max()) { n_min++; iv_min = ATANINF_DOWN; }
53 else if (r.tan_up(iv_min) < aTanIv.min()) { iv_min = ATANINF_DOWN; }
54 break;
55 case 1:
56 if (r.tan_down(iv_min) > aTanIv.max()) { n_min+=2; iv_min = ATANINF_DOWN; }
57 else if (r.tan_up(iv_min) < aTanIv.min()) { n_min++; iv_min = ATANINF_DOWN; }
58 break;
59 default:
61 break;
62 }
63
64 // 0 <=> in [0;PI/2]
65 // 1 <=> in [PI/2;PI]
66 switch ( POS(iv_max) )
67 {
68 case 0:
69 if (r.tan_down(iv_max) > aTanIv.max()) { iv_max = ATANSUP_UP; }
70 else if (r.tan_up(iv_max) < aTanIv.min()) { n_max--; iv_max = ATANSUP_UP; }
71 break;
72 case 1:
73 if (r.tan_down(iv_max) > aTanIv.max()) { n_max++; iv_max = ATANSUP_UP; }
74 else if (r.tan_up(iv_max) < aTanIv.min()) { iv_max = ATANSUP_UP; }
75 break;
76 default:
78 break;
79 }
80 #undef ATANINF_DOWN
81 #undef ATANSUP_UP
82 #undef POS
83 #undef I0__PI_2I
84 }
85
86 /*
87 * Bounds consistent tangent operator
88 *
89 */
90
91 template<class A, class B>
93 Tan<A,B>::dopropagate(Space& home, A x0, B x1) {
94 Rounding r;
95 int n_min = static_cast<int>(r.div_up(x0.min() + pi_half_upper(), pi_upper()));
96 int n_max = static_cast<int>(r.div_up(x0.max() + pi_half_upper(), pi_upper()));
97
98 if (x0 == x1) {
99 #define I0__PI_2I FloatVal(0,pi_half_upper())
100 if (I0__PI_2I.in(x0.max())) GECODE_ME_CHECK(x0.lq(home,0));
101 if (I0__PI_2I.in(-x0.min())) GECODE_ME_CHECK(x0.gq(home,0));
102 #undef I0__PI_2I
103
104 n_min = static_cast<int>(r.div_up(x0.min(), pi_upper()));
105 n_max = static_cast<int>(r.div_up(x0.max(), pi_upper()));
106
107 FloatNum x0_min;
108 FloatNum x0_max;
109 FloatNum t = x0.min();
110 do {
111 x0_min = t;
112 if (r.tan_down(x0_min) > x0_min) n_min++;
113 t = r.add_down(r.mul_up(n_min,pi_upper()),r.tan_down(x0_min));
114 } while (t > x0_min);
115 t = r.sub_down(r.mul_up(2*n_max,pi_upper()),x0.max());
116 do {
117 x0_max = t;
118 if (r.tan_down(x0_max) < x0_max) n_max--;
119 t = r.add_up(r.mul_up(n_max,pi_upper()),r.tan_up(x0_max));
120 } while (t > x0_max);
121 x0_max = r.sub_up(r.mul_up(2*n_max,pi_upper()),x0_max);
122
123 if (x0_min > x0_max) return ES_FAILED;
124 GECODE_ME_CHECK(x0.eq(home,FloatVal(x0_min,x0_max)));
125 } else {
126 GECODE_ME_CHECK(x1.eq(home,tan(x0.val())));
127 n_min = static_cast<int>(r.div_up(x0.min(), pi_upper()));
128 n_max = static_cast<int>(r.div_up(x0.max(), pi_upper()));
129 if (x0.min() < 0) n_min--;
130 if (x0.max() < 0) n_max--;
131 FloatNum iv_min = r.sub_down(x0.min(),r.mul_down(n_min, pi_upper()));
132 FloatNum iv_max = r.sub_up (x0.max(),r.mul_down(n_max, pi_upper()));
133 aTanProject(r,x1,iv_min,iv_max,n_min,n_max);
134 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
135 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
136 if (n_iv_min > n_iv_max) return ES_FAILED;
137 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max)));
138 GECODE_ME_CHECK(x1.eq(home,tan(x0.val()))); // Redo tan because with x0 reduction, sin may be more accurate
139 }
140
141 return ES_OK;
142 }
143
144 template<class A, class B>
146 Tan<A,B>::Tan(Home home, A x0, B x1)
147 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
148
149 template<class A, class B>
151 Tan<A,B>::post(Home home, A x0, B x1) {
152 if (x0 == x1) {
153 #define I0__PI_2I FloatVal(0,pi_half_upper())
154 if (I0__PI_2I.in(x0.max())) GECODE_ME_CHECK(x0.lq(home,0));
155 if (I0__PI_2I.in(-x0.min())) GECODE_ME_CHECK(x0.gq(home,0));
156 #undef I0__PI_2I
157 }
158 GECODE_ES_CHECK(dopropagate(home,x0,x1));
159 (void) new (home) Tan<A,B>(home,x0,x1);
160 return ES_OK;
161 }
162
163 template<class A, class B>
167
168 template<class A, class B>
169 Actor*
171 return new (home) Tan<A,B>(home,*this);
172 }
173
174 template<class A, class B>
177 GECODE_ES_CHECK(dopropagate(home,x0,x1));
178 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
179 }
180
181 /*
182 * Bounds consistent arc tangent operator
183 *
184 */
185
186 template<class A, class B>
188 ATan<A,B>::ATan(Home home, A x0, B x1)
189 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
190
191 template<class A, class B>
193 ATan<A,B>::post(Home home, A x0, B x1) {
194 if (x0 == x1) {
195 GECODE_ME_CHECK(x0.eq(home,0.0));
196 } else {
197 GECODE_ME_CHECK(x1.eq(home,atan(x0.domain())));
198 GECODE_ME_CHECK(x0.eq(home,tan(x1.domain())));
199 (void) new (home) ATan<A,B>(home,x0,x1);
200 }
201 return ES_OK;
202 }
203
204
205 template<class A, class B>
209
210 template<class A, class B>
211 Actor*
213 return new (home) ATan<A,B>(home,*this);
214 }
215
216 template<class A, class B>
219 GECODE_ME_CHECK(x1.eq(home,atan(x0.domain())));
220 GECODE_ME_CHECK(x0.eq(home,tan(x1.domain())));
221 return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
222 }
223
224}}}
225
226// STATISTICS: float-prop
227
NodeType t
Type of node.
int p
Number of positive literals for node type.
Base-class for both propagators and branchers.
Definition core.hpp:628
Float value type.
Definition float.hh:334
Floating point rounding policy.
Definition float.hh:154
Propagator for bounds consistent arc tangent operator
virtual Actor * copy(Space &home)
Create copy during cloning.
Definition tanatan.hpp:212
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition tanatan.hpp:218
static ExecStatus post(Home home, A x0, B x1)
Post propagator for .
Definition tanatan.hpp:193
ATan(Space &home, ATan &p)
Constructor for cloning p.
Definition tanatan.hpp:207
Propagator for bounds consistent tangent operator
static ExecStatus post(Home home, A x0, B x1)
Post propagator for .
Definition tanatan.hpp:151
static ExecStatus dopropagate(Space &home, A x0, B x1)
Perform actual propagation.
Definition tanatan.hpp:93
virtual Actor * copy(Space &home)
Create copy during cloning.
Definition tanatan.hpp:170
Tan(Space &home, Tan &p)
Constructor for cloning p.
Definition tanatan.hpp:165
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition tanatan.hpp:176
Home class for posting propagators
Definition core.hpp:856
Mixed binary propagator.
Definition pattern.hpp:204
Computation spaces.
Definition core.hpp:1742
ExecStatus ES_SUBSUMED(Propagator &p)
Definition core.hpp:3563
int ModEventDelta
Modification event deltas.
Definition core.hpp:89
#define GECODE_ME_CHECK(me)
Check whether modification event me is failed, and forward failure.
Definition macros.hpp:52
#define GECODE_ES_CHECK(es)
Check whether execution status es is failed or subsumed, and forward failure or subsumption.
Definition macros.hpp:91
double FloatNum
Floating point number base type.
Definition float.hh:106
void aTanProject(Rounding &r, const V &aTanIv, FloatNum &iv_min, FloatNum &iv_max, int &n_min, int &n_max)
Definition tanatan.hpp:41
const Gecode::PropCond PC_FLOAT_BND
Propagate when minimum or maximum of a view changes.
Definition var-type.hpp:292
Gecode toplevel namespace
FloatNum pi_upper(void)
Return upper bound of .
Definition num.hpp:49
Post propagator for SetVar SetOpType SetVar SetRelType r
Definition set.hh:767
FloatNum pi_half_upper(void)
Return upper bound of .
Definition num.hpp:41
void atan(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
ExecStatus
Definition core.hpp:472
@ ES_OK
Execution is okay.
Definition core.hpp:476
@ ES_FIX
Propagation has computed fixpoint.
Definition core.hpp:477
@ ES_FAILED
Execution has resulted in failure.
Definition core.hpp:474
void tan(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
#define I0__PI_2I
#define POS(X)
#define forceinline
Definition config.hpp:187
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56
#define ATANSUP_UP
#define ATANINF_DOWN