1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SoPlex is distributed under the terms of the ZIB Academic Licence.       */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SoPlex; see the file COPYING. If not email to soplex@zib.de.  */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	
17   	/**@file  ssvectorbase.h
18   	 * @brief Semi sparse vector.
19   	 */
20   	#ifndef _SSVECTORBASE_H_
21   	#define _SSVECTORBASE_H_
22   	
23   	#include <assert.h>
24   	
25   	#include "soplex/spxdefines.h"
26   	#include "soplex/vectorbase.h"
27   	#include "soplex/idxset.h"
28   	#include "soplex/spxalloc.h"
29   	#include "soplex/timer.h"
30   	#include "soplex/stablesum.h"
31   	
32   	namespace soplex
33   	{
34   	template < class R > class SVectorBase;
35   	template < class R > class SVSetBase;
36   	
37   	/**@brief   Semi sparse vector.
38   	 * @ingroup Algebra
39   	 *
40   	 *  This class implements semi-sparse vectors.  Such are #VectorBase%s where the indices of its nonzero elements can be
41   	 *  stored in an extra IdxSet.  Only elements with absolute value > #epsilon are considered to be nonzero.  Since really
42   	 *  storing the nonzeros is not always convenient, an SSVectorBase provides two different stati: setup and not setup.
43   	 *  An SSVectorBase being setup means that the nonzero indices are available, otherwise an SSVectorBase is just an
44   	 *  ordinary VectorBase with an empty IdxSet.  Note that due to arithmetic operation, zeros can slip in, i.e., it is
45   	 *  only guaranteed that at least every non-zero is in the IdxSet.
46   	 */
47   	template < class R >
48   	class SSVectorBase : public VectorBase<R>, protected IdxSet
49   	{
50   	private:
51   	
52   	   friend class VectorBase<R>;
53   	   template < class S > friend class DSVectorBase;
54   	
55   	   // ------------------------------------------------------------------------------------------------------------------
56   	   /**@name Data */
57   	   ///@{
58   	
59   	   /// Is the SSVectorBase set up?
60   	   bool setupStatus;
61   	
62   	   /// A value x with |x| < epsilon is considered zero.
63   	   R epsilon;
64   	
65   	   /// Allocates enough space to accommodate \p newmax values.
66   	   void setMax(int newmax)
67   	   {
68   	      assert(idx != 0);
69   	      assert(newmax != 0);
70   	      assert(newmax >= IdxSet::size());
71   	
72   	      len = newmax;
73   	      spx_realloc(idx, len);
74   	   }
75   	
76   	   ///@}
77   	
78   	public:
79   	
80   	   // ------------------------------------------------------------------------------------------------------------------
81   	   /**@name Status of an SSVectorBase
82   	    *
83   	    *  An SSVectorBase can be set up or not. In case it is set up, its IdxSet correctly contains all indices of nonzero
84   	    *  elements of the SSVectorBase.  Otherwise, it does not contain any useful data. Whether or not an SSVectorBase is
85   	    *  setup can be determined with the method \ref soplex::SSVectorBase::isSetup() "isSetup()".
86   	    *
87   	    *  There are three methods for directly affecting the setup status of an SSVectorBase:
88   	    *
89   	    *  - unSetup():    This method sets the status to ``not setup''.
90   	    *
91   	    *  - setup():      This method initializes the IdxSet to the SSVectorBase's nonzero indices and sets the status to
92   	    *                  ``setup''.
93   	    *
94   	    *  - forceSetup(): This method sets the status to ``setup'' without verifying that the IdxSet correctly contains all
95   	    *                  nonzero indices. It may be used when the nonzero indices have been computed externally.
96   	    */
97   	   ///@{
98   	
99   	   /// Only used in slufactor.hpp.
100  	   R* get_ptr()
101  	   {
102  	      return VectorBase<R>::get_ptr();
103  	   }
104  	   /// Returns the non-zero epsilon used.
105  	   R getEpsilon() const
106  	   {
107  	      return epsilon;
108  	   }
109  	
110  	   /// Changes the non-zero epsilon, invalidating the setup. */
111  	   void setEpsilon(R eps)
112  	   {
113  	      if(eps != epsilon)
114  	      {
115  	         epsilon = eps;
116  	         setupStatus = false;
117  	      }
118  	   }
119  	
120  	   /// Returns setup status.
121  	   bool isSetup() const
122  	   {
123  	      return setupStatus;
124  	   }
125  	
126  	   /// Makes SSVectorBase not setup.
127  	   void unSetup()
128  	   {
129  	      setupStatus = false;
130  	   }
131  	
132  	   /// Initializes nonzero indices for elements with absolute values above #epsilon and sets all other elements to 0.
133  	   void setup()
134  	   {
135  	      if(!isSetup())
136  	      {
137  	         IdxSet::clear();
138  	
139  	         int d = dim();
140  	         num = 0;
141  	
142  	         for(int i = 0; i < d; ++i)
143  	         {
144  	            if(VectorBase<R>::val[i] != R(0))
145  	            {
146  	               if(spxAbs(VectorBase<R>::val[i]) <= epsilon)
147  	                  VectorBase<R>::val[i] = R(0);
148  	               else
149  	               {
150  	                  idx[num] = i;
151  	                  num++;
152  	               }
153  	            }
154  	         }
155  	
156  	         setupStatus = true;
157  	
158  	         assert(isConsistent());
159  	      }
160  	   }
161  	
162  	   /// Forces setup status.
163  	   void forceSetup()
164  	   {
165  	      setupStatus = true;
166  	   }
167  	
168  	   ///@}
169  	
170  	   // ------------------------------------------------------------------------------------------------------------------
171  	   /**@name Methods for setup SSVectorBases */
172  	   ///@{
173  	
174  	   /// Returns index of the \p n 'th nonzero element.
175  	   int index(int n) const
176  	   {
177  	      assert(isSetup());
178  	
179  	      return IdxSet::index(n);
180  	   }
181  	
182  	   /// Returns value of the \p n 'th nonzero element.
183  	   R value(int n) const
184  	   {
185  	      assert(isSetup());
186  	      assert(n >= 0 && n < size());
187  	
188  	      return VectorBase<R>::val[idx[n]];
189  	   }
190  	
191  	   /// Finds the position of index \p i in the #IdxSet, or -1 if \p i doesn't exist.
192  	   int pos(int i) const
193  	   {
194  	      assert(isSetup());
195  	
196  	      return IdxSet::pos(i);
197  	   }
198  	
199  	   /// Returns the number of nonzeros.
200  	   int size() const
201  	   {
202  	      assert(isSetup());
203  	
204  	      return IdxSet::size();
205  	   }
206  	
207  	   /// Adds nonzero (\p i, \p x) to SSVectorBase.
208  	   /** No nonzero with index \p i must exist in the SSVectorBase. */
209  	   void add(int i, R x)
210  	   {
211  	      assert(VectorBase<R>::val[i] == R(0));
212  	      assert(pos(i) < 0);
213  	
214  	      addIdx(i);
215  	      VectorBase<R>::val[i] = x;
216  	   }
217  	
218  	   /// Sets \p i 'th element to \p x.
219  	   void setValue(int i, R x)
220  	   {
221  	      assert(i >= 0);
222  	      assert(i < VectorBase<R>::dim());
223  	
224  	      if(isSetup())
225  	      {
226  	         int n = pos(i);
227  	
228  	         if(n < 0)
229  	         {
230  	            if(spxAbs(x) > epsilon)
231  	               IdxSet::add(1, &i);
232  	         }
233  	         else if(x == R(0))
234  	            clearNum(n);
235  	      }
236  	
237  	      VectorBase<R>::val[i] = x;
238  	
239  	      assert(isConsistent());
240  	   }
241  	
242  	   /// Scale \p i 'th element by a
243  	   void scaleValue(int i, int scaleExp)
244  	   {
245  	      assert(i >= 0);
246  	      assert(i < VectorBase<R>::dim());
247  	
248  	      VectorBase<R>::val[i] = spxLdexp(VectorBase<R>::val[i], scaleExp);
249  	
250  	      assert(isConsistent());
251  	   }
252  	
253  	   /// Clears element \p i.
254  	   void clearIdx(int i)
255  	   {
256  	      if(isSetup())
257  	      {
258  	         int n = pos(i);
259  	
260  	         if(n >= 0)
261  	            remove(n);
262  	      }
263  	
264  	      VectorBase<R>::val[i] = 0;
265  	
266  	      assert(isConsistent());
267  	   }
268  	
269  	   /// Sets \p n 'th nonzero element to 0 (index \p n must exist).
270  	   void clearNum(int n)
271  	   {
272  	      assert(isSetup());
273  	      assert(index(n) >= 0);
274  	
275  	      VectorBase<R>::val[index(n)] = 0;
276  	      remove(n);
277  	
278  	      assert(isConsistent());
279  	   }
280  	
281  	   ///@}
282  	
283  	   // ------------------------------------------------------------------------------------------------------------------
284  	   /**@name Methods independent of the Status */
285  	   ///@{
286  	
287  	   /// Returns \p i 'th value.
288  	   R operator[](int i) const
289  	   {
290  	      return VectorBase<R>::val[i];
291  	   }
292  	
293  	   /// Returns array indices.
294  	   const int* indexMem() const
295  	   {
296  	      return idx;
297  	   }
298  	
299  	   /// Returns array values.
300  	   const R* values() const
301  	   {
302  	      return VectorBase<R>::val.data();
303  	   }
304  	
305  	   /// Returns indices.
306  	   const IdxSet& indices() const
307  	   {
308  	      return *this;
309  	   }
310  	
311  	   /// Returns array indices.
312  	   int* altIndexMem()
313  	   {
314  	      unSetup();
315  	      return idx;
316  	   }
317  	
318  	   /// Returns array values.
319  	   R* altValues()
320  	   {
321  	      unSetup();
322  	      return VectorBase<R>::val.data();
323  	   }
324  	
325  	   /// Returns indices.
326  	   IdxSet& altIndices()
327  	   {
328  	      unSetup();
329  	      return *this;
330  	   }
331  	
332  	   ///@}
333  	
334  	   // ------------------------------------------------------------------------------------------------------------------
335  	   /**@name Arithmetic operations */
336  	   ///@{
337  	
338  	   /// Addition.
339  	   template < class S >
340  	   SSVectorBase<R>& operator+=(const VectorBase<S>& vec)
341  	   {
342  	      VectorBase<S>::operator+=(vec);
343  	
344  	      if(isSetup())
345  	      {
346  	         setupStatus = false;
347  	         setup();
348  	      }
349  	
350  	      return *this;
351  	   }
352  	
353  	   /// Addition.
354  	   template < class S >
355  	   SSVectorBase<R>& operator+=(const SVectorBase<S>& vec);
356  	
357  	   /// Addition.
358  	   template < class S >
359  	   SSVectorBase<R>& operator+=(const SSVectorBase<S>& vec)
360  	   {
361  	      assert(vec.isSetup());
362  	
363  	      for(int i = vec.size() - 1; i >= 0; --i)
364  	         VectorBase<R>::val[vec.index(i)] += vec.value(i);
365  	
366  	      if(isSetup())
367  	      {
368  	         setupStatus = false;
369  	         setup();
370  	      }
371  	
372  	      return *this;
373  	   }
374  	
375  	   /// Subtraction.
376  	   template < class S >
377  	   SSVectorBase<R>& operator-=(const VectorBase<S>& vec)
378  	   {
379  	      VectorBase<R>::operator-=(vec);
380  	
381  	      if(isSetup())
382  	      {
383  	         setupStatus = false;
384  	         setup();
385  	      }
386  	
387  	      return *this;
388  	   }
389  	
390  	   /// Subtraction.
391  	   template < class S >
392  	   SSVectorBase<R>& operator-=(const SVectorBase<S>& vec);
393  	
394  	   /// Subtraction.
395  	   template < class S >
396  	   SSVectorBase<R>& operator-=(const SSVectorBase<S>& vec)
397  	   {
398  	      if(vec.isSetup())
399  	      {
400  	         for(int i = vec.size() - 1; i >= 0; --i)
401  	            VectorBase<R>::val[vec.index(i)] -= vec.value(i);
402  	      }
403  	      else
404  	         VectorBase<R>::operator-=(VectorBase<S>(vec));
405  	
406  	      if(isSetup())
407  	      {
408  	         setupStatus = false;
409  	         setup();
410  	      }
411  	
412  	      return *this;
413  	   }
414  	
415  	   /// Scaling.
416  	   template < class S >
417  	   SSVectorBase<R>& operator*=(S x)
418  	   {
419  	      assert(isSetup());
420  	      assert(x != S(0));
421  	
422  	      for(int i = size() - 1; i >= 0; --i)
423  	         VectorBase<R>::val[index(i)] *= x;
424  	
425  	      assert(isConsistent());
426  	
427  	      return *this;
428  	   }
429  	
430  	   // Inner product.
431  	   template < class S >
432  	   R operator*(const SSVectorBase<S>& w)
433  	   {
434  	      setup();
435  	
436  	      StableSum<R> x;
437  	      int i = size() - 1;
438  	      int j = w.size() - 1;
439  	
440  	      // both *this and w non-zero vectors?
441  	      if(i >= 0 && j >= 0)
442  	      {
443  	         int vi = index(i);
444  	         int wj = w.index(j);
445  	
446  	         while(i != 0 && j != 0)
447  	         {
448  	            if(vi == wj)
449  	            {
450  	               x += VectorBase<R>::val[vi] * R(w.val[wj]);
451  	               vi = index(--i);
452  	               wj = w.index(--j);
453  	            }
454  	            else if(vi > wj)
455  	               vi = index(--i);
456  	            else
457  	               wj = w.index(--j);
458  	         }
459  	
460  	         /* check remaining indices */
461  	
462  	         while(i != 0 && vi != wj)
463  	            vi = index(--i);
464  	
465  	         while(j != 0 && vi != wj)
466  	            wj = w.index(--j);
467  	
468  	         if(vi == wj)
469  	            x += VectorBase<R>::val[vi] * R(w.val[wj]);
470  	      }
471  	
472  	      return x;
473  	   }
474  	
475  	   /// Addition of a scaled vector.
476  	   ///@todo SSVectorBase::multAdd() should be rewritten without pointer arithmetic.
477  	   template < class S, class T >
478  	   SSVectorBase<R>& multAdd(S xx, const SVectorBase<T>& vec);
479  	
480  	   /// Addition of a scaled vector.
481  	   template < class S, class T >
482  	   SSVectorBase<R>& multAdd(S x, const VectorBase<T>& vec)
483  	   {
484  	      VectorBase<R>::multAdd(x, vec);
485  	
486  	      if(isSetup())
487  	      {
488  	         setupStatus = false;
489  	         setup();
490  	      }
491  	
492  	      return *this;
493  	   }
494  	
495  	   /// Assigns pair wise vector product to SSVectorBase.
496  	   template < class S, class T >
497  	   SSVectorBase<R>& assignPWproduct4setup(const SSVectorBase<S>& x, const SSVectorBase<T>& y);
498  	
499  	   /// Assigns \f$x^T \cdot A\f$ to SSVectorBase.
500  	   template < class S, class T >
501  	   SSVectorBase<R>& assign2product(const SSVectorBase<S>& x, const SVSetBase<T>& A);
502  	
503  	   /// Assigns SSVectorBase to \f$A \cdot x\f$ for a setup \p x.
504  	   template < class S, class T >
505  	   SSVectorBase<R>& assign2product4setup(const SVSetBase<S>& A, const SSVectorBase<T>& x,
506  	                                         Timer* timeSparse, Timer* timeFull, int& nCallsSparse, int& nCallsFull);
507  	
508  	public:
509  	
510  	   /// Assigns SSVectorBase to \f$A \cdot x\f$ thereby setting up \p x.
511  	   template < class S, class T >
512  	   SSVectorBase<R>& assign2productAndSetup(const SVSetBase<S>& A, SSVectorBase<T>& x);
513  	
514  	   /// Maximum absolute value, i.e., infinity norm.
515  	   R maxAbs() const
516  	   {
517  	      if(isSetup())
518  	      {
519  	         R maxabs = 0;
520  	
521  	         for(int i = 0; i < num; ++i)
522  	         {
523  	            R x = spxAbs(VectorBase<R>::val[idx[i]]);
524  	
525  	            if(x > maxabs)
526  	               maxabs = x;
527  	         }
528  	
529  	         return maxabs;
530  	      }
531  	      else
532  	         return VectorBase<R>::maxAbs();
533  	   }
534  	
535  	   /// Squared euclidian norm.
536  	   R length2() const
537  	   {
538  	      R x = 0;
539  	
540  	      if(isSetup())
541  	      {
542  	         for(int i = 0; i < num; ++i)
543  	            x += VectorBase<R>::val[idx[i]] * VectorBase<R>::val[idx[i]];
544  	      }
545  	      else
546  	         x = VectorBase<R>::length2();
547  	
548  	      return x;
549  	   }
550  	
551  	   /// Floating point approximation of euclidian norm (without any approximation guarantee).
552  	   R length() const
553  	   {
554  	      return spxSqrt(R(length2()));
555  	   }
556  	
557  	   ///@}
558  	
559  	   // ------------------------------------------------------------------------------------------------------------------
560  	   /**@name Miscellaneous */
561  	   ///@{
562  	
563  	   /// Dimension of VectorBase.
564  	   int dim() const
565  	   {
566  	      return VectorBase<R>::dim();
567  	   }
568  	
569  	   /// Resets dimension to \p newdim.
570  	   void reDim(int newdim)
571  	   {
572  	      for(int i = IdxSet::size() - 1; i >= 0; --i)
573  	      {
574  	         if(index(i) >= newdim)
575  	            remove(i);
576  	      }
577  	
578  	      VectorBase<R>::reDim(newdim);
579  	      setMax(VectorBase<R>::memSize() + 1);
580  	
581  	      assert(isConsistent());
582  	   }
583  	
584  	   /// Sets number of nonzeros (thereby unSetup SSVectorBase).
585  	   void setSize(int n)
586  	   {
587  	      assert(n >= 0);
588  	      assert(n <= IdxSet::max());
589  	
590  	      unSetup();
591  	      num = n;
592  	   }
593  	
594  	   /// Resets memory consumption to \p newsize.
595  	   void reMem(int newsize)
596  	   {
597  	      VectorBase<R>::reSize(newsize);
598  	      assert(isConsistent());
599  	
600  	      setMax(VectorBase<R>::memSize() + 1);
601  	   }
602  	
603  	   /// Clears vector.
604  	   void clear()
605  	   {
606  	      if(isSetup())
607  	      {
608  	         for(int i = 0; i < num; ++i)
609  	            VectorBase<R>::val[idx[i]] = 0;
610  	      }
611  	      else
612  	         VectorBase<R>::clear();
613  	
614  	      IdxSet::clear();
615  	      setupStatus = true;
616  	
617  	      assert(isConsistent());
618  	   }
619  	
620  	   /// consistency check.
621  	   bool isConsistent() const
622  	   {
623  	#ifdef ENABLE_CONSISTENCY_CHECKS
624  	
625  	      if(VectorBase<R>::dim() > IdxSet::max())
626  	         return MSGinconsistent("SSVectorBase");
627  	
628  	      if(VectorBase<R>::dim() < IdxSet::dim())
629  	         return MSGinconsistent("SSVectorBase");
630  	
631  	      if(isSetup())
632  	      {
633  	         for(int i = 0; i < VectorBase<R>::dim(); ++i)
634  	         {
635  	            int j = pos(i);
636  	
637  	            if(j < 0 && spxAbs(VectorBase<R>::val[i]) > 0)
638  	            {
639  	               MSG_ERROR(std::cerr << "ESSVEC01 i = " << i
640  	                         << "\tidx = " << j
641  	                         << "\tval = " << std::setprecision(16) << VectorBase<R>::val[i]
642  	                         << std::endl;)
643  	
644  	               return MSGinconsistent("SSVectorBase");
645  	            }
646  	         }
647  	      }
648  	
649  	      return VectorBase<R>::isConsistent() && IdxSet::isConsistent();
650  	#else
651  	      return true;
652  	#endif
653  	   }
654  	
655  	   ///@}
656  	
657  	   // ------------------------------------------------------------------------------------------------------------------
658  	   /**@name Constructors / Destructors */
659  	   ///@{
660  	
661  	   /// Default constructor.
662  	   explicit SSVectorBase<R>(int p_dim, R p_eps = Param::epsilon())
663  	      : VectorBase<R>(p_dim)
664  	      , IdxSet()
665  	      , setupStatus(true)
666  	      , epsilon(p_eps)
667  	   {
668  	      len = (p_dim < 1) ? 1 : p_dim;
669  	      spx_alloc(idx, len);
670  	      VectorBase<R>::clear();
671  	
672  	      assert(isConsistent());
673  	   }
674  	
675  	   /// Copy constructor.
676  	   template < class S >
677  	   SSVectorBase<R>(const SSVectorBase<S>& vec)
678  	      : VectorBase<R>(vec)
679  	      , IdxSet()
680  	      , setupStatus(vec.setupStatus)
681  	      , epsilon(vec.epsilon)
682  	   {
683  	      len = (vec.dim() < 1) ? 1 : vec.dim();
684  	      spx_alloc(idx, len);
685  	      IdxSet::operator=(vec);
686  	
687  	      assert(isConsistent());
688  	   }
689  	
690  	   /// Copy constructor.
691  	   /** The redundancy with the copy constructor below is necessary since otherwise the compiler doesn't realize that it
692  	    *  could use the more general one with S = R and generates a shallow copy constructor.
693  	    */
694  	   SSVectorBase<R>(const SSVectorBase<R>& vec)
695  	      : VectorBase<R>(vec)
696  	      , IdxSet()
697  	      , setupStatus(vec.setupStatus)
698  	      , epsilon(vec.epsilon)
699  	   {
700  	      len = (vec.dim() < 1) ? 1 : vec.dim();
701  	      spx_alloc(idx, len);
702  	      IdxSet::operator=(vec);
703  	
704  	      assert(isConsistent());
705  	   }
706  	
707  	   /// Constructs nonsetup copy of \p vec.
708  	   template < class S >
709  	   explicit SSVectorBase<R>(const VectorBase<S>& vec, R eps = Param::epsilon())
710  	      : VectorBase<R>(vec)
711  	      , IdxSet()
712  	      , setupStatus(false)
713  	      , epsilon(eps)
714  	   {
715  	      len = (vec.dim() < 1) ? 1 : vec.dim();
716  	      spx_alloc(idx, len);
717  	
718  	      assert(isConsistent());
719  	   }
720  	
721  	   /// Sets up \p rhs vector, and assigns it.
722  	   template < class S >
723  	   void setup_and_assign(SSVectorBase<S>& rhs)
724  	   {
725  	      clear();
726  	      epsilon = rhs.epsilon;
727  	      setMax(rhs.max());
728  	      VectorBase<R>::reDim(rhs.dim());
729  	
730  	      if(rhs.isSetup())
731  	      {
732  	         IdxSet::operator=(rhs);
733  	
734  	         for(int i = size() - 1; i >= 0; --i)
735  	         {
736  	            int j  = index(i);
737  	            VectorBase<R>::val[j] = rhs.val[j];
738  	         }
739  	      }
740  	      else
741  	      {
742  	         int d = rhs.dim();
743  	         num = 0;
744  	
745  	         for(int i = 0; i < d; ++i)
746  	         {
747  	            if(rhs.val[i] != 0)
748  	            {
749  	               if(spxAbs(rhs.val[i]) > epsilon)
750  	               {
751  	                  rhs.idx[num] = i;
752  	                  idx[num] = i;
753  	                  VectorBase<R>::val[i] = rhs.val[i];
754  	                  num++;
755  	               }
756  	               else
757  	                  rhs.val[i] = 0;
758  	            }
759  	         }
760  	
761  	         rhs.num = num;
762  	         rhs.setupStatus = true;
763  	      }
764  	
765  	      setupStatus = true;
766  	
767  	      assert(rhs.isConsistent());
768  	      assert(isConsistent());
769  	   }
770  	
771  	   /// Assigns only the elements of \p rhs.
772  	   template < class S >
773  	   SSVectorBase<R>& assign(const SVectorBase<S>& rhs);
774  	
775  	   /// Assignment operator.
776  	   template < class S >
777  	   SSVectorBase<R>& operator=(const SSVectorBase<S>& rhs)
778  	   {
779  	      assert(rhs.isConsistent());
780  	
781  	      if(this != &rhs)
782  	      {
783  	         clear();
784  	         epsilon = rhs.epsilon;
785  	         setMax(rhs.max());
786  	         VectorBase<R>::reDim(rhs.dim());
787  	
788  	         if(rhs.isSetup())
789  	         {
790  	            IdxSet::operator=(rhs);
791  	
792  	            for(int i = size() - 1; i >= 0; --i)
793  	            {
794  	               int j = index(i);
795  	               VectorBase<R>::val[j] = rhs.val[j];
796  	            }
797  	         }
798  	         else
799  	         {
800  	            int d = rhs.dim();
801  	            num = 0;
802  	
803  	            for(int i = 0; i < d; ++i)
804  	            {
805  	               if(spxAbs(rhs.val[i]) > epsilon)
806  	               {
807  	                  VectorBase<R>::val[i] = rhs.val[i];
808  	                  idx[num] = i;
809  	                  num++;
810  	               }
811  	            }
812  	         }
813  	
814  	         setupStatus = true;
815  	      }
816  	
817  	      assert(isConsistent());
818  	
819  	      return *this;
820  	   }
821  	
822  	   /// Assignment operator.
823  	   SSVectorBase<R>& operator=(const SSVectorBase<R>& rhs)
824  	   {
825  	      assert(rhs.isConsistent());
826  	
827  	      if(this != &rhs)
828  	      {
829  	         clear();
830  	         epsilon = rhs.epsilon;
831  	         setMax(rhs.max());
832  	         VectorBase<R>::reDim(rhs.dim());
833  	
834  	         if(rhs.isSetup())
835  	         {
836  	            IdxSet::operator=(rhs);
837  	
838  	            for(int i = size() - 1; i >= 0; --i)
839  	            {
840  	               int j = index(i);
841  	               VectorBase<R>::val[j] = rhs.val[j];
842  	            }
843  	         }
844  	         else
845  	         {
846  	            num = 0;
847  	
848  	            for(int i = 0; i < rhs.dim(); ++i)
849  	            {
850  	               if(spxAbs(rhs.val[i]) > epsilon)
851  	               {
852  	                  VectorBase<R>::val[i] = rhs.val[i];
853  	                  idx[num] = i;
854  	                  num++;
855  	               }
856  	            }
857  	         }
858  	
859  	         setupStatus = true;
860  	      }
861  	
862  	      assert(isConsistent());
863  	
864  	      return *this;
865  	   }
866  	
867  	   /// Assignment operator.
868  	   template < class S >
869  	   SSVectorBase<R>& operator=(const SVectorBase<S>& rhs);
870  	
871  	   /// Assignment operator.
872  	   template < class S >
873  	   SSVectorBase<R>& operator=(const VectorBase<S>& rhs)
874  	   {
875  	      unSetup();
876  	      VectorBase<R>::operator=(rhs);
877  	
878  	      assert(isConsistent());
879  	
880  	      return *this;
881  	   }
882  	
883  	   /// destructor
884  	   ~SSVectorBase<R>()
885  	   {
886  	      if(idx)
887  	         spx_free(idx);
888  	   }
889  	
890  	   ///@}
891  	
892  	private:
893  	
894  	   // ------------------------------------------------------------------------------------------------------------------
895  	   /**@name Private helpers */
896  	   ///@{
897  	
898  	   /// Assignment helper.
899  	   template < class S, class T >
900  	   SSVectorBase<R>& assign2product1(const SVSetBase<S>& A, const SSVectorBase<T>& x);
901  	
902  	   /// Assignment helper.
903  	   template < class S, class T >
904  	   SSVectorBase<R>& assign2productShort(const SVSetBase<S>& A, const SSVectorBase<T>& x);
905  	
906  	   /// Assignment helper.
907  	   template < class S, class T >
908  	   SSVectorBase<R>& assign2productFull(const SVSetBase<S>& A, const SSVectorBase<T>& x);
909  	
910  	   ///@}
911  	};
912  	
913  	} // namespace soplex
914  	#endif // _SSVECTORBASE_H_
915