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