00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "exprMul.hpp"
00012 #include "CouennePrecisions.hpp"
00013
00014
00017
00018 bool exprMul::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00019
00020
00021
00022 bool resL, resU = resL = false;
00023 int ind;
00024
00025 if ((arglist_ [ind=0] -> Type () <= CONST) ||
00026 (arglist_ [ind=1] -> Type () <= CONST)) {
00027
00028
00029
00030
00031
00032
00033 CouNumber c = arglist_ [ind] -> Value ();
00034
00035 bool argInt = arglist_ [1-ind] -> isInteger ();
00036
00037
00038 ind = arglist_ [1-ind] -> Index ();
00039
00040 if (ind==-1)
00041 return false;
00042
00043 if (c > COUENNE_EPS) {
00044
00045 resL = (l [wind] > - COUENNE_INFINITY) &&
00046 updateBound (-1, l + ind, argInt ? ceil (l [wind] / c - COUENNE_EPS) : (l [wind] / c));
00047 resU = (u [wind] < COUENNE_INFINITY) &&
00048 updateBound ( 1, u + ind, argInt ? floor (u [wind] / c + COUENNE_EPS) : (u [wind] / c));
00049 }
00050 else if (c < - COUENNE_EPS) {
00051
00052
00053
00054
00055 resL = (u [wind] < COUENNE_INFINITY) &&
00056 updateBound (-1, l + ind, argInt ? ceil (u [wind] / c - COUENNE_EPS) : (u [wind] / c));
00057 resU = (l [wind] > - COUENNE_INFINITY) &&
00058 updateBound ( 1, u + ind, argInt ? floor (l [wind] / c + COUENNE_EPS) : (l [wind] / c));
00059 }
00060
00061 if (resL) chg [ind].setLower(t_chg_bounds::CHANGED);
00062 if (resU) chg [ind].setUpper(t_chg_bounds::CHANGED);
00063
00064
00065
00066
00067 } else {
00068
00069
00070
00071
00072
00073 int xi = arglist_ [0] -> Index (),
00074 yi = arglist_ [1] -> Index ();
00075
00076 CouNumber *xl = l + xi, *yl = l + yi, wl = l [wind],
00077 *xu = u + xi, *yu = u + yi, wu = u [wind];
00078
00079
00080
00081
00082 bool resxL, resxU, resyL, resyU =
00083 resxL = resxU = resyL = false;
00084
00085 if (wl >= 0.) {
00086
00087
00088
00089 if (*xu * *yu < wl) {
00090 resxU = (*xu * *yl < wl) && updateBound (+1, xu, wl / *yl);
00091 resyU = (*xl * *yu < wl) && updateBound (+1, yu, wl / *xl);
00092 }
00093
00094
00095
00096 if (*xl * *yl < wl) {
00097 resxL = (*xl * *yu < wl) && updateBound (-1, xl, wl / *yu);
00098 resyL = (*xu * *yl < wl) && updateBound (-1, yl, wl / *xu);
00099 }
00100 } else if (wl > -COUENNE_INFINITY) {
00101
00102
00103
00104
00105 resxL = (*xl * *yl < wl) && (*yl > 0.) && updateBound (-1, xl, wl / *yl);
00106 resyU = (*xu * *yu < wl) && (*yu > 0.) && updateBound (+1, yu, wl / *xu);
00107
00108
00109 resyL = (*xl * *yl < wl) && (*yl < 0.) && updateBound (-1, yl, wl / *xl);
00110 resxU = (*xu * *yu < wl) && (*yu < 0.) && updateBound (+1, xu, wl / *yu);
00111 }
00112
00113
00114
00115
00116 if (wu >= 0.) {
00117
00118 if (wu < COUENNE_INFINITY) {
00119
00120
00121
00122 resxU = (*xu * *yl > wu) && (*yl > 0.) && updateBound (+1, xu, wu / *yl) || resxU;
00123 resyU = (*xl * *yu > wu) && (*yu > 0.) && updateBound (+1, yu, wu / *xl) || resyU;
00124
00125
00126 resxL = (*xl * *yu > wu) && (*yu < 0.) && updateBound (-1, xl, wu / *yu) || resxL;
00127 resyL = (*xu * *yl > wu) && (*yl < 0.) && updateBound (-1, yl, wu / *xu) || resyL;
00128 }
00129
00130 } else {
00131
00132
00133
00134 if (*xu * *yl > wu) {
00135 resxU = (*xu * *yu > wu) && updateBound (+1, xu, wu / *yu) || resxU;
00136 resyL = (*xl * *yl > wu) && updateBound (-1, yl, wu / *xl) || resyL;
00137 }
00138
00139
00140
00141 if (*xl * *yu > wu) {
00142 resxL = (*xl * *yl > wu) && updateBound (-1, xl, wu / *yl) || resxL;
00143 resyU = (*xu * *yu > wu) && updateBound (+1, yu, wu / *xu) || resyU;
00144 }
00145 }
00146
00147 bool
00148 xInt = arglist_ [0] -> isInteger (),
00149 yInt = arglist_ [1] -> isInteger ();
00150
00151 if (resxL) {chg [xi].setLower(t_chg_bounds::CHANGED); if (xInt) *xl = ceil (*xl - COUENNE_EPS);}
00152 if (resxU) {chg [xi].setUpper(t_chg_bounds::CHANGED); if (xInt) *xu = floor (*xu + COUENNE_EPS);}
00153 if (resyL) {chg [yi].setLower(t_chg_bounds::CHANGED); if (yInt) *yl = ceil (*yl - COUENNE_EPS);}
00154 if (resyU) {chg [yi].setUpper(t_chg_bounds::CHANGED); if (yInt) *yu = floor (*yu + COUENNE_EPS);}
00155
00156 resL = resxL || resyL;
00157 resU = resxU || resyU;
00158 }
00159
00160 return (resL || resU);
00161 }