| 38 | */ |
| 39 | template<class V> |
| 40 | void |
| 41 | aTanProject(Rounding& r, const V& aTanIv, FloatNum& iv_min, FloatNum& iv_max, int& n_min, int& n_max) { |
| 42 | #define I0_PI_2I FloatVal(0,pi_half_upper()) |
| 43 | #define POS(X) ((I0_PI_2I.in(X))?0:1) |
| 44 | #define ATANINF_DOWN r.atan_down(aTanIv.min()) |
| 45 | #define ATANSUP_UP r.atan_up(aTanIv.max()) |
| 46 | |
| 47 | // 0 <=> in [0;PI/2] |
| 48 | // 1 <=> in [PI/2;PI] |
| 49 | switch ( POS(iv_min) ) |
| 50 | { |
| 51 | case 0: |
| 52 | if (r.tan_down(iv_min) > aTanIv.max()) { n_min++; iv_min = ATANINF_DOWN; } |
| 53 | else if (r.tan_up(iv_min) < aTanIv.min()) { iv_min = ATANINF_DOWN; } |
| 54 | break; |
| 55 | case 1: |
| 56 | if (r.tan_down(iv_min) > aTanIv.max()) { n_min+=2; iv_min = ATANINF_DOWN; } |
| 57 | else if (r.tan_up(iv_min) < aTanIv.min()) { n_min++; iv_min = ATANINF_DOWN; } |
| 58 | break; |
| 59 | default: |
| 60 | GECODE_NEVER; |
| 61 | break; |
| 62 | } |
| 63 | |
| 64 | // 0 <=> in [0;PI/2] |
| 65 | // 1 <=> in [PI/2;PI] |
| 66 | switch ( POS(iv_max) ) |
| 67 | { |
| 68 | case 0: |
| 69 | if (r.tan_down(iv_max) > aTanIv.max()) { iv_max = ATANSUP_UP; } |
| 70 | else if (r.tan_up(iv_max) < aTanIv.min()) { n_max--; iv_max = ATANSUP_UP; } |
| 71 | break; |
| 72 | case 1: |
| 73 | if (r.tan_down(iv_max) > aTanIv.max()) { n_max++; iv_max = ATANSUP_UP; } |
| 74 | else if (r.tan_up(iv_max) < aTanIv.min()) { iv_max = ATANSUP_UP; } |
| 75 | break; |
| 76 | default: |
| 77 | GECODE_NEVER; |
| 78 | break; |
| 79 | } |
| 80 | #undef ATANINF_DOWN |
| 81 | #undef ATANSUP_UP |
| 82 | #undef POS |
| 83 | #undef I0_PI_2I |
| 84 | } |
| 85 | |
| 86 | /* |
| 87 | * Bounds consistent tangent operator |
no test coverage detected