1 | /* $Id: CoinPackedVectorBase.cpp 1448 2011-06-19 15:34:41Z stefan $ */ |
2 | // Copyright (C) 2000, International Business Machines |
3 | // Corporation and others. All Rights Reserved. |
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
5 | |
6 | #include <numeric> |
7 | |
8 | #include "CoinPackedVectorBase.hpp" |
9 | #include "CoinTypes.hpp" |
10 | #include "CoinHelperFunctions.hpp" |
11 | #include "CoinFloatEqual.hpp" |
12 | |
13 | //############################################################################# |
14 | |
15 | double * |
16 | CoinPackedVectorBase::denseVector(int denseSize) const |
17 | { |
18 | if (getMaxIndex() >= denseSize) |
19 | throw CoinError("Dense vector size is less than max index" , |
20 | "denseVector" , "CoinPackedVectorBase" ); |
21 | |
22 | double * dv = new double[denseSize]; |
23 | CoinFillN(dv, denseSize, 0.0); |
24 | const int s = getNumElements(); |
25 | const int * inds = getIndices(); |
26 | const double * elems = getElements(); |
27 | for (int i = 0; i < s; ++i) |
28 | dv[inds[i]] = elems[i]; |
29 | return dv; |
30 | } |
31 | |
32 | //----------------------------------------------------------------------------- |
33 | |
34 | double |
35 | CoinPackedVectorBase::operator[](int i) const |
36 | { |
37 | if (! testedDuplicateIndex_) |
38 | duplicateIndex("operator[]" , "CoinPackedVectorBase" ); |
39 | |
40 | // Get a reference to a map of full storage indices to |
41 | // packed storage location. |
42 | const std::set<int> & sv = *indexSet("operator[]" , "CoinPackedVectorBase" ); |
43 | #if 1 |
44 | if (sv.find(i) == sv.end()) |
45 | return 0.0; |
46 | return getElements()[findIndex(i)]; |
47 | #else |
48 | // LL: suggested change, somthing is wrong with this |
49 | const size_t ind = std::distance(sv.begin(), sv.find(i)); |
50 | return (ind == sv.size()) ? 0.0 : getElements()[ind]; |
51 | #endif |
52 | |
53 | } |
54 | |
55 | //############################################################################# |
56 | |
57 | void |
58 | CoinPackedVectorBase::setTestForDuplicateIndex(bool test) const |
59 | { |
60 | if (test == true) { |
61 | testForDuplicateIndex_ = true; |
62 | duplicateIndex("setTestForDuplicateIndex" , "CoinPackedVectorBase" ); |
63 | } else { |
64 | testForDuplicateIndex_ = false; |
65 | testedDuplicateIndex_ = false; |
66 | } |
67 | } |
68 | |
69 | //############################################################################# |
70 | |
71 | void |
72 | CoinPackedVectorBase::setTestForDuplicateIndexWhenTrue(bool test) const |
73 | { |
74 | // We know everything is okay so let's not test (e.g. full array) |
75 | testForDuplicateIndex_ = test; |
76 | testedDuplicateIndex_ = test; |
77 | } |
78 | |
79 | //############################################################################# |
80 | |
81 | int |
82 | CoinPackedVectorBase::getMaxIndex() const |
83 | { |
84 | findMaxMinIndices(); |
85 | return maxIndex_; |
86 | } |
87 | |
88 | //----------------------------------------------------------------------------- |
89 | |
90 | int |
91 | CoinPackedVectorBase::getMinIndex() const |
92 | { |
93 | findMaxMinIndices(); |
94 | return minIndex_; |
95 | } |
96 | |
97 | //----------------------------------------------------------------------------- |
98 | |
99 | void |
100 | CoinPackedVectorBase::duplicateIndex(const char* methodName, |
101 | const char * className) const |
102 | { |
103 | if (testForDuplicateIndex()) |
104 | indexSet(methodName, className); |
105 | testedDuplicateIndex_ = true; |
106 | } |
107 | |
108 | //----------------------------------------------------------------------------- |
109 | |
110 | bool |
111 | CoinPackedVectorBase::isExistingIndex(int i) const |
112 | { |
113 | if (! testedDuplicateIndex_) |
114 | duplicateIndex("indexExists" , "CoinPackedVectorBase" ); |
115 | |
116 | const std::set<int> & sv = *indexSet("indexExists" , "CoinPackedVectorBase" ); |
117 | return sv.find(i) != sv.end(); |
118 | } |
119 | |
120 | |
121 | int |
122 | CoinPackedVectorBase::findIndex(int i) const |
123 | { |
124 | const int * inds = getIndices(); |
125 | int retVal = static_cast<int>(std::find(inds, inds + getNumElements(), i) - inds); |
126 | if (retVal == getNumElements() ) retVal = -1; |
127 | return retVal; |
128 | } |
129 | |
130 | //############################################################################# |
131 | |
132 | bool |
133 | CoinPackedVectorBase::operator==(const CoinPackedVectorBase& rhs) const |
134 | { if (getNumElements() == 0 || rhs.getNumElements() == 0) { |
135 | if (getNumElements() == 0 && rhs.getNumElements() == 0) |
136 | return (true) ; |
137 | else |
138 | return (false) ; |
139 | } else { |
140 | return (getNumElements()==rhs.getNumElements() && |
141 | std::equal(getIndices(),getIndices()+getNumElements(), |
142 | rhs.getIndices()) && |
143 | std::equal(getElements(),getElements()+getNumElements(), |
144 | rhs.getElements())) ; |
145 | } |
146 | } |
147 | |
148 | //----------------------------------------------------------------------------- |
149 | |
150 | bool |
151 | CoinPackedVectorBase::operator!=(const CoinPackedVectorBase& rhs) const |
152 | { |
153 | return !( (*this)==rhs ); |
154 | } |
155 | |
156 | //----------------------------------------------------------------------------- |
157 | |
158 | int |
159 | CoinPackedVectorBase::compare(const CoinPackedVectorBase& rhs) const |
160 | { |
161 | const int size = getNumElements(); |
162 | int itmp = size - rhs.getNumElements(); |
163 | if (itmp != 0) { |
164 | return itmp; |
165 | } |
166 | itmp = memcmp(getIndices(), rhs.getIndices(), size * sizeof(int)); |
167 | if (itmp != 0) { |
168 | return itmp; |
169 | } |
170 | return memcmp(getElements(), rhs.getElements(), size * sizeof(double)); |
171 | } |
172 | |
173 | bool |
174 | CoinPackedVectorBase::isEquivalent(const CoinPackedVectorBase& rhs) const |
175 | { |
176 | return isEquivalent(rhs, CoinRelFltEq()); |
177 | } |
178 | |
179 | //############################################################################# |
180 | |
181 | double |
182 | CoinPackedVectorBase::dotProduct(const double* dense) const |
183 | { |
184 | const double * elems = getElements(); |
185 | const int * inds = getIndices(); |
186 | double dp = 0.0; |
187 | for (int i = getNumElements() - 1; i >= 0; --i) |
188 | dp += elems[i] * dense[inds[i]]; |
189 | return dp; |
190 | } |
191 | |
192 | //----------------------------------------------------------------------------- |
193 | |
194 | double |
195 | CoinPackedVectorBase::oneNorm() const |
196 | { |
197 | double norm = 0.0; |
198 | const double* elements = getElements(); |
199 | for (int i = getNumElements() - 1; i >= 0; --i) { |
200 | norm += fabs(elements[i]); |
201 | } |
202 | return norm; |
203 | } |
204 | |
205 | //----------------------------------------------------------------------------- |
206 | |
207 | double |
208 | CoinPackedVectorBase::normSquare() const |
209 | { |
210 | return std::inner_product(getElements(), getElements() + getNumElements(), |
211 | getElements(), 0.0); |
212 | } |
213 | |
214 | //----------------------------------------------------------------------------- |
215 | |
216 | double |
217 | CoinPackedVectorBase::twoNorm() const |
218 | { |
219 | return sqrt(normSquare()); |
220 | } |
221 | |
222 | //----------------------------------------------------------------------------- |
223 | |
224 | double |
225 | CoinPackedVectorBase::infNorm() const |
226 | { |
227 | double norm = 0.0; |
228 | const double* elements = getElements(); |
229 | for (int i = getNumElements() - 1; i >= 0; --i) { |
230 | norm = CoinMax(norm, fabs(elements[i])); |
231 | } |
232 | return norm; |
233 | } |
234 | |
235 | //----------------------------------------------------------------------------- |
236 | |
237 | double |
238 | CoinPackedVectorBase::sum() const |
239 | { |
240 | return std::accumulate(getElements(), getElements() + getNumElements(), 0.0); |
241 | } |
242 | |
243 | //############################################################################# |
244 | |
245 | CoinPackedVectorBase::CoinPackedVectorBase() : |
246 | maxIndex_(-COIN_INT_MAX/*0*/), |
247 | minIndex_(COIN_INT_MAX/*0*/), |
248 | indexSetPtr_(NULL), |
249 | testForDuplicateIndex_(true), |
250 | testedDuplicateIndex_(false) {} |
251 | |
252 | //----------------------------------------------------------------------------- |
253 | |
254 | CoinPackedVectorBase::~CoinPackedVectorBase() |
255 | { |
256 | delete indexSetPtr_; |
257 | } |
258 | |
259 | //############################################################################# |
260 | //############################################################################# |
261 | |
262 | void |
263 | CoinPackedVectorBase::findMaxMinIndices() const |
264 | { |
265 | if ( getNumElements()==0 ) |
266 | return; |
267 | // if indexSet exists then grab begin and rend to get min & max indices |
268 | else if ( indexSetPtr_ != NULL ) { |
269 | maxIndex_ = *indexSetPtr_->rbegin(); |
270 | minIndex_ = *indexSetPtr_-> begin(); |
271 | } else { |
272 | // Have to scan through vector to find min and max. |
273 | maxIndex_ = *(std::max_element(getIndices(), |
274 | getIndices() + getNumElements())); |
275 | minIndex_ = *(std::min_element(getIndices(), |
276 | getIndices() + getNumElements())); |
277 | } |
278 | } |
279 | |
280 | //------------------------------------------------------------------- |
281 | |
282 | std::set<int> * |
283 | CoinPackedVectorBase::indexSet(const char* methodName, |
284 | const char * className) const |
285 | { |
286 | testedDuplicateIndex_ = true; |
287 | if ( indexSetPtr_ == NULL ) { |
288 | // create a set of the indices |
289 | indexSetPtr_ = new std::set<int>; |
290 | const int s = getNumElements(); |
291 | const int * inds = getIndices(); |
292 | for (int j=0; j < s; ++j) { |
293 | if (!indexSetPtr_->insert(inds[j]).second) { |
294 | testedDuplicateIndex_ = false; |
295 | delete indexSetPtr_; |
296 | indexSetPtr_ = NULL; |
297 | if (methodName != NULL) { |
298 | throw CoinError("Duplicate index found" , methodName, className); |
299 | } else { |
300 | throw CoinError("Duplicate index found" , |
301 | "indexSet" , "CoinPackedVectorBase" ); |
302 | } |
303 | } |
304 | } |
305 | } |
306 | return indexSetPtr_; |
307 | } |
308 | |
309 | //----------------------------------------------------------------------------- |
310 | |
311 | void |
312 | CoinPackedVectorBase::clearIndexSet() const |
313 | { |
314 | delete indexSetPtr_; |
315 | indexSetPtr_ = NULL; |
316 | } |
317 | |
318 | //----------------------------------------------------------------------------- |
319 | |
320 | void |
321 | CoinPackedVectorBase::clearBase() const |
322 | { |
323 | clearIndexSet(); |
324 | maxIndex_ = -COIN_INT_MAX/*0*/; |
325 | minIndex_ = COIN_INT_MAX/*0*/; |
326 | testedDuplicateIndex_ = false; |
327 | } |
328 | |
329 | //############################################################################# |
330 | |