1 /* $Id: CoinPackedVectorBase.cpp 2083 2019-01-06 19:38:09Z unxusr $ */
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 *
denseVector(int denseSize) const16 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
operator [](int i) const35 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
setTestForDuplicateIndex(bool test) const56 void CoinPackedVectorBase::setTestForDuplicateIndex(bool test) const
57 {
58 if (test == true) {
59 testForDuplicateIndex_ = true;
60 duplicateIndex("setTestForDuplicateIndex", "CoinPackedVectorBase");
61 } else {
62 testForDuplicateIndex_ = false;
63 testedDuplicateIndex_ = false;
64 }
65 }
66
67 //#############################################################################
68
setTestForDuplicateIndexWhenTrue(bool test) const69 void CoinPackedVectorBase::setTestForDuplicateIndexWhenTrue(bool test) const
70 {
71 // We know everything is okay so let's not test (e.g. full array)
72 testForDuplicateIndex_ = test;
73 testedDuplicateIndex_ = test;
74 }
75
76 //#############################################################################
77
getMaxIndex() const78 int CoinPackedVectorBase::getMaxIndex() const
79 {
80 findMaxMinIndices();
81 return maxIndex_;
82 }
83
84 //-----------------------------------------------------------------------------
85
getMinIndex() const86 int CoinPackedVectorBase::getMinIndex() const
87 {
88 findMaxMinIndices();
89 return minIndex_;
90 }
91
92 //-----------------------------------------------------------------------------
93
duplicateIndex(const char * methodName,const char * className) const94 void CoinPackedVectorBase::duplicateIndex(const char *methodName,
95 const char *className) const
96 {
97 if (testForDuplicateIndex())
98 indexSet(methodName, className);
99 testedDuplicateIndex_ = true;
100 }
101
102 //-----------------------------------------------------------------------------
103
isExistingIndex(int i) const104 bool CoinPackedVectorBase::isExistingIndex(int i) const
105 {
106 if (!testedDuplicateIndex_)
107 duplicateIndex("indexExists", "CoinPackedVectorBase");
108
109 const std::set< int > &sv = *indexSet("indexExists", "CoinPackedVectorBase");
110 return sv.find(i) != sv.end();
111 }
112
findIndex(int i) const113 int CoinPackedVectorBase::findIndex(int i) const
114 {
115 const int *inds = getIndices();
116 int retVal = static_cast< int >(std::find(inds, inds + getNumElements(), i) - inds);
117 if (retVal == getNumElements())
118 retVal = -1;
119 return retVal;
120 }
121
122 //#############################################################################
123
operator ==(const CoinPackedVectorBase & rhs) const124 bool CoinPackedVectorBase::operator==(const CoinPackedVectorBase &rhs) const
125 {
126 if (getNumElements() == 0 || rhs.getNumElements() == 0) {
127 if (getNumElements() == 0 && rhs.getNumElements() == 0)
128 return (true);
129 else
130 return (false);
131 } else {
132 return (getNumElements() == rhs.getNumElements() && std::equal(getIndices(), getIndices() + getNumElements(), rhs.getIndices()) && std::equal(getElements(), getElements() + getNumElements(), rhs.getElements()));
133 }
134 }
135
136 //-----------------------------------------------------------------------------
137
operator !=(const CoinPackedVectorBase & rhs) const138 bool CoinPackedVectorBase::operator!=(const CoinPackedVectorBase &rhs) const
139 {
140 return !((*this) == rhs);
141 }
142
143 //-----------------------------------------------------------------------------
144
compare(const CoinPackedVectorBase & rhs) const145 int CoinPackedVectorBase::compare(const CoinPackedVectorBase &rhs) const
146 {
147 const int size = getNumElements();
148 int itmp = size - rhs.getNumElements();
149 if (itmp != 0) {
150 return itmp;
151 }
152 itmp = memcmp(getIndices(), rhs.getIndices(), size * sizeof(int));
153 if (itmp != 0) {
154 return itmp;
155 }
156 return memcmp(getElements(), rhs.getElements(), size * sizeof(double));
157 }
158
isEquivalent(const CoinPackedVectorBase & rhs) const159 bool CoinPackedVectorBase::isEquivalent(const CoinPackedVectorBase &rhs) const
160 {
161 return isEquivalent(rhs, CoinRelFltEq());
162 }
163
164 //#############################################################################
165
166 double
dotProduct(const double * dense) const167 CoinPackedVectorBase::dotProduct(const double *dense) const
168 {
169 const double *elems = getElements();
170 const int *inds = getIndices();
171 double dp = 0.0;
172 for (int i = getNumElements() - 1; i >= 0; --i)
173 dp += elems[i] * dense[inds[i]];
174 return dp;
175 }
176
177 //-----------------------------------------------------------------------------
178
179 double
oneNorm() const180 CoinPackedVectorBase::oneNorm() const
181 {
182 double norm = 0.0;
183 const double *elements = getElements();
184 for (int i = getNumElements() - 1; i >= 0; --i) {
185 norm += fabs(elements[i]);
186 }
187 return norm;
188 }
189
190 //-----------------------------------------------------------------------------
191
192 double
normSquare() const193 CoinPackedVectorBase::normSquare() const
194 {
195 return std::inner_product(getElements(), getElements() + getNumElements(),
196 getElements(), 0.0);
197 }
198
199 //-----------------------------------------------------------------------------
200
201 double
twoNorm() const202 CoinPackedVectorBase::twoNorm() const
203 {
204 return sqrt(normSquare());
205 }
206
207 //-----------------------------------------------------------------------------
208
209 double
infNorm() const210 CoinPackedVectorBase::infNorm() const
211 {
212 double norm = 0.0;
213 const double *elements = getElements();
214 for (int i = getNumElements() - 1; i >= 0; --i) {
215 norm = CoinMax(norm, fabs(elements[i]));
216 }
217 return norm;
218 }
219
220 //-----------------------------------------------------------------------------
221
222 double
sum() const223 CoinPackedVectorBase::sum() const
224 {
225 return std::accumulate(getElements(), getElements() + getNumElements(), 0.0);
226 }
227
228 //#############################################################################
229
CoinPackedVectorBase()230 CoinPackedVectorBase::CoinPackedVectorBase()
231 : maxIndex_(-COIN_INT_MAX /*0*/)
232 , minIndex_(COIN_INT_MAX /*0*/)
233 , indexSetPtr_(NULL)
234 , testForDuplicateIndex_(true)
235 , testedDuplicateIndex_(false)
236 {
237 }
238
239 //-----------------------------------------------------------------------------
240
~CoinPackedVectorBase()241 CoinPackedVectorBase::~CoinPackedVectorBase()
242 {
243 delete indexSetPtr_;
244 }
245
246 //#############################################################################
247 //#############################################################################
248
findMaxMinIndices() const249 void CoinPackedVectorBase::findMaxMinIndices() const
250 {
251 if (getNumElements() == 0)
252 return;
253 // if indexSet exists then grab begin and rend to get min & max indices
254 else if (indexSetPtr_ != NULL) {
255 maxIndex_ = *indexSetPtr_->rbegin();
256 minIndex_ = *indexSetPtr_->begin();
257 } else {
258 // Have to scan through vector to find min and max.
259 maxIndex_ = *(std::max_element(getIndices(),
260 getIndices() + getNumElements()));
261 minIndex_ = *(std::min_element(getIndices(),
262 getIndices() + getNumElements()));
263 }
264 }
265
266 //-------------------------------------------------------------------
267
268 std::set< int > *
indexSet(const char * methodName,const char * className) const269 CoinPackedVectorBase::indexSet(const char *methodName,
270 const char *className) const
271 {
272 testedDuplicateIndex_ = true;
273 if (indexSetPtr_ == NULL) {
274 // create a set of the indices
275 indexSetPtr_ = new std::set< int >;
276 const int s = getNumElements();
277 const int *inds = getIndices();
278 for (int j = 0; j < s; ++j) {
279 if (!indexSetPtr_->insert(inds[j]).second) {
280 testedDuplicateIndex_ = false;
281 delete indexSetPtr_;
282 indexSetPtr_ = NULL;
283 if (methodName != NULL) {
284 throw CoinError("Duplicate index found", methodName, className);
285 } else {
286 throw CoinError("Duplicate index found",
287 "indexSet", "CoinPackedVectorBase");
288 }
289 }
290 }
291 }
292 return indexSetPtr_;
293 }
294
295 //-----------------------------------------------------------------------------
296
clearIndexSet() const297 void CoinPackedVectorBase::clearIndexSet() const
298 {
299 delete indexSetPtr_;
300 indexSetPtr_ = NULL;
301 }
302
303 //-----------------------------------------------------------------------------
304
clearBase() const305 void CoinPackedVectorBase::clearBase() const
306 {
307 clearIndexSet();
308 maxIndex_ = -COIN_INT_MAX /*0*/;
309 minIndex_ = COIN_INT_MAX /*0*/;
310 testedDuplicateIndex_ = false;
311 }
312
313 //#############################################################################
314
315 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
316 */
317