| 90 | |
| 91 | template<class A, class B> |
| 92 | ExecStatus |
| 93 | Tan<A,B>::dopropagate(Space& home, A x0, B x1) { |
| 94 | Rounding r; |
| 95 | int n_min = static_cast<int>(r.div_up(x0.min() + pi_half_upper(), pi_upper())); |
| 96 | int n_max = static_cast<int>(r.div_up(x0.max() + pi_half_upper(), pi_upper())); |
| 97 | |
| 98 | if (x0 == x1) { |
| 99 | #define I0_PI_2I FloatVal(0,pi_half_upper()) |
| 100 | if (I0_PI_2I.in(x0.max())) GECODE_ME_CHECK(x0.lq(home, 0)); |
| 101 | if (I0_PI_2I.in(-x0.min())) GECODE_ME_CHECK(x0.gq(home, 0)); |
| 102 | #undef I0_PI_2I |
| 103 | |
| 104 | n_min = static_cast<int>(r.div_up(x0.min(), pi_upper())); |
| 105 | n_max = static_cast<int>(r.div_up(x0.max(), pi_upper())); |
| 106 | |
| 107 | FloatNum x0_min; |
| 108 | FloatNum x0_max; |
| 109 | FloatNum t = x0.min(); |
| 110 | do { |
| 111 | x0_min = t; |
| 112 | if (r.tan_down(x0_min) > x0_min) n_min++; |
| 113 | t = r.add_down(r.mul_up(n_min,pi_upper()),r.tan_down(x0_min)); |
| 114 | } while (t > x0_min); |
| 115 | t = r.sub_down(r.mul_up(2*n_max,pi_upper()),x0.max()); |
| 116 | do { |
| 117 | x0_max = t; |
| 118 | if (r.tan_down(x0_max) < x0_max) n_max--; |
| 119 | t = r.add_up(r.mul_up(n_max,pi_upper()),r.tan_up(x0_max)); |
| 120 | } while (t > x0_max); |
| 121 | x0_max = r.sub_up(r.mul_up(2*n_max,pi_upper()),x0_max); |
| 122 | |
| 123 | if (x0_min > x0_max) return ES_FAILED; |
| 124 | GECODE_ME_CHECK(x0.eq(home,FloatVal(x0_min,x0_max))); |
| 125 | } else { |
| 126 | GECODE_ME_CHECK(x1.eq(home,tan(x0.val()))); |
| 127 | n_min = static_cast<int>(r.div_up(x0.min(), pi_upper())); |
| 128 | n_max = static_cast<int>(r.div_up(x0.max(), pi_upper())); |
| 129 | if (x0.min() < 0) n_min--; |
| 130 | if (x0.max() < 0) n_max--; |
| 131 | FloatNum iv_min = r.sub_down(x0.min(),r.mul_down(n_min, pi_upper())); |
| 132 | FloatNum iv_max = r.sub_up (x0.max(),r.mul_down(n_max, pi_upper())); |
| 133 | aTanProject(r,x1,iv_min,iv_max,n_min,n_max); |
| 134 | FloatNum n_iv_min = r.add_down(iv_min,r.mul_down(n_min, pi_upper())); |
| 135 | FloatNum n_iv_max = r.add_up (iv_max,r.mul_down(n_max, pi_upper())); |
| 136 | if (n_iv_min > n_iv_max) return ES_FAILED; |
| 137 | GECODE_ME_CHECK(x0.eq(home,FloatVal(n_iv_min,n_iv_max))); |
| 138 | GECODE_ME_CHECK(x1.eq(home,tan(x0.val()))); // Redo tan because with x0 reduction, sin may be more accurate |
| 139 | } |
| 140 | |
| 141 | return ES_OK; |
| 142 | } |
| 143 | |
| 144 | template<class A, class B> |
| 145 | forceinline |
nothing calls this directly
no test coverage detected