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 template<class V>
00044 void
00045 aTanProject(Rounding& r, const V& aTanIv, FloatNum& iv_min, FloatNum& iv_max, int& n_min, int& n_max) {
00046 #define I0__PI_2I FloatVal(0,pi_half_upper())
00047 #define POS(X) ((I0__PI_2I.in(X))?0:1)
00048 #define ATANINF_DOWN r.atan_down(aTanIv.min())
00049 #define ATANSUP_UP r.atan_up(aTanIv.max())
00050
00051
00052
00053 switch ( POS(iv_min) )
00054 {
00055 case 0:
00056 if (r.tan_down(iv_min) > aTanIv.max()) { n_min++; iv_min = ATANINF_DOWN; }
00057 else if (r.tan_up(iv_min) < aTanIv.min()) { iv_min = ATANINF_DOWN; }
00058 break;
00059 case 1:
00060 if (r.tan_down(iv_min) > aTanIv.max()) { n_min+=2; iv_min = ATANINF_DOWN; }
00061 else if (r.tan_up(iv_min) < aTanIv.min()) { n_min++; iv_min = ATANINF_DOWN; }
00062 break;
00063 default:
00064 GECODE_NEVER;
00065 break;
00066 }
00067
00068
00069
00070 switch ( POS(iv_max) )
00071 {
00072 case 0:
00073 if (r.tan_down(iv_max) > aTanIv.max()) { iv_max = ATANSUP_UP; }
00074 else if (r.tan_up(iv_max) < aTanIv.min()) { n_max--; iv_max = ATANSUP_UP; }
00075 break;
00076 case 1:
00077 if (r.tan_down(iv_max) > aTanIv.max()) { n_max++; iv_max = ATANSUP_UP; }
00078 else if (r.tan_up(iv_max) < aTanIv.min()) { iv_max = ATANSUP_UP; }
00079 break;
00080 default:
00081 GECODE_NEVER;
00082 break;
00083 }
00084 #undef ATANINF_DOWN
00085 #undef ATANSUP_UP
00086 #undef POS
00087 #undef I0__PI_2I
00088 }
00089
00090
00091
00092
00093
00094
00095 template<class A, class B>
00096 forceinline
00097 Tan<A,B>::Tan(Home home, A x0, B x1)
00098 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
00099
00100 template<class A, class B>
00101 ExecStatus
00102 Tan<A,B>::post(Home home, A x0, B x1) {
00103 if (same(x0,x1)) {
00104 #define I0__PI_2I FloatVal(0,pi_half_upper())
00105 if (I0__PI_2I.in(x0.max())) GECODE_ME_CHECK(x0.lq(home,0));
00106 if (I0__PI_2I.in(-x0.min())) GECODE_ME_CHECK(x0.gq(home,0));
00107 #undef I0__PI_2I
00108 }
00109
00110 (void) new (home) Tan<A,B>(home,x0,x1);
00111 return ES_OK;
00112 }
00113
00114 template<class A, class B>
00115 forceinline
00116 Tan<A,B>::Tan(Space& home, bool share, Tan<A,B>& p)
00117 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p) {}
00118
00119 template<class A, class B>
00120 Actor*
00121 Tan<A,B>::copy(Space& home, bool share) {
00122 return new (home) Tan<A,B>(home,share,*this);
00123 }
00124
00125 template<class A, class B>
00126 ExecStatus
00127 Tan<A,B>::propagate(Space& home, const ModEventDelta&) {
00128 Rounding r;
00129 int n_min = static_cast<int>(r.div_up(x0.min() + pi_half_upper(), pi_upper()));
00130 int n_max = static_cast<int>(r.div_up(x0.max() + pi_half_upper(), pi_upper()));
00131
00132 if (same(x0,x1)) {
00133 #define I0__PI_2I FloatVal(0,pi_half_upper())
00134 if (I0__PI_2I.in(x0.max())) GECODE_ME_CHECK(x0.lq(home,0));
00135 if (I0__PI_2I.in(-x0.min())) GECODE_ME_CHECK(x0.gq(home,0));
00136 #undef I0__PI_2I
00137
00138 n_min = static_cast<int>(r.div_up(x0.min(), pi_upper()));
00139 n_max = static_cast<int>(r.div_up(x0.max(), pi_upper()));
00140
00141 FloatNum x0_min;
00142 FloatNum x0_max;
00143 FloatNum t = x0.min();
00144 do {
00145 x0_min = t;
00146 if (r.tan_down(x0_min) > x0_min) n_min++;
00147 t = r.add_down(r.mul_up(n_min,pi_upper()),r.tan_down(x0_min));
00148 } while (t > x0_min);
00149 t = r.sub_down(r.mul_up(2*n_max,pi_upper()),x0.max());
00150 do {
00151 x0_max = t;
00152 if (r.tan_down(x0_max) < x0_max) n_max--;
00153 t = r.add_up(r.mul_up(n_max,pi_upper()),r.tan_up(x0_max));
00154 } while (t > x0_max);
00155 x0_max = r.sub_up(r.mul_up(2*n_max,pi_upper()),x0_max);
00156
00157 if (x0_min > x0_max) return ES_FAILED;
00158 GECODE_ME_CHECK(x0.eq(home,FloatVal(x0_min,x0_max)));
00159 } else {
00160 GECODE_ME_CHECK(x1.eq(home,tan(x0.val())));
00161 n_min = static_cast<int>(r.div_up(x0.min(), pi_upper()));
00162 n_max = static_cast<int>(r.div_up(x0.max(), pi_upper()));
00163 if (x0.min() < 0) n_min--;
00164 if (x0.max() < 0) n_max--;
00165 FloatNum iv_min = r.sub_down(x0.min(),r.mul_down(n_min, pi_upper()));
00166 FloatNum iv_max = r.sub_up (x0.max(),r.mul_down(n_max, pi_upper()));
00167 aTanProject(r,x1,iv_min,iv_max,n_min,n_max);
00168 FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper()));
00169 FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper()));
00170 if (n_iv_min > n_iv_max) return ES_FAILED;
00171 GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max)));
00172 GECODE_ME_CHECK(x1.eq(home,tan(x0.val())));
00173 }
00174
00175 return (x0.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00176 }
00177
00178
00179
00180
00181
00182
00183 template<class A, class B>
00184 forceinline
00185 ATan<A,B>::ATan(Home home, A x0, B x1)
00186 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,x0,x1) {}
00187
00188 template<class A, class B>
00189 ExecStatus
00190 ATan<A,B>::post(Home home, A x0, B x1) {
00191 if (same(x0,x1)) {
00192 GECODE_ME_CHECK(x0.eq(home,0.0));
00193 } else {
00194 (void) new (home) ATan<A,B>(home,x0,x1);
00195 }
00196 return ES_OK;
00197 }
00198
00199
00200 template<class A, class B>
00201 forceinline
00202 ATan<A,B>::ATan(Space& home, bool share, ATan<A,B>& p)
00203 : MixBinaryPropagator<A,PC_FLOAT_BND,B,PC_FLOAT_BND>(home,share,p) {}
00204
00205 template<class A, class B>
00206 Actor*
00207 ATan<A,B>::copy(Space& home, bool share) {
00208 return new (home) ATan<A,B>(home,share,*this);
00209 }
00210
00211 template<class A, class B>
00212 ExecStatus
00213 ATan<A,B>::propagate(Space& home, const ModEventDelta&) {
00214 GECODE_ME_CHECK(x1.eq(home,atan(x0.domain())));
00215 GECODE_ME_CHECK(x0.eq(home,tan(x1.domain())));
00216 return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00217 }
00218
00219 }}}
00220
00221
00222