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