Generated on Tue Feb 11 2025 17:33:26 for Gecode by doxygen 1.12.0
sincos.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
37 /*
38 * ASin projection function
39 *
40 */
41template<class V>
42void aSinProject(Rounding& r, const V& aSinIv, FloatNum& iv_min, FloatNum& iv_max, int& n_min, int& n_max) {
43 #define I0__PI_2I FloatVal(0,pi_half_upper())
44 #define IPI_2__PII FloatVal(pi_half_lower(),pi_upper())
45 #define IPI__3PI_2I FloatVal(pi_lower(),3*pi_half_upper())
46 #define I3PI_2__2PII FloatVal(3*pi_half_lower(),pi_twice_upper())
47 #define POS(X) ((I0__PI_2I.in(X))?0: (IPI_2__PII.in(X))?1: (IPI__3PI_2I.in(X))?2: 3 )
48 #define ASININF_DOWN r.asin_down(aSinIv.min())
49 #define ASINSUP_UP r.asin_up(aSinIv.max())
50
51 // 0 <=> in [0;PI/2]
52 // 1 <=> in [PI/2;PI]
53 // 2 <=> in [PI;3*PI/2]
54 // 3 <=> in [3*PI/2;2*PI]
55 switch ( POS(iv_min) )
56 {
57 case 0:
58 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
59 else if (r.sin_up(iv_min) < aSinIv.min()) { iv_min = ASININF_DOWN; }
60 break;
61 case 1:
62 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
63 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
64 break;
65 case 2:
66 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
67 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
68 break;
69 case 3:
70 if (r.sin_down(iv_min) > aSinIv.max()) { n_min+=3; iv_min = -ASINSUP_UP; }
71 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
72 break;
73 default:
75 break;
76 }
77
78 // 0 <=> in [0;PI/2]
79 // 1 <=> in [PI/2;PI]
80 // 2 <=> in [PI;3*PI/2]
81 // 3 <=> in [3*PI/2;2*PI]
82 switch ( POS(iv_max) )
83 {
84 case 0:
85 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
86 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max--; iv_max = -ASININF_DOWN; }
87 break;
88 case 1:
89 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
90 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
91 break;
92 case 2:
93 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
94 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
95 break;
96 case 3:
97 if (r.sin_down(iv_max) > aSinIv.max()) { n_max+=2; iv_max = ASINSUP_UP; }
98 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
99 break;
100 default:
102 break;
103 }
104 #undef ASININF_DOWN
105 #undef ASINSUP_UP
106 #undef POS
107 #undef I0__PI_2I
108 #undef IPI_2__PII
109 #undef IPI__3PI_2I
110 #undef I3PI_2__2PII
111}
112
113/*
114 * Bounds consistent sinus operator
115 *
116 */
117
118 template<class A, class B>
120 Sin<A,B>::dopropagate(Space& home, A x0, B x1) {
121 GECODE_ME_CHECK(x1.eq(home,sin(x0.val())));
122 Rounding r;
123 int n_min = 2*static_cast<int>(r.div_up(x0.min(), pi_twice_upper()));
124 int n_max = 2*static_cast<int>(r.div_up(x0.max(), pi_twice_upper()));
125 if (x0.min() < 0) n_min-=2;
126 if (x0.max() < 0) n_max-=2;
127 FloatNum iv_min = r.sub_down(x0.min(),r.mul_down(n_min, pi_upper()));
128 FloatNum iv_max = r.sub_up (x0.max(),r.mul_down(n_max, pi_upper()));
129 aSinProject(r,x1,iv_min,iv_max,n_min,n_max);
130 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
131 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
132 if (n_iv_min > n_iv_max) return ES_FAILED;
133 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max)));
134 GECODE_ME_CHECK(x1.eq(home,sin(x0.val()))); // Redo sin because with x0 reduction, sin may be more accurate
135 return ES_OK;
136 }
137
138 template<class A, class B>
140 Sin<A,B>::Sin(Home home, A x0, B x1)
141 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
142
143 template<class A, class B>
145 Sin<A,B>::post(Home home, A x0, B x1) {
146 if (x0 == x1) {
147 GECODE_ME_CHECK(x0.eq(home,0.0));
148 } else {
149 GECODE_ME_CHECK(x1.gq(home,-1.0));
150 GECODE_ME_CHECK(x1.lq(home,1.0));
151 GECODE_ES_CHECK(dopropagate(home,x0,x1));
152 (void) new (home) Sin<A,B>(home,x0,x1);
153 }
154
155 return ES_OK;
156 }
157
158
159 template<class A, class B>
163
164 template<class A, class B>
165 Actor*
167 return new (home) Sin<A,B>(home,*this);
168 }
169
170 template<class A, class B>
173 GECODE_ES_CHECK(dopropagate(home,x0,x1));
174 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
175 }
176
177 /*
178 * Bounds consistent cosinus operator
179 *
180 */
181
182 template<class A, class B>
184 Cos<A,B>::dopropagate(Space& home, A x0, B x1) {
185 GECODE_ME_CHECK(x1.eq(home,cos(x0.val())));
186 Rounding r;
187 FloatVal x0Trans = x0.val() + FloatVal::pi_half();
188 int n_min = 2*static_cast<int>(r.div_up(x0Trans.min(), pi_twice_upper()));
189 int n_max = 2*static_cast<int>(r.div_up(x0Trans.max(), pi_twice_upper()));
190 if (x0Trans.min() < 0) n_min-=2;
191 if (x0Trans.max() < 0) n_max-=2;
192 FloatNum iv_min = r.sub_down(x0Trans.min(),r.mul_down(n_min, pi_upper()));
193 FloatNum iv_max = r.sub_up (x0Trans.max(),r.mul_down(n_max, pi_upper()));
194 aSinProject(r,x1,iv_min,iv_max,n_min,n_max);
195 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
196 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
197 if (n_iv_min > n_iv_max) return ES_FAILED;
198 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max) - FloatVal::pi_half()));
199 GECODE_ME_CHECK(x1.eq(home,cos(x0.val()))); // Redo sin because with x0 reduction, sin may be more accurate
200 return ES_OK;
201 }
202
203 template<class A, class B>
205 Cos<A,B>::Cos(Home home, A x0, B x1)
206 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
207
208 template<class A, class B>
210 Cos<A,B>::post(Home home, A x0, B x1) {
211 if (x0 == x1) {
212 GECODE_ME_CHECK(x0.gq(home,0.7390851332151));
213 GECODE_ME_CHECK(x0.lq(home,0.7390851332152));
214 bool mod;
215 do {
216 mod = false;
217 GECODE_ME_CHECK_MODIFIED(mod,x0.eq(home,cos(x0.val())));
218 } while (mod);
219 } else {
220 GECODE_ME_CHECK(x1.gq(home,-1.0));
221 GECODE_ME_CHECK(x1.lq(home,1.0));
222 GECODE_ES_CHECK(dopropagate(home,x0,x1));
223 (void) new (home) Cos<A,B>(home,x0,x1);
224 }
225 return ES_OK;
226 }
227
228
229 template<class A, class B>
233
234 template<class A, class B>
235 Actor*
237 return new (home) Cos<A,B>(home,*this);
238 }
239
240 template<class A, class B>
243 GECODE_ES_CHECK(dopropagate(home,x0,x1));
244 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
245 }
246
247}}}
248
249// STATISTICS: float-prop
250
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
friend FloatVal max(const FloatVal &x, const FloatVal &y)
Definition val.hpp:386
friend FloatVal min(const FloatVal &x, const FloatVal &y)
Definition val.hpp:398
static FloatVal pi_half(void)
Return .
Definition val.hpp:109
Floating point rounding policy.
Definition float.hh:154
Propagator for bounds consistent cosinus operator
static ExecStatus dopropagate(Space &home, A x0, B x1)
Perform actual propagation.
Definition sincos.hpp:184
static ExecStatus post(Home home, A x0, B x1)
Post propagator for .
Definition sincos.hpp:210
Cos(Space &home, Cos &p)
Constructor for cloning p.
Definition sincos.hpp:231
virtual Actor * copy(Space &home)
Create copy during cloning.
Definition sincos.hpp:236
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition sincos.hpp:242
Propagator for bounds consistent sinus operator
static ExecStatus dopropagate(Space &home, A x0, B x1)
Perform actual propagation.
Definition sincos.hpp:120
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition sincos.hpp:172
static ExecStatus post(Home home, A x0, B x1)
Post propagator for .
Definition sincos.hpp:145
virtual Actor * copy(Space &home)
Create copy during cloning.
Definition sincos.hpp:166
Sin(Space &home, Sin &p)
Constructor for cloning p.
Definition sincos.hpp:161
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
#define GECODE_ME_CHECK_MODIFIED(modified, me)
Check whether me is failed or modified, and forward failure.
Definition macros.hpp:64
double FloatNum
Floating point number base type.
Definition float.hh:106
void aSinProject(Rounding &r, const V &aSinIv, FloatNum &iv_min, FloatNum &iv_max, int &n_min, int &n_max)
Definition sincos.hpp:42
const Gecode::PropCond PC_FLOAT_BND
Propagate when minimum or maximum of a view changes.
Definition var-type.hpp:292
Gecode toplevel namespace
void sin(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
FloatNum pi_upper(void)
Return upper bound of .
Definition num.hpp:49
Post propagator for SetVar SetOpType SetVar SetRelType r
Definition set.hh:767
void mod(Home home, IntVar x0, IntVar x1, IntVar x2, IntPropLevel ipl=IPL_DEF)
Post propagator for .
void cos(Home home, FloatVar x0, FloatVar x1)
Post propagator for .
FloatNum pi_twice_upper(void)
Return upper bound of .
Definition num.hpp:57
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
#define POS(X)
#define ASININF_DOWN
#define ASINSUP_UP
#define forceinline
Definition config.hpp:187
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56