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