1 /* Siconos is a program dedicated to modeling, simulation and control
2  * of non smooth dynamical systems.
3  *
4  * Copyright 2021 INRIA.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17 */
18 
19 #include "SiconosConfig.h"
20 
21 #include "SiconosAlgebraTypeDef.hpp"
22 #include "SiconosVectorIterator.hpp"
23 #include "Tools.hpp"
24 
25 #include <boost/numeric/ublas/io.hpp>            // for >>
26 //#include <boost/numeric/ublas/vector_proxy.hpp>  // for project
27 #include <boost/numeric/ublas/vector_sparse.hpp>
28 
29 
30 #include <boost/numeric/bindings/ublas/vector_proxy.hpp>
31 #include <boost/numeric/bindings/blas.hpp>
32 #include <boost/numeric/bindings/ublas/vector.hpp>
33 #include <boost/numeric/bindings/std/vector.hpp>
34 namespace siconosBindings = boost::numeric::bindings::blas;
35 
36 #include "SimpleMatrix.hpp"
37 #include "BlockVector.hpp"
38 #include "ioVector.hpp"
39 #include "SiconosVector.hpp"
40 #include "SiconosAlgebra.hpp"
41 #include <cmath>        // std::exp(double)
42 #include <algorithm>    // std::transform
43 #include "SiconosException.hpp"
44 //#define DEBUG_MESSAGES
45 #include "siconos_debug.h"
46 
47 // Do not document
48 /// @cond
49 #include "Question.hpp"
50 
51 struct IsDense : public Question<bool>
52 {
53   using SiconosVisitor::visit;
54 
visitIsDense55   void visit(const SiconosVector& v)
56   {
57     answer = v._dense;
58   }
59 
visitIsDense60   void visit(const BlockVector& v)
61   {
62     answer = false;
63   }
64 };
65 
66 struct IsSparse : public Question<bool>
67 {
68 
69   using SiconosVisitor::visit;
70 
visitIsSparse71   void visit(const SiconosVector& v)
72   {
73     answer = !v._dense;
74   }
75 
visitIsSparse76   void visit(const BlockVector& v)
77   {
78     answer = false;
79   }
80 };
81 
82 struct IsBlock : public Question<bool>
83 {
84   using SiconosVisitor::visit;
85 
visitIsBlock86   void visit(const SiconosVector& v)
87   {
88     answer = false;
89   }
90 
visitIsBlock91   void visit(const BlockVector& v)
92   {
93     answer = true;
94   }
95 };
96 
97 
98 /// @endcond
99 
100 
101 // =================================================
102 //                CONSTRUCTORS
103 // =================================================
104 
105 // Default
SiconosVector()106 SiconosVector::SiconosVector()
107 {
108   _dense = true;
109   vect.Dense = new DenseVect(ublas::zero_vector<double>());
110 }
111 
112 // parameters: dimension and type.
SiconosVector(unsigned row,Siconos::UBLAS_TYPE type)113 SiconosVector::SiconosVector(unsigned row, Siconos::UBLAS_TYPE type)
114 {
115   if(type == Siconos::SPARSE)
116   {
117     _dense = false;
118     vect.Sparse = new SparseVect(ublas::zero_vector<double>(row));
119   }
120   else if(type == Siconos::DENSE)
121   {
122     _dense = true;
123     vect.Dense = new DenseVect(ublas::zero_vector<double>(row));
124   }
125   else
126   {
127     THROW_EXCEPTION("invalid type");
128   }
129 }
130 
131 // parameters: dimension, default value for all components and type.
SiconosVector(unsigned row,double val,Siconos::UBLAS_TYPE type)132 SiconosVector::SiconosVector(unsigned row, double val, Siconos::UBLAS_TYPE type)
133 {
134   if(type == Siconos::SPARSE)
135   {
136     _dense = false;
137     vect.Sparse = new SparseVect(row);
138     fill(val);
139   }
140   else if(type == Siconos::DENSE)
141   {
142     _dense = true;
143     vect.Dense = new DenseVect(ublas::scalar_vector<double>(row, val));
144   }
145   else
146   {
147     THROW_EXCEPTION("invalid type");
148   }
149 }
150 
151 // parameters: a vector (stl) of double and the type.
SiconosVector(const std::vector<double> & v,Siconos::UBLAS_TYPE typ)152 SiconosVector::SiconosVector(const std::vector<double>& v, Siconos::UBLAS_TYPE typ)
153 {
154   if(typ != Siconos::DENSE)
155     THROW_EXCEPTION("invalid type");
156 
157   _dense = true;
158   vect.Dense = new DenseVect(v.size());
159   std::copy(v.begin(), v.end(), (vect.Dense)->begin());
160 }
161 
162 // Copy
SiconosVector(const SiconosVector & svect)163 SiconosVector::SiconosVector(const SiconosVector &svect) : std::enable_shared_from_this<SiconosVector>()
164 {
165   if(ask<IsDense>(svect))  // dense
166   {
167     _dense = true;
168     vect.Dense = new DenseVect(svect.size());
169     noalias(*vect.Dense) = (*svect.dense());
170     // std::copy((vect.Dense)->begin(), (vect.Dense)->end(), (svect.dense())->begin());
171   }
172   else //sparse
173   {
174     _dense = false;
175     vect.Sparse = new SparseVect(svect.size());
176     noalias(*vect.Sparse) = (*svect.sparse());
177     //std::copy((vect.Sparse)->begin(), (vect.Sparse)->end(), (svect.sparse())->begin());
178   }
179   // Note FP: using constructor + noalias = (or std::copy) seems to be more
180   // efficient than a call to ublas::vector copy constructor, this for
181   // large or small vectors.
182 }
183 
184 
SiconosVector(const DenseVect & m)185 SiconosVector::SiconosVector(const DenseVect& m)
186 {
187   _dense = true;
188   vect.Dense = new DenseVect(m.size());
189   noalias(*vect.Dense) = m;
190 
191 }
192 
SiconosVector(const SparseVect & m)193 SiconosVector::SiconosVector(const SparseVect& m)
194 {
195   _dense = false;
196   vect.Sparse = new SparseVect(m.size());
197   noalias(*vect.Sparse) = m;
198 }
199 
SiconosVector(const std::string & file,bool ascii)200 SiconosVector::SiconosVector(const std::string &file, bool ascii)
201 {
202   _dense = true;
203   vect.Dense = new DenseVect();
204   if(ascii)
205   {
206     ioVector::read(file, *this, ioVector::ASCII_IN);
207   }
208   else
209   {
210     ioVector::read(file, *this, ioVector::BINARY_IN);
211   }
212 }
213 
SiconosVector(const SiconosVector & v1,const SiconosVector & v2)214 SiconosVector::SiconosVector(const SiconosVector& v1, const SiconosVector& v2)
215 {
216   unsigned int size1 = v1.size();
217   if(ask<IsDense>(v1) && ask<IsDense>(v2))
218   {
219     _dense = true;
220     vect.Dense = new DenseVect(size1 + v2.size());
221   }
222   else if(ask<IsSparse>(v1) && ask<IsSparse>(v2))
223   {
224     _dense = false;
225     vect.Sparse = new SparseVect(size1 + v2.size());
226   }
227   else
228   {
229     THROW_EXCEPTION("mixed dense and sparse vector detected");
230   }
231   setBlock(0, v1);
232   setBlock(size1, v2);
233 }
234 
235 // Copy a block vector into a SiconosVector
236 // This is mostly used to handle contiguous memory.
SiconosVector(const BlockVector & input)237 SiconosVector::SiconosVector(const BlockVector & input)
238 {
239   std::cout << "BLOCK COPY !!!!" << std::endl;
240   if(input.isDense())
241   {
242     _dense = true;
243     vect.Dense = new DenseVect(input.size());
244   }
245   else
246   {
247     _dense = false;
248     vect.Sparse = new SparseVect(input.size());
249   }
250 
251   unsigned int pos = 0;
252   for(auto it = input.begin(); it != input.end(); ++it)
253   {
254     setBlock(pos, **it);
255     pos += (*it)->size();
256   }
257 }
258 
259 
~SiconosVector()260 SiconosVector::~SiconosVector()
261 {
262   if(_dense)
263     delete(vect.Dense);
264   else
265     delete(vect.Sparse);
266 }
267 
268 
269 // =================================================
270 //        get Ublas component (dense or sparse)
271 // =================================================
272 
sparse() const273 SparseVect* SiconosVector::sparse()const
274 {
275 
276   if(_dense)
277     THROW_EXCEPTION("the current vector is not a Sparse vector");
278 
279   return vect.Sparse;
280 }
281 
getArray() const282 double* SiconosVector::getArray() const
283 {
284   assert(vect.Dense && "SiconosVector::getArray() : not yet implemented for sparse vector.");
285 
286   return &(((*vect.Dense).data())[0]);
287 }
288 
289 // ===========================
290 //       fill vector
291 // ===========================
292 
zero()293 void SiconosVector::zero()
294 {
295   if(_dense)
296     siconosBindings::scal(0.0, *vect.Dense);
297 
298   else
299   {
300     assert(vect.Sparse);
301     *vect.Sparse *= 0.0;
302   }
303 
304 }
305 
fill(double value)306 void SiconosVector::fill(double value)
307 {
308   if(!_dense)
309   {
310     for(unsigned int i = 0; i < (vect.Sparse)->size(); ++i)
311       (vect.Sparse)->push_back(i, value);
312   }
313   else
314     siconosBindings::set(value, *vect.Dense);
315 
316 
317 }
318 
319 //=======================
320 // set vector dimension
321 //=======================
322 
resize(unsigned int n,bool preserve)323 void SiconosVector::resize(unsigned int n, bool preserve)
324 {
325   if(_dense)
326     (vect.Dense)->resize(n, preserve);
327   else
328     (vect.Sparse)->resize(n, preserve);
329 }
330 
331 //=======================
332 //       get norm
333 //=======================
334 
normInf() const335 double SiconosVector::normInf() const
336 {
337   if(_dense)
338     return norm_inf(*vect.Dense);
339   else //if(num==Siconos::SPARSE)
340     return norm_inf(*vect.Sparse);
341 }
342 
norm2() const343 double SiconosVector::norm2() const
344 {
345   if(_dense)
346     return ublas::norm_2(*vect.Dense);
347   else //if(num==Siconos::SPARSE)
348     return ublas::norm_2(*vect.Sparse);
349 }
350 //======================================
351 // get sum of all elements of the vector
352 //=====================================
vector_sum() const353 double SiconosVector::vector_sum() const
354 {
355   if(_dense)
356     return ublas::sum(*vect.Dense);
357   else
358     return ublas::sum(*vect.Sparse);
359 }
360 
361 //=====================
362 // screen display
363 //=====================
364 
display() const365 void SiconosVector::display()const
366 {
367   std::cout.setf(std::ios::scientific);
368   std::cout.precision(6);
369   if(_dense)
370     std::cout << *vect.Dense << std::endl;
371   else if(vect.Sparse)
372     std::cout << *vect.Sparse << std::endl;
373 }
374 
375 //============================
376 // Convert vector to a std::string
377 //============================
378 
toString() const379 std::string SiconosVector::toString() const
380 {
381   return ::toString(*this);
382 }
383 
384 //=====================
385 // convert to an ostream
386 //=====================
387 
operator <<(std::ostream & os,const SiconosVector & sv)388 std::ostream& operator<<(std::ostream& os, const SiconosVector& sv)
389 {
390   if(sv._dense)
391     os << *sv.vect.Dense;
392   else
393     os << *sv.vect.Sparse;
394   return os;
395 }
396 
397 //=============================
398 // Elements access (get or set)
399 //=============================
400 
getValue(unsigned int row) const401 double SiconosVector::getValue(unsigned int row) const
402 {
403   assert(row < size() && "SiconosVector::getValue(index) : Index out of range");
404 
405   if(_dense)
406     return (*vect.Dense)(row);
407   else
408     return (*vect.Sparse)(row);
409 }
410 
setValue(unsigned int row,double value)411 void SiconosVector::setValue(unsigned int row, double value)
412 {
413   assert(row < size() && "SiconosVector::setValue(index, value) : Index out of range");
414   if(_dense)
415     (*vect.Dense)(row) = value ;
416   else
417     (*vect.Sparse)(row) = value;
418 }
419 
operator ()(unsigned int row)420 double& SiconosVector::operator()(unsigned int row)
421 {
422   assert(row < size() && "SiconosVector::operator ( index ): Index out of range");
423 
424   if(_dense)
425     return (*vect.Dense)(row);
426   else
427     return (*vect.Sparse)(row).ref();
428 }
429 
operator ()(unsigned int row) const430 double SiconosVector::operator()(unsigned int row) const
431 {
432   assert(row < size() && "SiconosVector::operator ( index ): Index out of range");
433 
434   if(_dense)
435     return (*vect.Dense)(row);
436   else
437     return ((*vect.Sparse)(row)).ref();
438 }
439 
440 //============================================
441 // Access (get or set) to blocks of elements
442 //============================================
443 
setBlock(unsigned int index,const SiconosVector & vIn)444 void SiconosVector::setBlock(unsigned int index, const SiconosVector& vIn)
445 {
446   // Set current vector elements, starting from position "index", to the values of vector vIn
447 
448   // Exceptions ...
449   assert(&vIn != this && "SiconosVector::this->setBlock(pos,vIn): vIn = this.");
450 
451   assert(index < size() && "SiconosVector::setBlock : invalid ranges");
452 
453   auto end = vIn.size() + index;
454   assert(end <= size() && "SiconosVector::setBlock : invalid ranges");
455 
456   assert(vIn.num() == num() && "SiconosVector::setBlock: inconsistent types.");
457 
458   if(_dense)
459     noalias(ublas::subrange(*vect.Dense, index, end)) = *vIn.dense();
460   else
461     noalias(ublas::subrange(*vect.Sparse, index, end)) = *vIn.sparse();
462 }
463 
toBlock(SiconosVector & vOut,unsigned int sizeB,unsigned int startIn,unsigned int startOut) const464 void SiconosVector::toBlock(SiconosVector& vOut, unsigned int sizeB, unsigned int startIn, unsigned int startOut) const
465 {
466   // To copy a subBlock of the vector (from position startIn to startIn+sizeB) into vOut (from pos. startOut to startOut+sizeB).
467   // Check dim ...
468   assert(startIn < size() && "vector toBlock(v1,v2,...): start position in input vector is out of range.");
469 
470   assert(startOut < vOut.size() && "vector toBlock(v1,v2,...): start position in output vector is out of range.");
471 
472   assert(startIn + sizeB <= size() && "vector toBlock(v1,v2,...): end position in input vector is out of range.");
473   assert(startOut + sizeB <= vOut.size() && "vector toBlock(v1,v2,...): end position in output vector is out of range.");
474 
475   unsigned int endOut = startOut + sizeB;
476   Siconos::UBLAS_TYPE numIn = num();
477   Siconos::UBLAS_TYPE numOut = vOut.num();
478 
479   if(numIn == numOut)
480   {
481     if(numIn == Siconos::DENSE)
482       noalias(ublas::subrange(*vOut.dense(), startOut, endOut)) = ublas::subrange(*vect.Dense, startIn, startIn + sizeB);
483     else // if(numIn == Siconos::SPARSE)// vIn / vOut are Sparse
484       noalias(ublas::subrange(*vOut.sparse(), startOut, endOut)) = ublas::subrange(*vect.Sparse, startIn, startIn + sizeB);
485   }
486   else // vIn and vout of different types ...
487   {
488     if(numIn == Siconos::DENSE)  // vIn Dense
489       noalias(ublas::subrange(*vOut.sparse(), startOut, endOut)) = ublas::subrange(*vect.Dense, startIn, startIn + sizeB);
490     else // if(numIn == Siconos::SPARSE)// vIn Sparse
491       noalias(ublas::subrange(*vOut.dense(), startOut, endOut)) = ublas::subrange(*vect.Sparse, startIn, startIn + sizeB);
492   }
493 }
494 
addBlock(unsigned int index,const SiconosVector & vIn)495 void SiconosVector::addBlock(unsigned int index, const SiconosVector& vIn)
496 {
497   // Add vIn to the current vector, starting from position "index".
498 
499   if(&vIn == this)
500     THROW_EXCEPTION("try to add a vector to itself.");
501 
502   unsigned int end = vIn.size();
503   if((index + end) > size())
504     THROW_EXCEPTION("invalid ranges");
505 
506   Siconos::UBLAS_TYPE numVin = vIn.num();
507 
508   if(numVin != num())
509     THROW_EXCEPTION("inconsistent types.");
510 
511   if(_dense)
512     noalias(ublas::subrange(*vect.Dense, index, index + end)) += *vIn.dense();
513   else
514     noalias(ublas::subrange(*vect.Sparse, index, index + end)) += *vIn.sparse();
515 }
516 
subBlock(unsigned int index,const SiconosVector & vIn)517 void SiconosVector::subBlock(unsigned int index, const SiconosVector& vIn)
518 {
519   // Add vIn from the current vector, starting from position "index".
520 
521   unsigned int end = vIn.size();
522   if((index + end) > size())
523     THROW_EXCEPTION("invalid ranges");
524 
525   Siconos::UBLAS_TYPE numVin = vIn.num();
526   if(numVin != num())
527     THROW_EXCEPTION("inconsistent types.");
528 
529   if(_dense)
530     noalias(ublas::subrange(*vect.Dense, index, index + end)) -= *vIn.dense();
531   else
532     noalias(ublas::subrange(*vect.Sparse, index, index + end)) -= *vIn.sparse();
533 }
534 
535 //===============
536 //  Assignment
537 //===============
538 
operator =(const SiconosVector & vIn)539 SiconosVector& SiconosVector::operator = (const SiconosVector& vIn)
540 {
541   if(&vIn == this) return *this;  // auto-assignment.
542 
543   assert(size() == vIn.size() && "SiconosVector::operator = failed: inconsistent sizes.");
544 
545   Siconos::UBLAS_TYPE vInNum = vIn.num();
546   {
547     switch(num())
548     {
549     case Siconos::DENSE:
550       switch(vInNum)
551       {
552       case Siconos::DENSE:
553         //siconosBindings::copy(*vIn.dense(),*vect.Dense);
554         noalias(*vect.Dense) = *vIn.dense();
555         break;
556       case Siconos::SPARSE:
557         noalias(*vect.Dense) = *vIn.sparse();
558         break;
559       default:
560         THROW_EXCEPTION("invalid type");
561         break;
562       }
563       break;
564     case Siconos::SPARSE:
565       if (vInNum == Siconos::DENSE)
566         noalias(*vect.Sparse) = *vIn.dense();
567       else if(vInNum == Siconos::SPARSE)
568         noalias(*vect.Sparse) = *vIn.sparse();
569       else
570         THROW_EXCEPTION("invalid type");
571       break;
572     default:
573         THROW_EXCEPTION("invalid type");
574       break;
575     }
576   }
577   return *this;
578 }
579 
operator =(const BlockVector & vIn)580 SiconosVector& SiconosVector::operator = (const BlockVector& vIn)
581 {
582   VectorOfVectors::const_iterator it;
583   unsigned int pos = 0;
584   for(it = vIn.begin(); it != vIn.end(); ++it)
585   {
586     setBlock(pos, **it);
587     pos += (*it)->size();
588   }
589   return *this;
590 }
591 
592 
operator =(const DenseVect & d)593 SiconosVector& SiconosVector::operator = (const DenseVect& d)
594 {
595   if(!_dense)
596     THROW_EXCEPTION("the current vector is not dense.");
597   if(d.size() != size())
598     THROW_EXCEPTION("inconsistent size.");
599 
600   siconosBindings::copy(d, *vect.Dense);
601   return *this;
602 }
603 
operator =(const SparseVect & sp)604 SiconosVector& SiconosVector::operator = (const SparseVect& sp)
605 {
606   if(_dense)
607     THROW_EXCEPTION("current vector is not sparse.");
608   if(sp.size() != size())
609     THROW_EXCEPTION("inconsistent size.");
610 
611   noalias(*vect.Sparse) = sp;
612 
613   return *this;
614 }
615 
operator =(const double * d)616 SiconosVector& SiconosVector::operator = (const double* d)
617 {
618   assert(_dense && "SiconosVector::operator = double* : forbidden: the current vector is not dense.");
619 
620   siconosBindings::detail::copy(vect.Dense->size(), d, 1, getArray(), 1);
621   return *this;
622 }
623 
copyData(double * data) const624 unsigned SiconosVector::copyData(double* data) const
625 {
626   assert(_dense && "SiconosVector::copyData : forbidden: the current vector is not dense.");
627 
628   unsigned size = vect.Dense->size();
629   siconosBindings::detail::copy(vect.Dense->size(), getArray(), 1, data, 1);
630   return size;
631 }
632 
633 
634 //=================================
635 // Op. and assignment (+=, -= ... )
636 //=================================
637 
operator +=(const SiconosVector & vIn)638 SiconosVector& SiconosVector::operator += (const SiconosVector& vIn)
639 {
640   if(&vIn == this)  // alias
641   {
642     // Note: using this *= 2.0 is much more time-consuming.
643     switch(num())
644     {
645     case Siconos::DENSE:
646       *vect.Dense += *vect.Dense;
647       break;
648     case Siconos::SPARSE:
649       *vect.Sparse += *vect.Sparse;
650       break;
651     default:
652       THROW_EXCEPTION("invalid type.");
653       break;
654     }
655     return *this;
656   }
657 
658   Siconos::UBLAS_TYPE vInNum = vIn.num();
659   {
660     switch(num())
661     {
662     case Siconos::DENSE:
663       switch(vInNum)
664       {
665       case Siconos::DENSE:
666         noalias(*vect.Dense) += *vIn.dense();
667         break;
668       case Siconos::SPARSE:
669         noalias(*vect.Dense) += *vIn.sparse();
670         break;
671       default:
672         THROW_EXCEPTION("invalid type");
673         break;
674       }
675       break;
676     case Siconos::SPARSE:
677       if(vInNum == Siconos::SPARSE)
678         noalias(*vect.Sparse) += *vIn.sparse();
679       else
680         THROW_EXCEPTION("can not add a dense to a sparse.");
681       break;
682     default:
683       THROW_EXCEPTION("invalid type.");
684       break;
685     }
686   }
687   return *this;
688 }
operator +=(const BlockVector & vIn)689 SiconosVector& SiconosVector::operator += (const BlockVector& vIn)
690 {
691   VectorOfVectors::const_iterator it;
692   unsigned int pos = 0;
693   for(it = vIn.begin(); it != vIn.end(); ++it)
694   {
695     addBlock(pos, **it);
696     pos += (*it)->size();
697   }
698   return *this;
699 }
700 
operator -=(const SiconosVector & vIn)701 SiconosVector& SiconosVector::operator -= (const SiconosVector& vIn)
702 {
703   if(&vIn == this)
704   {
705     this->zero();
706     return *this;
707   }
708 
709   Siconos::UBLAS_TYPE vInNum = vIn.num();
710   {
711     switch(num())
712     {
713     case Siconos::DENSE:
714       switch(vInNum)
715       {
716       case Siconos::DENSE:
717         noalias(*vect.Dense) -= *vIn.dense();
718         break;
719       case Siconos::SPARSE:
720         noalias(*vect.Dense) -= *vIn.sparse();
721         break;
722       default:
723         THROW_EXCEPTION("invalid type.");
724         break;
725       }
726       break;
727     case Siconos::SPARSE:
728       if(vInNum == Siconos::SPARSE)
729         noalias(*vect.Sparse) -= *vIn.sparse();
730       else
731         THROW_EXCEPTION("can not sub a dense to a sparse.");
732       break;
733     default:
734       THROW_EXCEPTION("invalid type.");
735       break;
736     }
737   }
738   return *this;
739 }
740 
operator -=(const BlockVector & vIn)741 SiconosVector& SiconosVector::operator -= (const BlockVector& vIn)
742 {
743   VectorOfVectors::const_iterator it;
744   unsigned int pos = 0;
745   for(it = vIn.begin(); it != vIn.end(); ++it)
746   {
747     subBlock(pos, **it);
748     pos += (*it)->size();
749   }
750   return *this;
751 }
752 
753 
754 //===============
755 // Comparison
756 //===============
757 
operator ==(const SiconosVector & m,const SiconosVector & x)758 bool operator == (const SiconosVector &m, const SiconosVector &x)
759 {
760   DEBUG_PRINTF("norm = %12.8e \n", (m - x).normInf());
761   DEBUG_PRINTF("std::numeric_limits<double>::epsilon() = %12.8e \n", std::numeric_limits<double>::epsilon());
762   DEBUG_EXPR(std::cout << std::boolalpha << ((m - x).normInf() <= std::numeric_limits<double>::epsilon()) <<std::endl;);
763   double atol = 1e-14;
764   double rtol = std::numeric_limits<double>::epsilon();
765   return ((m - x).normInf() <= atol + rtol * x.normInf()) ;
766 }
767 
768 //==================
769 // y = scalar * x
770 //==================
771 
operator *(const SiconosVector & m,double d)772 SiconosVector operator * (const  SiconosVector&m, double d)
773 {
774   Siconos::UBLAS_TYPE numM = m.num();
775 
776   if(numM == Siconos::DENSE)
777   {
778     // Copy m into p and call siconosBindings::scal(d,p), p = d*p.
779     DenseVect p = *m.dense();
780     siconosBindings::scal(d, p);
781     return p;
782   }
783   else// if(numM==Siconos::SPARSE)
784   {
785     return (SparseVect)(*m.sparse() * d);
786   }
787 }
788 
operator *(double d,const SiconosVector & m)789 SiconosVector operator * (double d, const  SiconosVector&m)
790 {
791   Siconos::UBLAS_TYPE numM = m.num();
792 
793   if(numM == Siconos::DENSE)
794   {
795     // Copy m into p and call siconosBindings::scal(d,p), p = d*p.
796     DenseVect p = *m.dense();
797     siconosBindings::scal(d, p);
798     return p;
799   }
800   else// if(numM==Siconos::SPARSE)
801   {
802     return (SparseVect)(*m.sparse() * d);
803   }
804 }
805 
operator /(const SiconosVector & m,double d)806 SiconosVector operator / (const SiconosVector &m, double d)
807 {
808   Siconos::UBLAS_TYPE numM = m.num();
809 
810   if(numM == Siconos::DENSE)
811   {
812     DenseVect p = *m.dense();
813     siconosBindings::scal((1.0 / d), p);
814     return p;
815   }
816 
817   else// if(numM==Siconos::SPARSE){
818     return (SparseVect)(*m.sparse() / d);
819 }
820 
821 //====================
822 //  Vectors addition
823 //====================
824 
operator +(const SiconosVector & x,const SiconosVector & y)825 SiconosVector operator + (const  SiconosVector& x, const  SiconosVector& y)
826 {
827   if(x.size() != y.size())
828     THROW_EXCEPTION("inconsistent sizes");
829 
830   Siconos::UBLAS_TYPE numX = x.num();
831   Siconos::UBLAS_TYPE numY = y.num();
832 
833   if(numX == numY)  // x, y SiconosVector of the same type
834   {
835     if(numX == Siconos::DENSE)
836     {
837       //    siconosBindings::xpy(*x.dense(),p);
838       //    return p;
839       return (DenseVect)(*x.dense() + *y.dense());
840     }
841     else
842       return (SparseVect)(*x.sparse() + *y.sparse());
843   }
844 
845   else // x, y SiconosVector with y and x of different types
846   {
847     if(numX == Siconos::DENSE)
848       return (DenseVect)(*x.dense() + *y.sparse());
849     else
850       return (DenseVect)(*x.sparse() + *y.dense());
851   }
852 
853 }
854 
add(const SiconosVector & x,const SiconosVector & y,SiconosVector & z)855 void add(const SiconosVector& x, const SiconosVector& y, SiconosVector& z)
856 {
857   // Computes z = x + y in an "optimized" way (in comparison with operator +)
858 
859   if(x.size() != y.size() || x.size() != z.size())
860     THROW_EXCEPTION("inconsistent sizes");
861 
862   Siconos::UBLAS_TYPE numX = x.num();
863   Siconos::UBLAS_TYPE numY = y.num();
864   Siconos::UBLAS_TYPE numZ = z.num();
865 
866   if(&z == &x)  // x, and z are the same object.
867   {
868     z += y;
869   }
870   else if(&z == &y)  // y and z are the same object, different from x
871   {
872     z += x;
873   }
874   else // No common memory between x,y and z
875   {
876 
877     if(numZ != 0)  // z is a SiconosVector
878     {
879       if(numX == numY && numX != 0)  // x, y SiconosVector of the same type
880       {
881         if(numX == Siconos::DENSE)
882         {
883           if(numZ != Siconos::DENSE)
884             THROW_EXCEPTION("Addition of two dense vectors into a sparse.");
885           noalias(*z.dense()) = *x.dense() + *y.dense() ;
886         }
887         else
888         {
889           if(numZ == Siconos::DENSE)
890             noalias(*z.dense()) = *x.sparse() + *y.sparse() ;
891           else
892             noalias(*z.sparse()) = *x.sparse() + *y.sparse() ;
893         }
894       }
895       else if(numX != 0 && numY != 0)  // x and y of different types => z must be dense.
896       {
897         if(numZ != Siconos::DENSE)
898           THROW_EXCEPTION("z can not be sparse.");
899         if(numX == Siconos::DENSE)
900           noalias(*z.dense()) = *x.dense() + *y.sparse();
901         else
902           noalias(*z.dense()) = *x.sparse() + *y.dense() ;
903       }
904     }
905   }
906 }
907 
908 //======================
909 //  Vectors subtraction
910 //======================
911 
operator -(const SiconosVector & x,const SiconosVector & y)912 SiconosVector operator - (const  SiconosVector& x, const  SiconosVector& y)
913 {
914   if(x.size() != y.size())
915     THROW_EXCEPTION("inconsistent sizes");
916 
917   Siconos::UBLAS_TYPE numX = x.num();
918   Siconos::UBLAS_TYPE numY = y.num();
919 
920   if(numX == numY)  // x, y SiconosVector of the same type
921   {
922     if(numX == Siconos::DENSE)
923     {
924       //    siconosBindings::xpy(*x.dense(),p);
925       //    return p;
926       return (DenseVect)(*x.dense() - *y.dense());
927     }
928     else
929       return (SparseVect)(*x.sparse() - *y.sparse());
930   }
931   else // x, y SiconosVector with y and x of different types
932   {
933     if(numX == Siconos::DENSE)
934       return (DenseVect)(*x.dense() - *y.sparse());
935     else
936       return (DenseVect)(*x.sparse() - *y.dense());
937   }
938 }
939 
sub(const SiconosVector & x,const SiconosVector & y,SiconosVector & z)940 void sub(const SiconosVector& x, const SiconosVector& y, SiconosVector& z)
941 {
942   // Computes z = x - y in an "optimized" way (in comparison with operator +)
943 
944   if(x.size() != y.size() || x.size() != z.size())
945     THROW_EXCEPTION("inconsistent sizes");
946 
947   Siconos::UBLAS_TYPE numX = x.num();
948   Siconos::UBLAS_TYPE numY = y.num();
949   Siconos::UBLAS_TYPE numZ = z.num();
950 
951   if(&z == &x)  // x and z are the same object.
952   {
953     z -= y;
954   }
955   else if(&z == &y)  // y and z are the same object
956   {
957     {
958       if(numX == Siconos::DENSE)
959       {
960         if(numZ != Siconos::DENSE)
961           THROW_EXCEPTION("Subtraction of two dense vectors into a sparse.");
962         *z.dense() = *x.dense() - *y.dense() ;
963       }
964       else
965       {
966         if(numZ == Siconos::DENSE)
967           *z.dense() = *x.sparse() - *y.dense() ;
968         else
969           *z.sparse() = *x.sparse() - *y.sparse() ;
970       }
971     }
972   }
973   else // No common memory between x or y and z
974   {
975 
976     if(numZ != 0)  // z is a SiconosVector
977     {
978       if(numX == numY && numX != 0)  // x, y SiconosVector of the same type
979       {
980         if(numX == Siconos::DENSE)
981         {
982           if(numZ != Siconos::DENSE)
983             THROW_EXCEPTION("Addition of two dense vectors into a sparse.");
984           noalias(*z.dense()) = *x.dense() - *y.dense() ;
985         }
986         else
987         {
988           if(numZ == Siconos::DENSE)
989             noalias(*z.dense()) = *x.sparse() - *y.sparse() ;
990           else
991             noalias(*z.sparse()) = *x.sparse() - *y.sparse() ;
992         }
993       }
994       else if(numX != 0 && numY != 0)  // x and y of different types => z must be dense.
995       {
996         if(numZ != Siconos::DENSE)
997           THROW_EXCEPTION("z can not be sparse.");
998         if(numX == Siconos::DENSE)
999           noalias(*z.dense()) = *x.dense() - *y.sparse();
1000         else
1001           noalias(*z.dense()) = *x.sparse() - *y.dense() ;
1002       }
1003     }
1004   }
1005 }
1006 
axpby(double a,const SiconosVector & x,double b,SiconosVector & y)1007 void axpby(double a, const SiconosVector& x, double b, SiconosVector& y)
1008 {
1009   // Computes y = ax + by
1010 
1011   if(x.size() != y.size())
1012     THROW_EXCEPTION("inconsistent sizes");
1013 
1014   Siconos::UBLAS_TYPE numX = x.num();
1015   Siconos::UBLAS_TYPE numY = y.num();
1016 
1017   if(numX == numY)  // x and y of the same type
1018   {
1019     if(numX == Siconos::DENSE)  // all dense
1020     {
1021       siconosBindings::scal(b, *y.dense());
1022       siconosBindings::axpy(a, *x.dense(), *y.dense());
1023     }
1024     else // all sparse
1025     {
1026       *y.sparse() *= b;
1027       if(&y != &x)
1028         noalias(*y.sparse()) += a**x.sparse();
1029       else
1030         *y.sparse() += a**x.sparse();
1031     }
1032   }
1033 
1034   else // x and y of different types
1035   {
1036     y *= b;
1037     {
1038       if(numX == Siconos::DENSE)
1039         *y.sparse() += a**x.dense();
1040       else
1041         *y.dense() +=  a**x.sparse();
1042     }
1043   }
1044 }
1045 
axpy(double a,const SiconosVector & x,SiconosVector & y)1046 void axpy(double a, const SiconosVector& x, SiconosVector& y)
1047 {
1048   // Computes y = ax + y
1049 
1050   if(x.size() != y.size())
1051     THROW_EXCEPTION("nconsistent sizes");
1052 
1053   Siconos::UBLAS_TYPE numX = x.num();
1054   Siconos::UBLAS_TYPE numY = y.num();
1055 
1056   if(numX == numY)  // x and y of the same type
1057   {
1058     if(numX == Siconos::DENSE)  // all dense
1059       siconosBindings::axpy(a, *x.dense(), *y.dense());
1060 
1061     else // all sparse
1062     {
1063       if(&y != &x)
1064         noalias(*y.sparse()) += a**x.sparse();
1065       else
1066         *y.sparse() += a**x.sparse();
1067     }
1068   }
1069 
1070   else // x and y of different types
1071   {
1072     {
1073       if(numX == Siconos::DENSE)
1074         *y.sparse() += a**x.dense();
1075       else
1076         *y.dense() +=  a**x.sparse();
1077     }
1078   }
1079 }
1080 
inner_prod(const SiconosVector & x,const SiconosVector & m)1081 double inner_prod(const SiconosVector &x, const SiconosVector &m)
1082 {
1083   if(x.size() != m.size())
1084     THROW_EXCEPTION("inconsistent sizes");
1085 
1086   Siconos::UBLAS_TYPE numM = m.num();
1087   Siconos::UBLAS_TYPE numX = x.num();
1088 
1089   if(numX == numM)
1090   {
1091     if(numM == Siconos::DENSE)
1092       return siconosBindings::dot(*x.dense(), *m.dense());
1093     else
1094       return inner_prod(*x.sparse(), *m.sparse());
1095   }
1096   else if(numM == Siconos::DENSE)
1097     return inner_prod(*x.sparse(), *m.dense());
1098   else
1099     return inner_prod(*x.dense(), *m.sparse());
1100 }
1101 
1102 // outer_prod(v,w) = trans(v)*w
outer_prod(const SiconosVector & x,const SiconosVector & m)1103 SimpleMatrix outer_prod(const SiconosVector &x, const SiconosVector& m)
1104 {
1105   Siconos::UBLAS_TYPE numM = m.num();
1106   Siconos::UBLAS_TYPE numX = x.num();
1107 
1108   if(numM == Siconos::DENSE)
1109   {
1110     if(numX == Siconos::DENSE)
1111       return (DenseMat)(outer_prod(*x.dense(), *m.dense()));
1112 
1113     else// if(numX == Siconos::SPARSE)
1114       return (DenseMat)(outer_prod(*x.sparse(), *m.dense()));
1115   }
1116   else // if(numM == Siconos::SPARSE)
1117   {
1118     if(numX == Siconos::DENSE)
1119       return (DenseMat)(outer_prod(*x.dense(), *m.sparse()));
1120 
1121     else //if(numX == Siconos::SPARSE)
1122       return (DenseMat)(outer_prod(*x.sparse(), *m.sparse()));
1123   }
1124 }
1125 
scal(double a,const SiconosVector & x,SiconosVector & y,bool init)1126 void scal(double a, const SiconosVector & x, SiconosVector & y, bool init)
1127 {
1128   // To compute y = a *x (init = true) or y += a*x (init = false)
1129 
1130   if(&x == &y)
1131   {
1132     if(init)
1133       y *= a;
1134     else
1135     {
1136       y *= (1.0 + a);
1137     }
1138   }
1139   else
1140   {
1141     unsigned int sizeX = x.size();
1142     unsigned int sizeY = y.size();
1143 
1144     if(sizeX != sizeY)
1145       THROW_EXCEPTION("sizes are not consistent.");
1146 
1147     Siconos::UBLAS_TYPE numY = y.num();
1148     Siconos::UBLAS_TYPE numX = x.num();
1149     if(numX == numY)
1150     {
1151 
1152       if(numX == Siconos::DENSE)  // ie if both are Dense
1153       {
1154         if(init)
1155           //siconosBindings::axpby(a,*x.dense(),0.0,*y.dense());
1156           noalias(*y.dense()) = a * *x.dense();
1157         else
1158           noalias(*y.dense()) += a * *x.dense();
1159       }
1160       else  // if both are sparse
1161       {
1162         if(init)
1163           noalias(*y.sparse()) = a**x.sparse();
1164         else
1165           noalias(*y.sparse()) += a**x.sparse();
1166       }
1167     }
1168     else
1169     {
1170       if(numY == 0 || numX == 0)  // if y or x is block
1171       {
1172         if(init)
1173         {
1174           y = x;
1175           y *= a;
1176         }
1177         else
1178         {
1179           SiconosVector tmp(x);
1180           tmp *= a;
1181           y += tmp;
1182         }
1183       }
1184       else
1185       {
1186         if(numY == Siconos::DENSE)  // if y is dense
1187         {
1188           if(init)
1189             noalias(*y.dense()) = a**x.sparse();
1190           else
1191             noalias(*y.dense()) += a**x.sparse();
1192 
1193         }
1194         else
1195           THROW_EXCEPTION("Operation not allowed on non-dense vector.");
1196       }
1197     }
1198   }
1199 }
1200 
subscal(double a,const SiconosVector & x,SiconosVector & y,const Index & coord,bool init)1201 void subscal(double a, const SiconosVector & x, SiconosVector & y, const Index& coord, bool init)
1202 {
1203   // To compute sub_y = a *sub_x (init = true) or sub_y += a*sub_x (init = false)
1204   // Coord  = [r0x r1x r0y r1y];
1205   // subX is the sub-vector of x, for row numbers between r0x and r1x-1.
1206   // The same for y with riy.
1207 
1208 
1209   // Check dimensions
1210   unsigned int dimX = coord[1] - coord[0];
1211   unsigned int dimY = coord[3] - coord[2];
1212   if(dimY != dimX)
1213     THROW_EXCEPTION("inconsistent sizes between (sub)x and (sub)y.");
1214   if(dimY > y.size() || dimX > x.size())
1215     THROW_EXCEPTION("input index too large.");
1216 
1217   Siconos::UBLAS_TYPE numY = y.num();
1218   Siconos::UBLAS_TYPE numX = x.num();
1219 
1220   if(&x == &y)  // if x and y are the same object
1221   {
1222     if(numX == Siconos::DENSE)  // Dense
1223     {
1224       ublas::vector_range<DenseVect> subY(*y.dense(), ublas::range(coord[2], coord[3]));
1225       if(coord[0] == coord[2])
1226       {
1227         if(init)
1228           subY *= a;
1229         else
1230           subY *= (1.0 + a);
1231       }
1232       else
1233       {
1234         ublas::vector_range<DenseVect> subX(*x.dense(), ublas::range(coord[0], coord[1]));
1235         if(init)
1236           subY = a * subX;
1237         else
1238           subY += a * subX;
1239       }
1240     }
1241     else //if (numX == Siconos::SPARSE) // Sparse
1242     {
1243       ublas::vector_range<SparseVect> subY(*y.sparse(), ublas::range(coord[2], coord[3]));
1244       if(coord[0] == coord[2])
1245       {
1246         if(init)
1247           subY *= a;
1248         else
1249           subY *= (1.0 + a);
1250       }
1251       else
1252       {
1253         ublas::vector_range<SparseVect> subX(*x.sparse(), ublas::range(coord[0], coord[1]));
1254         if(init)
1255           subY = a * subX;
1256         else
1257           subY += a * subX;
1258       }
1259     }
1260   }
1261   else
1262   {
1263     if(numX == numY)
1264     {
1265       if(numX == Siconos::DENSE)  // ie if both are Dense
1266       {
1267         ublas::vector_range<DenseVect> subX(*x.dense(), ublas::range(coord[0], coord[1]));
1268         ublas::vector_range<DenseVect> subY(*y.dense(), ublas::range(coord[2], coord[3]));
1269 
1270         if(init)
1271           noalias(subY) = a * subX;
1272         else
1273           noalias(subY) += a * subX;
1274       }
1275       else  // if both are sparse
1276       {
1277         ublas::vector_range<SparseVect> subX(*x.sparse(), ublas::range(coord[0], coord[1]));
1278         ublas::vector_range<SparseVect> subY(*y.sparse(), ublas::range(coord[2], coord[3]));
1279 
1280         if(init)
1281           noalias(subY) = a * subX;
1282         else
1283           noalias(subY) += a * subX;
1284       }
1285     }
1286     else // x and y of different types ...
1287     {
1288       if(numY == Siconos::DENSE)  // y dense, x sparse
1289       {
1290         ublas::vector_range<DenseVect> subY(*y.dense(), ublas::range(coord[2], coord[3]));
1291         ublas::vector_range<SparseVect> subX(*x.sparse(), ublas::range(coord[0], coord[1]));
1292 
1293         if(init)
1294           noalias(subY) = a * subX;
1295         else
1296           noalias(subY) += a * subX;
1297       }
1298       else // y sparse, x dense => fails
1299         THROW_EXCEPTION("Operation not allowed (y sparse, x dense).");
1300     }
1301   }
1302 }
cross_product(const SiconosVector & V1,const SiconosVector & V2,SiconosVector & VOUT)1303 void cross_product(const SiconosVector& V1, const SiconosVector& V2, SiconosVector& VOUT)
1304 {
1305   if(V1.size() != 3 || V2.size() != 3 || VOUT.size() != 3)
1306     THROW_EXCEPTION("allowed only with dim 3.");
1307 
1308   double aux = V1.getValue(1) * V2.getValue(2) - V1.getValue(2) * V2.getValue(1);
1309   VOUT.setValue(0, aux);
1310 
1311   aux = V1.getValue(2) * V2.getValue(0) - V1.getValue(0) * V2.getValue(2);
1312   VOUT.setValue(1, aux);
1313 
1314   aux = V1.getValue(0) * V2.getValue(1) - V1.getValue(1) * V2.getValue(0);
1315   VOUT.setValue(2, aux);
1316 
1317 }
1318 
1319 //
1320 
abs_wise(const SiconosVector & V,SiconosVector & Vabs)1321 void abs_wise(const SiconosVector& V, SiconosVector& Vabs)
1322 {
1323   for(unsigned int it = 0; it < V.size(); ++it)
1324   {
1325     Vabs.setValue(it, std::abs(V.getValue(it)));
1326   };
1327 }
1328 
1329 //
1330 
getMax(const SiconosVector & V,double & maxvalue,unsigned int & idmax)1331 void getMax(const SiconosVector& V, double& maxvalue, unsigned int& idmax)
1332 {
1333   maxvalue = V.getValue(0);
1334   idmax = 0;
1335   for(unsigned int it = 1; it < V.size(); ++it)
1336   {
1337     if(V.getValue(it) > maxvalue)
1338     {
1339       maxvalue = V.getValue(it);
1340       idmax = it;
1341     };
1342   };
1343 }
1344 
1345 //
1346 
getMin(const SiconosVector & V,double & minvalue,unsigned int & idmin)1347 void getMin(const SiconosVector& V, double& minvalue, unsigned int& idmin)
1348 {
1349   minvalue = V.getValue(0);
1350   idmin = 0;
1351   for(unsigned int it = 1; it < V.size(); ++it)
1352   {
1353     if(V.getValue(it) < minvalue)
1354     {
1355       minvalue = V.getValue(it);
1356       idmin = it;
1357     };
1358   };
1359 }
1360 
1361 
1362 // struct exp_op
1363 // {
1364 //   double operator()(double d) const
1365 //   {
1366 //     return std::exp(d);
1367 //   }
1368 // };
1369 
setBlock(const SiconosVector & vIn,SP::SiconosVector vOut,unsigned int sizeB,unsigned int startIn,unsigned int startOut)1370 void setBlock(const SiconosVector& vIn, SP::SiconosVector vOut, unsigned int sizeB,
1371               unsigned int startIn, unsigned int startOut)
1372 {
1373   unsigned int endOut = startOut + sizeB;
1374   Siconos::UBLAS_TYPE numIn = vIn.num();
1375   Siconos::UBLAS_TYPE numOut = vOut->num();
1376   assert(vOut->size() >= endOut && "The output vector is too small");
1377   if(numIn == numOut)
1378   {
1379     if(numIn == Siconos::DENSE)  // vIn / vOut are Dense
1380       noalias(ublas::subrange(*vOut->dense(), startOut, endOut)) = ublas::subrange(*vIn.dense(), startIn, startIn + sizeB);
1381     else // if(numIn == Siconos::SPARSE)// vIn / vOut are Sparse
1382       noalias(ublas::subrange(*vOut->sparse(), startOut, endOut)) = ublas::subrange(*vIn.sparse(), startIn, startIn + sizeB);
1383   }
1384   else // vIn and vout of different types ...
1385   {
1386     if(numIn == Siconos::DENSE)  // vIn Dense
1387       noalias(ublas::subrange(*vOut->sparse(), startOut, endOut)) = ublas::subrange(*vIn.dense(), startIn, startIn + sizeB);
1388     else // if(numIn == Siconos::SPARSE)// vIn Sparse
1389       noalias(ublas::subrange(*vOut->dense(), startOut, endOut)) = ublas::subrange(*vIn.sparse(), startIn, startIn + sizeB);
1390   }
1391 }
1392 
size(void) const1393 unsigned int SiconosVector::size(void) const
1394 {
1395   if(!_dense)
1396   {
1397     return (vect.Sparse->size());
1398   }
1399   else
1400   {
1401     return (vect.Dense->size());
1402   }
1403 }
1404 
operator *=(SiconosVector & v,const double & s)1405 SiconosVector& operator *= (SiconosVector& v, const double& s)
1406 {
1407   if(v._dense)
1408     *v.dense() *= s;
1409   else
1410     *v.sparse() *= s;
1411   return v;
1412 }
1413 
1414 
operator /=(SiconosVector & v,const double & s)1415 SiconosVector& operator /= (SiconosVector& v, const double& s)
1416 {
1417   if(v._dense)
1418     *v.dense() /= s;
1419   else
1420     *v.sparse() /= s;
1421   return v;
1422 }
1423 
begin()1424 SiconosVector::iterator SiconosVector::begin()
1425 {
1426   return SiconosVector::iterator(*this, 0);
1427 }
1428 
begin() const1429 SiconosVector::const_iterator SiconosVector::begin() const
1430 {
1431   return SiconosVector::const_iterator(*this, 0);
1432 }
1433 
end()1434 SiconosVector::iterator SiconosVector::end()
1435 {
1436   return SiconosVector::iterator(*this, size());
1437 }
1438 
end() const1439 SiconosVector::const_iterator SiconosVector::end() const
1440 {
1441   return SiconosVector::const_iterator(*this, size());
1442 }
1443 
operator std::vector<double>()1444 SiconosVector::operator std::vector<double>()
1445 {
1446   std::vector<double> v(size());
1447   std::copy(begin(), end(), v.begin());
1448   return v;
1449 }
1450