this repo has no description
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:
74 GECODE_NEVER;
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:
101 GECODE_NEVER;
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>
119 ExecStatus
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>
139 forceinline
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>
144 ExecStatus
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>
160 forceinline
161 Sin<A,B>::Sin(Space& home, Sin<A,B>& p)
162 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,p) {}
163
164 template<class A, class B>
165 Actor*
166 Sin<A,B>::copy(Space& home) {
167 return new (home) Sin<A,B>(home,*this);
168 }
169
170 template<class A, class B>
171 ExecStatus
172 Sin<A,B>::propagate(Space& home, const ModEventDelta&) {
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>
183 ExecStatus
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>
204 forceinline
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>
209 ExecStatus
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>
230 forceinline
231 Cos<A,B>::Cos(Space& home, Cos<A,B>& p)
232 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,p) {}
233
234 template<class A, class B>
235 Actor*
236 Cos<A,B>::copy(Space& home) {
237 return new (home) Cos<A,B>(home,*this);
238 }
239
240 template<class A, class B>
241 ExecStatus
242 Cos<A,B>::propagate(Space& home, const ModEventDelta&) {
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