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
15double *
16CoinPackedVectorBase::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
34double
35CoinPackedVectorBase::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
57void
58CoinPackedVectorBase::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
71void
72CoinPackedVectorBase::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
81int
82CoinPackedVectorBase::getMaxIndex() const
83{
84 findMaxMinIndices();
85 return maxIndex_;
86}
87
88//-----------------------------------------------------------------------------
89
90int
91CoinPackedVectorBase::getMinIndex() const
92{
93 findMaxMinIndices();
94 return minIndex_;
95}
96
97//-----------------------------------------------------------------------------
98
99void
100CoinPackedVectorBase::duplicateIndex(const char* methodName,
101 const char * className) const
102{
103 if (testForDuplicateIndex())
104 indexSet(methodName, className);
105 testedDuplicateIndex_ = true;
106}
107
108//-----------------------------------------------------------------------------
109
110bool
111CoinPackedVectorBase::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
121int
122CoinPackedVectorBase::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
132bool
133CoinPackedVectorBase::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
150bool
151CoinPackedVectorBase::operator!=(const CoinPackedVectorBase& rhs) const
152{
153 return !( (*this)==rhs );
154}
155
156//-----------------------------------------------------------------------------
157
158int
159CoinPackedVectorBase::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
173bool
174CoinPackedVectorBase::isEquivalent(const CoinPackedVectorBase& rhs) const
175{
176 return isEquivalent(rhs, CoinRelFltEq());
177}
178
179//#############################################################################
180
181double
182CoinPackedVectorBase::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
194double
195CoinPackedVectorBase::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
207double
208CoinPackedVectorBase::normSquare() const
209{
210 return std::inner_product(getElements(), getElements() + getNumElements(),
211 getElements(), 0.0);
212}
213
214//-----------------------------------------------------------------------------
215
216double
217CoinPackedVectorBase::twoNorm() const
218{
219 return sqrt(normSquare());
220}
221
222//-----------------------------------------------------------------------------
223
224double
225CoinPackedVectorBase::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
237double
238CoinPackedVectorBase::sum() const
239{
240 return std::accumulate(getElements(), getElements() + getNumElements(), 0.0);
241}
242
243//#############################################################################
244
245CoinPackedVectorBase::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
254CoinPackedVectorBase::~CoinPackedVectorBase()
255{
256 delete indexSetPtr_;
257}
258
259//#############################################################################
260//#############################################################################
261
262void
263CoinPackedVectorBase::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
282std::set<int> *
283CoinPackedVectorBase::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
311void
312CoinPackedVectorBase::clearIndexSet() const
313{
314 delete indexSetPtr_;
315 indexSetPtr_ = NULL;
316}
317
318//-----------------------------------------------------------------------------
319
320void
321CoinPackedVectorBase::clearBase() const
322{
323 clearIndexSet();
324 maxIndex_ = -COIN_INT_MAX/*0*/;
325 minIndex_ = COIN_INT_MAX/*0*/;
326 testedDuplicateIndex_ = false;
327}
328
329//#############################################################################
330