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 #include <oned/rec_bisect_minmax.hpp>
00038
00039
00040 template<typename T, typename Pr>
00041 double oned::RecursiveBisectionMinMax<T, Pr>::pointDiff(const Pr prefixSum, int low, int high, int leftProc, int rightProc, int point)
00042 {
00043 double y1 = RecursiveBisectionMinMax<T,Pr>::calculateDiff (prefixSum, low, high, leftProc, rightProc, point - 1);
00044 double y2 = RecursiveBisectionMinMax<T,Pr>::calculateDiff (prefixSum, low, high, leftProc, rightProc, point);
00045 return y2-y1;
00046 }
00047
00048
00049
00050
00051 template<typename T, typename Pr>
00052 int oned::RecursiveBisectionMinMax<T, Pr>::slopeAt(const Pr prefixSum, int low, int high, int leftProc, int rightProc, int point)
00053 {
00054 if(prefixSum[point - 1] == 0)
00055 return -1;
00056 double diff = pointDiff(prefixSum, low, high, leftProc, rightProc, point);
00057 if(diff <0)
00058 return -1;
00059 else if(diff>0)
00060 return 1;
00061 else
00062 {
00063
00064 while((low<point) && (prefixSum[point] == prefixSum[point-1]))
00065 {
00066 point--;
00067 }
00068 if(diff <= 0)
00069 return -1;
00070 else
00071 return 1;
00072
00073 }
00074 }
00075
00076 template<typename T, typename Pr>
00077 int oned::RecursiveBisectionMinMax<T, Pr>::bimonsearch(const Pr prefixSum, int low, int high, int leftProc, int rightProc)
00078 {
00079 assert(low<high);
00080 int lowlimit=low;
00081 int highlimit=high;
00082 int mid;
00083 while(lowlimit<highlimit)
00084 {
00085 mid = (lowlimit+highlimit)/2;
00086 if(slopeAt(prefixSum, low, high, leftProc, rightProc, mid) == -1)
00087 {
00088 lowlimit = mid+1;
00089 }
00090 else
00091 highlimit = mid;
00092
00093 }
00094 return lowlimit;
00095 }
00096
00097 template<typename T, typename Pr>
00098 double oned::RecursiveBisectionMinMax<T, Pr>::calculateDiff(const Pr prefixSum, int low, int high,
00099 int leftProc, int rightProc, int candidate)
00100 {
00101 assert(low>=0);
00102 assert(candidate>=0);
00103 double a = (prefixSum[candidate] - prefixSum[low - 1]) / ((double)leftProc);
00104 double b = (prefixSum[high] - prefixSum[candidate])/ ((double)rightProc);
00105
00106 return (a>b?a:b);
00107 }
00109 template<typename T, typename Pr>
00110 int oned::RecursiveBisectionMinMax<T, Pr>::linsrch(const Pr prefixSum, int low, int high, int leftProc, int rightProc)
00111 {
00112 double cutWeight;
00113 int cutPoint;
00114
00115 cutWeight = ((prefixSum[high] - prefixSum[low - 1]) * (double)leftProc / ((double)leftProc + (double)rightProc));
00116 cutPoint = binarySearch(prefixSum, low, high, cutWeight+prefixSum[low-1]);
00117
00118
00119
00120 if(cutPoint == -1)
00121 cutWeight = (double)prefixSum[high];
00122 else
00123 cutWeight = calculateDiff (prefixSum, low, high, leftProc, rightProc, cutPoint);
00124
00125 int tmpCutPoint;
00126 double tmpWeight;
00127 for(tmpCutPoint = low; tmpCutPoint < high; tmpCutPoint++)
00128 {
00129 tmpWeight = calculateDiff (prefixSum, low, high, leftProc, rightProc, tmpCutPoint);
00130 if(tmpWeight < cutWeight)
00131 {
00132 cutWeight = tmpWeight;
00133 cutPoint = tmpCutPoint;
00134 }
00135 }
00136 return cutPoint;
00137 }
00138 template<typename T, typename Pr>
00139 int oned::RecursiveBisectionMinMax<T, Pr>::findEvenCut(const Pr prefixSum, int low, int high, int leftProc, int rightProc)
00140 {
00141 assert (low<=high);
00142 assert(leftProc != 0);
00143 assert(rightProc != 0);
00144
00145 int cutPoint = bimonsearch( prefixSum, low, high, leftProc, rightProc)-1;
00146
00147 assert(cutPoint < high);
00148 assert(cutPoint >= low);
00149
00150 return cutPoint;
00151 }
00152
00153
00154
00155 template<typename T, typename Pr>
00156 T oned::RecursiveBisectionMinMax<T, Pr>::rec_bisection_internal(int numProc, int low, int high, const Pr prefixSum, int *cutPoints)
00157 {
00158
00159 int leftProc, rightProc, cutPointHere, candidate;
00160 T candidatediff;
00161
00162 if(low > high)
00163 {
00164 int p;
00165 for (p = 0;p<numProc - 1;p++)
00166 {
00167 cutPoints[p] = high;
00168 }
00169 return 0;
00170 }
00171
00172
00173 assert (prefixSum[high-1]<=prefixSum[high]);
00174 assert (prefixSum[low]<=prefixSum[high]);
00175 assert (numProc>0);
00176
00177 if (numProc == 1)
00178 return prefixSum[high] - prefixSum[low-1];
00179
00180 if (high-low+1 <= numProc)
00181 {
00182 int p;
00183 T m=prefixSum[low] - prefixSum[low - 1];
00184
00185
00186 for (p = 0;p < high-low; p++)
00187 {
00188 cutPoints[p] = low+p;
00189 m = std::max(m, prefixSum[low+p] - prefixSum[low+p-1]);
00190 }
00191
00192 for (;p<numProc - 1;p++)
00193 {
00194 cutPoints[p] = high;
00195 }
00196
00197
00198 return m;
00199 }
00200
00201 if(numProc > 1)
00202 {
00203 leftProc = 1;
00204 rightProc = numProc - leftProc;
00205
00206
00207 int tmpcandidate = findEvenCut(prefixSum, low, high, leftProc, rightProc);
00208 T tmpcandidatediff = calculateDiff(prefixSum, low, high, leftProc, rightProc, tmpcandidate);
00209 candidate = tmpcandidate;
00210 candidatediff = tmpcandidatediff;
00211
00212 for(int tmpleft = leftProc + 1;tmpleft < numProc; tmpleft++)
00213 {
00214 int tmpright = numProc - tmpleft;
00215
00216 tmpcandidate = findEvenCut(prefixSum, low, high, tmpleft, tmpright);
00217 tmpcandidatediff = calculateDiff(prefixSum, low, high, tmpleft, tmpright, candidate);
00218
00219 if(candidatediff > tmpcandidatediff)
00220 {
00221 candidatediff = tmpcandidatediff;
00222 candidate = tmpcandidate;
00223 leftProc = tmpleft;
00224
00225 }
00226 }
00227
00228 rightProc = numProc - leftProc;
00229
00230 assert (candidate<=high);
00231 assert (candidate>=low);
00232
00233 cutPointHere = candidate;
00234
00235
00236 if(cutPointHere == -1)
00237 cutPointHere = low;
00238 assert(cutPointHere > -1);
00239
00240 assert (cutPointHere<=high);
00241 assert (cutPointHere>=low);
00242
00243 *(cutPoints+leftProc-1) = cutPointHere;
00244 assert(cutPointHere >= low);
00245 assert(leftProc + rightProc == numProc);
00246 T a = rec_bisection_internal(leftProc, low, cutPointHere, prefixSum, cutPoints);
00247 T b = rec_bisection_internal(rightProc, cutPointHere+1, high, prefixSum, cutPoints+leftProc);
00248 return std::max(a,b);
00249 }
00250 assert (0);
00251 return -1;
00252 }
00253
00254 template <typename T, typename Pr>
00255 T oned::RecursiveBisectionMinMax<T, Pr>::rec_bisection(int procCount, const Pr prefixSumArray,
00256 int length, int *cutIndexes, T )
00257 {
00258 return rec_bisection_internal(procCount, 1, length - 1, prefixSumArray, cutIndexes);
00259 }