00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 namespace Gecode { namespace Float { namespace Trigonometric {
00039
00040
00041
00042
00043
00044
00045 template<class V>
00046 void aSinProject(Rounding& r, const V& aSinIv, FloatNum& iv_min, FloatNum& iv_max, int& n_min, int& n_max) {
00047 #define I0__PI_2I FloatVal(0,pi_half_upper())
00048 #define IPI_2__PII FloatVal(pi_half_lower(),pi_upper())
00049 #define IPI__3PI_2I FloatVal(pi_lower(),3*pi_half_upper())
00050 #define I3PI_2__2PII FloatVal(3*pi_half_lower(),pi_twice_upper())
00051 #define POS(X) ((I0__PI_2I.in(X))?0: (IPI_2__PII.in(X))?1: (IPI__3PI_2I.in(X))?2: 3 )
00052 #define ASININF_DOWN r.asin_down(aSinIv.min())
00053 #define ASINSUP_UP r.asin_up(aSinIv.max())
00054
00055
00056
00057
00058
00059 switch ( POS(iv_min) )
00060 {
00061 case 0:
00062 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
00063 else if (r.sin_up(iv_min) < aSinIv.min()) { iv_min = ASININF_DOWN; }
00064 break;
00065 case 1:
00066 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
00067 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
00068 break;
00069 case 2:
00070 if (r.sin_down(iv_min) > aSinIv.max()) { n_min++; iv_min = -ASINSUP_UP; }
00071 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
00072 break;
00073 case 3:
00074 if (r.sin_down(iv_min) > aSinIv.max()) { n_min+=3; iv_min = -ASINSUP_UP; }
00075 else if (r.sin_up(iv_min) < aSinIv.min()) { n_min+=2; iv_min = ASININF_DOWN; }
00076 break;
00077 default:
00078 GECODE_NEVER;
00079 break;
00080 }
00081
00082
00083
00084
00085
00086 switch ( POS(iv_max) )
00087 {
00088 case 0:
00089 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
00090 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max--; iv_max = -ASININF_DOWN; }
00091 break;
00092 case 1:
00093 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
00094 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
00095 break;
00096 case 2:
00097 if (r.sin_down(iv_max) > aSinIv.max()) { iv_max = ASINSUP_UP; }
00098 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
00099 break;
00100 case 3:
00101 if (r.sin_down(iv_max) > aSinIv.max()) { n_max+=2; iv_max = ASINSUP_UP; }
00102 else if (r.sin_up(iv_max) < aSinIv.min()) { n_max++; iv_max = -ASININF_DOWN; }
00103 break;
00104 default:
00105 GECODE_NEVER;
00106 break;
00107 }
00108 #undef ASININF_DOWN
00109 #undef ASINSUP_UP
00110 #undef POS
00111 #undef I0__PI_2I
00112 #undef IPI_2__PII
00113 #undef IPI__3PI_2I
00114 #undef I3PI_2__2PII
00115 }
00116
00117
00118
00119
00120
00121
00122 template<class A, class B>
00123 forceinline
00124 Sin<A,B>::Sin(Home home, A x0, B x1)
00125 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
00126
00127 template<class A, class B>
00128 ExecStatus
00129 Sin<A,B>::post(Home home, A x0, B x1) {
00130 if (same(x0,x1)) {
00131 GECODE_ME_CHECK(x0.eq(home,0.0));
00132 } else {
00133 GECODE_ME_CHECK(x1.gq(home,-1.0));
00134 GECODE_ME_CHECK(x1.lq(home,1.0));
00135 (void) new (home) Sin<A,B>(home,x0,x1);
00136 }
00137
00138 return ES_OK;
00139 }
00140
00141
00142 template<class A, class B>
00143 forceinline
00144 Sin<A,B>::Sin(Space& home, bool share, Sin<A,B>& p)
00145 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p) {}
00146
00147 template<class A, class B>
00148 Actor*
00149 Sin<A,B>::copy(Space& home, bool share) {
00150 return new (home) Sin<A,B>(home,share,*this);
00151 }
00152
00153 template<class A, class B>
00154 ExecStatus
00155 Sin<A,B>::propagate(Space& home, const ModEventDelta&) {
00156 GECODE_ME_CHECK(x1.eq(home,sin(x0.val())));
00157 Rounding r;
00158 int n_min = 2*static_cast<int>(r.div_up(x0.min(), pi_twice_upper()));
00159 int n_max = 2*static_cast<int>(r.div_up(x0.max(), pi_twice_upper()));
00160 if (x0.min() < 0) n_min-=2;
00161 if (x0.max() < 0) n_max-=2;
00162 FloatNum iv_min = r.sub_down(x0.min(),r.mul_down(n_min, pi_upper()));
00163 FloatNum iv_max = r.sub_up (x0.max(),r.mul_down(n_max, pi_upper()));
00164 aSinProject(r,x1,iv_min,iv_max,n_min,n_max);
00165 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
00166 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
00167 if (n_iv_min > n_iv_max) return ES_FAILED;
00168 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max)));
00169 GECODE_ME_CHECK(x1.eq(home,sin(x0.val())));
00170 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00171 }
00172
00173
00174
00175
00176
00177
00178 template<class A, class B>
00179 forceinline
00180 Cos<A,B>::Cos(Home home, A x0, B x1)
00181 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
00182
00183 template<class A, class B>
00184 ExecStatus
00185 Cos<A,B>::post(Home home, A x0, B x1) {
00186 if (same(x0,x1)) {
00187 GECODE_ME_CHECK(x0.gq(home,0.7390851332151));
00188 GECODE_ME_CHECK(x0.lq(home,0.7390851332152));
00189 bool mod;
00190 do {
00191 mod = false;
00192 GECODE_ME_CHECK_MODIFIED(mod,x0.eq(home,cos(x0.val())));
00193 } while (mod);
00194 } else {
00195 GECODE_ME_CHECK(x1.gq(home,-1.0));
00196 GECODE_ME_CHECK(x1.lq(home,1.0));
00197 (void) new (home) Cos<A,B>(home,x0,x1);
00198 }
00199 return ES_OK;
00200 }
00201
00202
00203 template<class A, class B>
00204 forceinline
00205 Cos<A,B>::Cos(Space& home, bool share, Cos<A,B>& p)
00206 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p) {}
00207
00208 template<class A, class B>
00209 Actor*
00210 Cos<A,B>::copy(Space& home, bool share) {
00211 return new (home) Cos<A,B>(home,share,*this);
00212 }
00213
00214 template<class A, class B>
00215 ExecStatus
00216 Cos<A,B>::propagate(Space& home, const ModEventDelta&) {
00217 GECODE_ME_CHECK(x1.eq(home,cos(x0.val())));
00218 Rounding r;
00219 FloatVal x0Trans = x0.val() + FloatVal::pi_half();
00220 int n_min = 2*static_cast<int>(r.div_up(x0Trans.min(), pi_twice_upper()));
00221 int n_max = 2*static_cast<int>(r.div_up(x0Trans.max(), pi_twice_upper()));
00222 if (x0Trans.min() < 0) n_min-=2;
00223 if (x0Trans.max() < 0) n_max-=2;
00224 FloatNum iv_min = r.sub_down(x0Trans.min(),r.mul_down(n_min, pi_upper()));
00225 FloatNum iv_max = r.sub_up (x0Trans.max(),r.mul_down(n_max, pi_upper()));
00226 aSinProject(r,x1,iv_min,iv_max,n_min,n_max);
00227 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
00228 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
00229 if (n_iv_min > n_iv_max) return ES_FAILED;
00230 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max) - FloatVal::pi_half()));
00231 GECODE_ME_CHECK(x1.eq(home,cos(x0.val())));
00232 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00233 }
00234
00235 }}}
00236
00237
00238