svd_si.h
Go to the documentation of this file.
1 /* svd_si.h automatically generated by makeheader from svd.template */
2 
3 #define assert(A)
4 /* stuff included from libs/ap.h */
5 
6 /********************************************************************
7 AP library.
8 See www.alglib.net or alglib.sources.ru for details.
9 ********************************************************************/
10 
11 #ifndef AP_H
12 #define AP_H
13 
14 #include <stdlib.h>
15 #include <math.h>
16 #include "resources/feFopen.h"
17 #include "kernel/mod2.h"
18 
19 #ifdef HAVE_SVD
20 /********************************************************************
21 Checking of the array boundaries mode.
22 ********************************************************************/
23 //#define NO_AP_ASSERT
24 #define AP_ASSERT
25 
26 #ifndef AP_ASSERT
27 #define NO_AP_ASSERT
28 #endif
29 
30 #ifdef NO_AP_ASSERT
31 #ifdef AP_ASSERT
32 #undef NO_AP_ASSERT
33 #endif
34 #endif
35 
36 
37 /********************************************************************
38 This symbol is used for debugging. Do not define it and do not remove
39 comments.
40 ********************************************************************/
41 //#define UNSAFE_MEM_COPY
42 
43 
44 /********************************************************************
45 Namespace of a standard library AlgoPascal.
46 ********************************************************************/
47 namespace ap
48 {
49 
50 
51 /********************************************************************
52 Exception class.
53 ********************************************************************/
54 class ap_error
55 {
56 public:
57  static void make_assertion(bool bClause)
58  { if(!bClause) /*throw ap_error();*/ ::WerrorS("ap_error"); };
59 private:
60 };
61 
62 /********************************************************************
63 Class defining a complex number with double precision.
64 ********************************************************************/
65 class complex;
66 
67 class complex
68 {
69 public:
70  complex():x(0.0),y(0.0){};
71  complex(const double &_x):x(_x),y(0.0){};
72  complex(const double &_x, const double &_y):x(_x),y(_y){};
73  complex(const complex &z):x(z.x),y(z.y){};
74 
75  complex& operator= (const double& v){ x = v; y = 0.0; return *this; };
76  complex& operator+=(const double& v){ x += v; return *this; };
77  complex& operator-=(const double& v){ x -= v; return *this; };
78  complex& operator*=(const double& v){ x *= v; y *= v; return *this; };
79  complex& operator/=(const double& v){ x /= v; y /= v; return *this; };
80 
81  complex& operator= (const complex& z){ x = z.x; y = z.y; return *this; };
82  complex& operator+=(const complex& z){ x += z.x; y += z.y; return *this; };
83  complex& operator-=(const complex& z){ x -= z.x; y -= z.y; return *this; };
84  complex& operator*=(const complex& z){ double t = x*z.x-y*z.y; y = x*z.y+y*z.x; x = t; return *this; };
86  {
88  double e;
89  double f;
90  if( fabs(z.y)<fabs(z.x) )
91  {
92  e = z.y/z.x;
93  f = z.x+z.y*e;
94  result.x = (z.x+z.y*e)/f;
95  result.y = (z.y-z.x*e)/f;
96  }
97  else
98  {
99  e = z.x/z.y;
100  f = z.y+z.x*e;
101  result.x = (z.y+z.x*e)/f;
102  result.y = (-z.x+z.y*e)/f;
103  }
104  *this = result;
105  return *this;
106  };
107 
108  double x, y;
109 };
110 
111 const complex operator/(const complex& lhs, const complex& rhs);
112 bool operator==(const complex& lhs, const complex& rhs);
113 bool operator!=(const complex& lhs, const complex& rhs);
114 const complex operator+(const complex& lhs);
115 const complex operator-(const complex& lhs);
116 const complex operator+(const complex& lhs, const complex& rhs);
117 const complex operator+(const complex& lhs, const double& rhs);
118 const complex operator+(const double& lhs, const complex& rhs);
119 const complex operator-(const complex& lhs, const complex& rhs);
120 const complex operator-(const complex& lhs, const double& rhs);
121 const complex operator-(const double& lhs, const complex& rhs);
122 const complex operator*(const complex& lhs, const complex& rhs);
123 const complex operator*(const complex& lhs, const double& rhs);
124 const complex operator*(const double& lhs, const complex& rhs);
125 const complex operator/(const complex& lhs, const complex& rhs);
126 const complex operator/(const double& lhs, const complex& rhs);
127 const complex operator/(const complex& lhs, const double& rhs);
128 double abscomplex(const complex &z);
129 const complex conj(const complex &z);
130 const complex csqr(const complex &z);
131 
132 
133 /********************************************************************
134 Template defining vector in memory. It is used by the basic
135 subroutines of linear algebra.
136 
137 Vector consists of Length elements of type T, starting from an element,
138 which Data is pointed to. Interval between adjacent elements equals
139 the value of Step.
140 
141 The class provides an access for reading only.
142 ********************************************************************/
143 template<class T>
144 class const_raw_vector
145 {
146 public:
147  const_raw_vector(const T *Data, int Length, int Step):
148  pData(const_cast<T*>(Data)),iLength(Length),iStep(Step){};
149 
150  const T* GetData() const
151  { return pData; };
152 
153  int GetLength() const
154  { return iLength; };
155 
156  int GetStep() const
157  { return iStep; };
158 protected:
159  T *pData;
160  int iLength, iStep;
161 };
162 
163 
164 /********************************************************************
165 Template defining vector in memory, derived from const_raw_vector.
166 It is used by the basic subroutines of linear algebra.
167 
168 Vector consists of Length elements of type T, starting from an element,
169 which Data is pointed to. Interval between adjacent elements equals
170 the value of Step.
171 
172 The class provides an access both for reading and writing.
173 ********************************************************************/
174 template<class T>
175 class raw_vector : public const_raw_vector<T>
176 {
177 public:
178  raw_vector(T *Data, int Length, int Step):const_raw_vector<T>(Data, Length, Step){};
179 
181  { return const_raw_vector<T>::pData; };
182 };
183 
184 
185 /********************************************************************
186 Scalar product
187 ********************************************************************/
188 template<class T>
190 {
192  if( v1.GetStep()==1 && v2.GetStep()==1 )
193  {
194  //
195  // fast
196  //
197  T r = 0;
198  const T *p1 = v1.GetData();
199  const T *p2 = v2.GetData();
200  int imax = v1.GetLength()/4;
201  int i;
202  for(i=imax; i!=0; i--)
203  {
204  r += (*p1)*(*p2) + p1[1]*p2[1] + p1[2]*p2[2] + p1[3]*p2[3];
205  p1+=4;
206  p2+=4;
207  }
208  for(i=0; i<v1.GetLength()%4; i++)
209  r += (*(p1++))*(*(p2++));
210  return r;
211  }
212  else
213  {
214  //
215  // general
216  //
217  int offset11 = v1.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
218  int offset21 = v2.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
219  T r = 0;
220  const T *p1 = v1.GetData();
221  const T *p2 = v2.GetData();
222  int imax = v1.GetLength()/4;
223  int i;
224  for(i=0; i<imax; i++)
225  {
226  r += (*p1)*(*p2) + p1[offset11]*p2[offset21] + p1[offset12]*p2[offset22] + p1[offset13]*p2[offset23];
227  p1+=offset14;
228  p2+=offset24;
229  }
230  for(i=0; i<v1.GetLength()%4; i++)
231  {
232  r += (*p1)*(*p2);
233  p1+=offset11;
234  p2+=offset21;
235  }
236  return r;
237  }
238 }
239 
240 
241 /********************************************************************
242 Copy one vector into another
243 ********************************************************************/
244 template<class T>
245 void vmove(raw_vector<T> vdst, const_raw_vector<T> vsrc)
246 {
248  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
249  {
250  //
251  // fast
252  //
253  T *p1 = vdst.GetData();
254  const T *p2 = vsrc.GetData();
255  int imax = vdst.GetLength()/2;
256  int i;
257  for(i=imax; i!=0; i--)
258  {
259  *p1 = *p2;
260  p1[1] = p2[1];
261  p1 += 2;
262  p2 += 2;
263  }
264  if(vdst.GetLength()%2 != 0)
265  *p1 = *p2;
266  return;
267  }
268  else
269  {
270  //
271  // general
272  //
273  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
274  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
275  T *p1 = vdst.GetData();
276  const T *p2 = vsrc.GetData();
277  int imax = vdst.GetLength()/4;
278  int i;
279  for(i=0; i<imax; i++)
280  {
281  *p1 = *p2;
282  p1[offset11] = p2[offset21];
283  p1[offset12] = p2[offset22];
284  p1[offset13] = p2[offset23];
285  p1 += offset14;
286  p2 += offset24;
287  }
288  for(i=0; i<vdst.GetLength()%4; i++)
289  {
290  *p1 = *p2;
291  p1 += vdst.GetStep();
292  p2 += vsrc.GetStep();
293  }
294  return;
295  }
296 }
297 
298 
299 /********************************************************************
300 Copy one vector multiplied by -1 into another.
301 ********************************************************************/
302 template<class T>
304 {
306  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
307  {
308  //
309  // fast
310  //
311  T *p1 = vdst.GetData();
312  const T *p2 = vsrc.GetData();
313  int imax = vdst.GetLength()/2;
314  int i;
315  for(i=0; i<imax; i++)
316  {
317  *p1 = -*p2;
318  p1[1] = -p2[1];
319  p1 += 2;
320  p2 += 2;
321  }
322  if(vdst.GetLength()%2 != 0)
323  *p1 = -*p2;
324  return;
325  }
326  else
327  {
328  //
329  // general
330  //
331  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
332  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
333  T *p1 = vdst.GetData();
334  const T *p2 = vsrc.GetData();
335  int imax = vdst.GetLength()/4;
336  int i;
337  for(i=imax; i!=0; i--)
338  {
339  *p1 = -*p2;
340  p1[offset11] = -p2[offset21];
341  p1[offset12] = -p2[offset22];
342  p1[offset13] = -p2[offset23];
343  p1 += offset14;
344  p2 += offset24;
345  }
346  for(i=0; i<vdst.GetLength()%4; i++)
347  {
348  *p1 = -*p2;
349  p1 += vdst.GetStep();
350  p2 += vsrc.GetStep();
351  }
352  return;
353  }
354 }
355 
356 
357 /********************************************************************
358 Copy one vector multiplied by a number into another vector.
359 ********************************************************************/
360 template<class T, class T2>
362 {
364  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
365  {
366  //
367  // fast
368  //
369  T *p1 = vdst.GetData();
370  const T *p2 = vsrc.GetData();
371  int imax = vdst.GetLength()/4;
372  int i;
373  for(i=imax; i!=0; i--)
374  {
375  *p1 = alpha*(*p2);
376  p1[1] = alpha*p2[1];
377  p1[2] = alpha*p2[2];
378  p1[3] = alpha*p2[3];
379  p1 += 4;
380  p2 += 4;
381  }
382  for(i=0; i<vdst.GetLength()%4; i++)
383  *(p1++) = alpha*(*(p2++));
384  return;
385  }
386  else
387  {
388  //
389  // general
390  //
391  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
392  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
393  T *p1 = vdst.GetData();
394  const T *p2 = vsrc.GetData();
395  int imax = vdst.GetLength()/4;
396  int i;
397  for(i=0; i<imax; i++)
398  {
399  *p1 = alpha*(*p2);
400  p1[offset11] = alpha*p2[offset21];
401  p1[offset12] = alpha*p2[offset22];
402  p1[offset13] = alpha*p2[offset23];
403  p1 += offset14;
404  p2 += offset24;
405  }
406  for(i=0; i<vdst.GetLength()%4; i++)
407  {
408  *p1 = alpha*(*p2);
409  p1 += vdst.GetStep();
410  p2 += vsrc.GetStep();
411  }
412  return;
413  }
414 }
415 
416 
417 /********************************************************************
418 Vector addition
419 ********************************************************************/
420 template<class T>
421 void vadd(raw_vector<T> vdst, const_raw_vector<T> vsrc)
422 {
424  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
425  {
426  //
427  // fast
428  //
429  T *p1 = vdst.GetData();
430  const T *p2 = vsrc.GetData();
431  int imax = vdst.GetLength()/4;
432  int i;
433  for(i=imax; i!=0; i--)
434  {
435  *p1 += *p2;
436  p1[1] += p2[1];
437  p1[2] += p2[2];
438  p1[3] += p2[3];
439  p1 += 4;
440  p2 += 4;
441  }
442  for(i=0; i<vdst.GetLength()%4; i++)
443  *(p1++) += *(p2++);
444  return;
445  }
446  else
447  {
448  //
449  // general
450  //
451  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
452  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
453  T *p1 = vdst.GetData();
454  const T *p2 = vsrc.GetData();
455  int imax = vdst.GetLength()/4;
456  int i;
457  for(i=0; i<imax; i++)
458  {
459  *p1 += *p2;
460  p1[offset11] += p2[offset21];
461  p1[offset12] += p2[offset22];
462  p1[offset13] += p2[offset23];
463  p1 += offset14;
464  p2 += offset24;
465  }
466  for(i=0; i<vdst.GetLength()%4; i++)
467  {
468  *p1 += *p2;
469  p1 += vdst.GetStep();
470  p2 += vsrc.GetStep();
471  }
472  return;
473  }
474 }
475 
476 
477 /********************************************************************
478 Add one vector multiplied by a number to another vector.
479 ********************************************************************/
480 template<class T, class T2>
481 void vadd(raw_vector<T> vdst, const_raw_vector<T> vsrc, T2 alpha)
482 {
484  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
485  {
486  //
487  // fast
488  //
489  T *p1 = vdst.GetData();
490  const T *p2 = vsrc.GetData();
491  int imax = vdst.GetLength()/4;
492  int i;
493  for(i=imax; i!=0; i--)
494  {
495  *p1 += alpha*(*p2);
496  p1[1] += alpha*p2[1];
497  p1[2] += alpha*p2[2];
498  p1[3] += alpha*p2[3];
499  p1 += 4;
500  p2 += 4;
501  }
502  for(i=0; i<vdst.GetLength()%4; i++)
503  *(p1++) += alpha*(*(p2++));
504  return;
505  }
506  else
507  {
508  //
509  // general
510  //
511  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
512  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
513  T *p1 = vdst.GetData();
514  const T *p2 = vsrc.GetData();
515  int imax = vdst.GetLength()/4;
516  int i;
517  for(i=0; i<imax; i++)
518  {
519  *p1 += alpha*(*p2);
520  p1[offset11] += alpha*p2[offset21];
521  p1[offset12] += alpha*p2[offset22];
522  p1[offset13] += alpha*p2[offset23];
523  p1 += offset14;
524  p2 += offset24;
525  }
526  for(i=0; i<vdst.GetLength()%4; i++)
527  {
528  *p1 += alpha*(*p2);
529  p1 += vdst.GetStep();
530  p2 += vsrc.GetStep();
531  }
532  return;
533  }
534 }
535 
536 
537 /********************************************************************
538 Vector subtraction
539 ********************************************************************/
540 template<class T>
541 void vsub(raw_vector<T> vdst, const_raw_vector<T> vsrc)
542 {
544  if( vdst.GetStep()==1 && vsrc.GetStep()==1 )
545  {
546  //
547  // fast
548  //
549  T *p1 = vdst.GetData();
550  const T *p2 = vsrc.GetData();
551  int imax = vdst.GetLength()/4;
552  int i;
553  for(i=imax; i!=0; i--)
554  {
555  *p1 -= *p2;
556  p1[1] -= p2[1];
557  p1[2] -= p2[2];
558  p1[3] -= p2[3];
559  p1 += 4;
560  p2 += 4;
561  }
562  for(i=0; i<vdst.GetLength()%4; i++)
563  *(p1++) -= *(p2++);
564  return;
565  }
566  else
567  {
568  //
569  // general
570  //
571  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
572  int offset21 = vsrc.GetStep(), offset22 = 2*offset21, offset23 = 3*offset21, offset24 = 4*offset21;
573  T *p1 = vdst.GetData();
574  const T *p2 = vsrc.GetData();
575  int imax = vdst.GetLength()/4;
576  int i;
577  for(i=0; i<imax; i++)
578  {
579  *p1 -= *p2;
580  p1[offset11] -= p2[offset21];
581  p1[offset12] -= p2[offset22];
582  p1[offset13] -= p2[offset23];
583  p1 += offset14;
584  p2 += offset24;
585  }
586  for(i=0; i<vdst.GetLength()%4; i++)
587  {
588  *p1 -= *p2;
589  p1 += vdst.GetStep();
590  p2 += vsrc.GetStep();
591  }
592  return;
593  }
594 }
595 
596 
597 /********************************************************************
598 Subtract one vector multiplied by a number from another vector.
599 ********************************************************************/
600 template<class T, class T2>
601 void vsub(raw_vector<T> vdst, const_raw_vector<T> vsrc, T2 alpha)
602 {
603  vadd(vdst, vsrc, -alpha);
604 }
605 
606 
607 /********************************************************************
608 In-place vector multiplication
609 ********************************************************************/
610 template<class T, class T2>
611 void vmul(raw_vector<T> vdst, T2 alpha)
612 {
613  if( vdst.GetStep()==1 )
614  {
615  //
616  // fast
617  //
618  T *p1 = vdst.GetData();
619  int imax = vdst.GetLength()/4;
620  int i;
621  for(i=imax; i!=0; i--)
622  {
623  *p1 *= alpha;
624  p1[1] *= alpha;
625  p1[2] *= alpha;
626  p1[3] *= alpha;
627  p1 += 4;
628  }
629  for(i=0; i<vdst.GetLength()%4; i++)
630  *(p1++) *= alpha;
631  return;
632  }
633  else
634  {
635  //
636  // general
637  //
638  int offset11 = vdst.GetStep(), offset12 = 2*offset11, offset13 = 3*offset11, offset14 = 4*offset11;
639  T *p1 = vdst.GetData();
640  int imax = vdst.GetLength()/4;
641  int i;
642  for(i=0; i<imax; i++)
643  {
644  *p1 *= alpha;
645  p1[offset11] *= alpha;
646  p1[offset12] *= alpha;
647  p1[offset13] *= alpha;
648  p1 += offset14;
649  }
650  for(i=0; i<vdst.GetLength()%4; i++)
651  {
652  *p1 *= alpha;
653  p1 += vdst.GetStep();
654  }
655  return;
656  }
657 }
658 
659 
660 /********************************************************************
661 Template of a dynamical one-dimensional array
662 ********************************************************************/
663 template<class T>
664 class template_1d_array
665 {
666 public:
668  {
669  m_Vec=0;
670  m_iVecSize = 0;
671  };
672 
674  {
675  if(m_Vec)
676  delete[] m_Vec;
677  };
678 
680  {
681  m_iVecSize = rhs.m_iVecSize;
682  m_iLow = rhs.m_iLow;
683  m_iHigh = rhs.m_iHigh;
684  if(rhs.m_Vec)
685  {
686  m_Vec = new T[m_iVecSize];
687  #ifndef UNSAFE_MEM_COPY
688  for(int i=0; i<m_iVecSize; i++)
689  m_Vec[i] = rhs.m_Vec[i];
690  #else
691  memcpy(m_Vec, rhs.m_Vec, m_iVecSize*sizeof(T));
692  #endif
693  }
694  else
695  m_Vec=0;
696  };
697 
698 
700  {
701  if( this==&rhs )
702  return *this;
703 
704  m_iLow = rhs.m_iLow;
705  m_iHigh = rhs.m_iHigh;
706  m_iVecSize = rhs.m_iVecSize;
707  if(m_Vec)
708  delete[] m_Vec;
709  if(rhs.m_Vec)
710  {
711  m_Vec = new T[m_iVecSize];
712  #ifndef UNSAFE_MEM_COPY
713  for(int i=0; i<m_iVecSize; i++)
714  m_Vec[i] = rhs.m_Vec[i];
715  #else
716  memcpy(m_Vec, rhs.m_Vec, m_iVecSize*sizeof(T));
717  #endif
718  }
719  else
720  m_Vec=0;
721  return *this;
722  };
723 
724 
725  const T& operator()(int i) const
726  {
727  #ifndef NO_AP_ASSERT
728  ap_error::make_assertion(i>=m_iLow && i<=m_iHigh);
729  #endif
730  return m_Vec[ i-m_iLow ];
731  };
732 
733 
734  T& operator()(int i)
735  {
736  #ifndef NO_AP_ASSERT
737  ap_error::make_assertion(i>=m_iLow && i<=m_iHigh);
738  #endif
739  return m_Vec[ i-m_iLow ];
740  };
741 
742 
743  void setbounds( int iLow, int iHigh )
744  {
745  if(m_Vec)
746  delete[] m_Vec;
747  m_iLow = iLow;
748  m_iHigh = iHigh;
749  m_iVecSize = iHigh-iLow+1;
750  m_Vec = new T[m_iVecSize];
751  };
752 
753 
754  void setcontent( int iLow, int iHigh, const T *pContent )
755  {
756  setbounds(iLow, iHigh);
757  for(int i=iLow; i<=iHigh; i++)
758  (*this)(i) = pContent[i-iLow];
759  };
760 
761 
763  {
764  return m_Vec;
765  };
766 
767  const T* getcontent() const
768  {
769  return m_Vec;
770  };
771 
772 
773  int getlowbound(int iBoundNum = 0) const
774  {
775  return m_iLow;
776  };
777 
778 
779  int gethighbound(int iBoundNum = 0) const
780  {
781  return m_iHigh;
782  };
783 
784  raw_vector<T> getvector(int iStart, int iEnd)
785  {
786  if( iStart>iEnd || wrongIdx(iStart) || wrongIdx(iEnd) )
787  return raw_vector<T>(0, 0, 1);
788  else
789  return raw_vector<T>(m_Vec+iStart-m_iLow, iEnd-iStart+1, 1);
790  };
791 
792 
793  const_raw_vector<T> getvector(int iStart, int iEnd) const
794  {
795  if( iStart>iEnd || wrongIdx(iStart) || wrongIdx(iEnd) )
796  return const_raw_vector<T>(0, 0, 1);
797  else
798  return const_raw_vector<T>(m_Vec+iStart-m_iLow, iEnd-iStart+1, 1);
799  };
800 private:
801  bool wrongIdx(int i) const { return i<m_iLow || i>m_iHigh; };
802 
803  T *m_Vec;
804  long m_iVecSize;
805  long m_iLow, m_iHigh;
806 };
807 
808 
809 
810 /********************************************************************
811 Template of a dynamical two-dimensional array
812 ********************************************************************/
813 template<class T>
814 class template_2d_array
815 {
816 public:
818  {
819  m_Vec=0;
820  m_iVecSize=0;
821  };
822 
824  {
825  if(m_Vec)
826  delete[] m_Vec;
827  };
828 
830  {
831  m_iVecSize = rhs.m_iVecSize;
832  m_iLow1 = rhs.m_iLow1;
833  m_iLow2 = rhs.m_iLow2;
834  m_iHigh1 = rhs.m_iHigh1;
835  m_iHigh2 = rhs.m_iHigh2;
836  m_iConstOffset = rhs.m_iConstOffset;
837  m_iLinearMember = rhs.m_iLinearMember;
838  if(rhs.m_Vec)
839  {
840  m_Vec = new T[m_iVecSize];
841  #ifndef UNSAFE_MEM_COPY
842  for(int i=0; i<m_iVecSize; i++)
843  m_Vec[i] = rhs.m_Vec[i];
844  #else
845  memcpy(m_Vec, rhs.m_Vec, m_iVecSize*sizeof(T));
846  #endif
847  }
848  else
849  m_Vec=0;
850  };
852  {
853  if( this==&rhs )
854  return *this;
855 
856  m_iLow1 = rhs.m_iLow1;
857  m_iLow2 = rhs.m_iLow2;
858  m_iHigh1 = rhs.m_iHigh1;
859  m_iHigh2 = rhs.m_iHigh2;
860  m_iConstOffset = rhs.m_iConstOffset;
861  m_iLinearMember = rhs.m_iLinearMember;
862  m_iVecSize = rhs.m_iVecSize;
863  if(m_Vec)
864  delete[] m_Vec;
865  if(rhs.m_Vec)
866  {
867  m_Vec = new T[m_iVecSize];
868  #ifndef UNSAFE_MEM_COPY
869  for(int i=0; i<m_iVecSize; i++)
870  m_Vec[i] = rhs.m_Vec[i];
871  #else
872  memcpy(m_Vec, rhs.m_Vec, m_iVecSize*sizeof(T));
873  #endif
874  }
875  else
876  m_Vec=0;
877  return *this;
878  };
879 
880  const T& operator()(int i1, int i2) const
881  {
882  #ifndef NO_AP_ASSERT
883  ap_error::make_assertion(i1>=m_iLow1 && i1<=m_iHigh1);
884  ap_error::make_assertion(i2>=m_iLow2 && i2<=m_iHigh2);
885  #endif
886  return m_Vec[ m_iConstOffset + i2 +i1*m_iLinearMember];
887  };
888 
889  T& operator()(int i1, int i2)
890  {
891  #ifndef NO_AP_ASSERT
892  ap_error::make_assertion(i1>=m_iLow1 && i1<=m_iHigh1);
893  ap_error::make_assertion(i2>=m_iLow2 && i2<=m_iHigh2);
894  #endif
895  return m_Vec[ m_iConstOffset + i2 +i1*m_iLinearMember];
896  };
897 
898  void setbounds( int iLow1, int iHigh1, int iLow2, int iHigh2 )
899  {
900  if(m_Vec)
901  delete[] m_Vec;
902  m_iVecSize = (iHigh1-iLow1+1)*(iHigh2-iLow2+1);
903  m_Vec = new T[m_iVecSize];
904  m_iLow1 = iLow1;
905  m_iHigh1 = iHigh1;
906  m_iLow2 = iLow2;
907  m_iHigh2 = iHigh2;
908  m_iConstOffset = -m_iLow2-m_iLow1*(m_iHigh2-m_iLow2+1);
909  m_iLinearMember = (m_iHigh2-m_iLow2+1);
910  };
911 
912  void setcontent( int iLow1, int iHigh1, int iLow2, int iHigh2, const T *pContent )
913  {
914  setbounds(iLow1, iHigh1, iLow2, iHigh2);
915  for(int i=0; i<m_iVecSize; i++)
916  m_Vec[i]=pContent[i];
917  };
918 
920  {
921  return m_Vec;
922  };
923 
924  const T* getcontent() const
925  {
926  return m_Vec;
927  };
928 
929  int getlowbound(int iBoundNum) const
930  {
931  return iBoundNum==1 ? m_iLow1 : m_iLow2;
932  };
933 
934  int gethighbound(int iBoundNum) const
935  {
936  return iBoundNum==1 ? m_iHigh1 : m_iHigh2;
937  };
938 
939  raw_vector<T> getcolumn(int iColumn, int iRowStart, int iRowEnd)
940  {
941  if( (iRowStart>iRowEnd) || wrongColumn(iColumn) || wrongRow(iRowStart) ||wrongRow(iRowEnd) )
942  return raw_vector<T>(0, 0, 1);
943  else
944  return raw_vector<T>(&((*this)(iRowStart, iColumn)), iRowEnd-iRowStart+1, m_iLinearMember);
945  };
946 
947  raw_vector<T> getrow(int iRow, int iColumnStart, int iColumnEnd)
948  {
949  if( (iColumnStart>iColumnEnd) || wrongRow(iRow) || wrongColumn(iColumnStart) || wrongColumn(iColumnEnd))
950  return raw_vector<T>(0, 0, 1);
951  else
952  return raw_vector<T>(&((*this)(iRow, iColumnStart)), iColumnEnd-iColumnStart+1, 1);
953  };
954 
955  const_raw_vector<T> getcolumn(int iColumn, int iRowStart, int iRowEnd) const
956  {
957  if( (iRowStart>iRowEnd) || wrongColumn(iColumn) || wrongRow(iRowStart) ||wrongRow(iRowEnd) )
958  return const_raw_vector<T>(0, 0, 1);
959  else
960  return const_raw_vector<T>(&((*this)(iRowStart, iColumn)), iRowEnd-iRowStart+1, m_iLinearMember);
961  };
962 
963  const_raw_vector<T> getrow(int iRow, int iColumnStart, int iColumnEnd) const
964  {
965  if( (iColumnStart>iColumnEnd) || wrongRow(iRow) || wrongColumn(iColumnStart) || wrongColumn(iColumnEnd))
966  return const_raw_vector<T>(0, 0, 1);
967  else
968  return const_raw_vector<T>(&((*this)(iRow, iColumnStart)), iColumnEnd-iColumnStart+1, 1);
969  };
970 private:
971  bool wrongRow(int i) const { return i<m_iLow1 || i>m_iHigh1; };
972  bool wrongColumn(int j) const { return j<m_iLow2 || j>m_iHigh2; };
973 
974  T *m_Vec;
975  long m_iVecSize;
976  long m_iLow1, m_iLow2, m_iHigh1, m_iHigh2;
977  long m_iConstOffset, m_iLinearMember;
978 };
979 
980 
989 
990 
991 /********************************************************************
992 Constants and functions introduced for compatibility with AlgoPascal
993 ********************************************************************/
994 extern const double machineepsilon;
995 extern const double maxrealnumber;
996 extern const double minrealnumber;
997 
998 int sign(double x);
999 double randomreal();
1000 int randominteger(int maxv);
1001 int round(double x);
1002 int trunc(double x);
1003 int ifloor(double x);
1004 int iceil(double x);
1005 double pi();
1006 double sqr(double x);
1007 int maxint(int m1, int m2);
1008 int minint(int m1, int m2);
1009 double maxreal(double m1, double m2);
1010 double minreal(double m1, double m2);
1011 
1012 };//namespace ap
1013 
1014 
1015 /* stuff included from libs/amp.h */
1016 
1017 #include "omalloc/omalloc.h"
1018 
1019 #include <gmp.h>
1020 #include <mpfr.h>
1021 #include <stdexcept>
1022 #include <math.h>
1023 #include <string>
1024 #include <stdio.h>
1025 #include <time.h>
1026 #include <memory.h>
1027 #include <vector>
1028 #include <list>
1029 
1030 //#define _AMP_NO_TEMPLATE_CONSTRUCTORS
1031 
1032 namespace amp
1033 {
1034  class exception {};
1035  class incorrectPrecision : public exception {};
1036  class overflow : public exception {};
1037  class divisionByZero : public exception {};
1038  class sqrtOfNegativeNumber : public exception {};
1039  class invalidConversion : public exception {};
1040  class invalidString : public exception {};
1041  class internalError : public exception {};
1042  class domainError : public exception {};
1043 
1044  typedef unsigned long unsigned32;
1045  typedef signed long signed32;
1046 
1047  struct mpfr_record
1048  {
1049  unsigned int refCount;
1050  unsigned int Precision;
1051  mpfr_t value;
1052  mpfr_record *next;
1053  };
1054 
1055  typedef mpfr_record* mpfr_record_ptr;
1056 
1057  //
1058  // storage for mpfr_t instances
1059  //
1060  class mpfr_storage
1061  {
1062  public:
1063  static mpfr_record* newMpfr(unsigned int Precision);
1064  static void deleteMpfr(mpfr_record* ref);
1065  /*static void clearStorage();*/
1066  static gmp_randstate_t* getRandState();
1067  private:
1068  static mpfr_record_ptr& getList(unsigned int Precision);
1069  };
1070 
1071  //
1072  // mpfr_t reference
1073  //
1074  class mpfr_reference
1075  {
1076  public:
1077  mpfr_reference();
1078  mpfr_reference(const mpfr_reference& r);
1079  mpfr_reference& operator= (const mpfr_reference &r);
1080  ~mpfr_reference();
1081 
1082  void initialize(int Precision);
1083  void free();
1084 
1085  mpfr_srcptr getReadPtr() const;
1086  mpfr_ptr getWritePtr();
1087  private:
1088  mpfr_record *ref;
1089  };
1090 
1091  //
1092  // ampf template
1093  //
1094  template<unsigned int Precision>
1095  class ampf
1096  {
1097  public:
1098  //
1099  // Destructor
1100  //
1102  {
1103  rval->refCount--;
1104  if( rval->refCount==0 )
1105  mpfr_storage::deleteMpfr(rval);
1106  }
1107 
1108  //
1109  // Initializing
1110  //
1111  ampf () { InitializeAsZero(); }
1112  ampf(mpfr_record *v) { rval = v; }
1113 
1114  ampf (long double v) { InitializeAsDouble(v); }
1115  ampf (double v) { InitializeAsDouble(v); }
1116  ampf (float v) { InitializeAsDouble(v); }
1117  ampf (signed long v) { InitializeAsSLong(v); }
1118  ampf (unsigned long v) { InitializeAsULong(v); }
1119  ampf (signed int v) { InitializeAsSLong(v); }
1120  ampf (unsigned int v) { InitializeAsULong(v); }
1121  ampf (signed short v) { InitializeAsSLong(v); }
1122  ampf (unsigned short v) { InitializeAsULong(v); }
1123  ampf (signed char v) { InitializeAsSLong(v); }
1124  ampf (unsigned char v) { InitializeAsULong(v); }
1125 
1126  //
1127  // initializing from string
1128  // string s must have format "X0.hhhhhhhh@eee" or "X-0.hhhhhhhh@eee"
1129  //
1130  ampf (const std::string &s) { InitializeAsString(s.c_str()); }
1131  ampf (const char *s) { InitializeAsString(s); }
1132 
1133  //
1134  // copy constructors
1135  //
1136  ampf(const ampf& r)
1137  {
1138  rval = r.rval;
1139  rval->refCount++;
1140  }
1141 #ifndef _AMP_NO_TEMPLATE_CONSTRUCTORS
1142  template<unsigned int Precision2>
1144  {
1145  CheckPrecision();
1146  rval = mpfr_storage::newMpfr(Precision);
1147  mpfr_set(getWritePtr(), r.getReadPtr(), GMP_RNDN);
1148  }
1149 #endif
1150 
1151  //
1152  // Assignment constructors
1153  //
1154  ampf& operator= (long double v) { mpfr_set_ld(getWritePtr(), v, GMP_RNDN); return *this; }
1155  ampf& operator= (double v) { mpfr_set_ld(getWritePtr(), v, GMP_RNDN); return *this; }
1156  ampf& operator= (float v) { mpfr_set_ld(getWritePtr(), v, GMP_RNDN); return *this; }
1157  ampf& operator= (signed long v) { mpfr_set_si(getWritePtr(), v, GMP_RNDN); return *this; }
1158  ampf& operator= (unsigned long v) { mpfr_set_ui(getWritePtr(), v, GMP_RNDN); return *this; }
1159  ampf& operator= (signed int v) { mpfr_set_si(getWritePtr(), v, GMP_RNDN); return *this; }
1160  ampf& operator= (unsigned int v) { mpfr_set_ui(getWritePtr(), v, GMP_RNDN); return *this; }
1161  ampf& operator= (signed short v) { mpfr_set_si(getWritePtr(), v, GMP_RNDN); return *this; }
1162  ampf& operator= (unsigned short v) { mpfr_set_ui(getWritePtr(), v, GMP_RNDN); return *this; }
1163  ampf& operator= (signed char v) { mpfr_set_si(getWritePtr(), v, GMP_RNDN); return *this; }
1164  ampf& operator= (unsigned char v) { mpfr_set_ui(getWritePtr(), v, GMP_RNDN); return *this; }
1165  ampf& operator= (const char *s) { mpfr_strtofr(getWritePtr(), s, NULL, 0, GMP_RNDN); return *this; }
1166  ampf& operator= (const std::string &s) { mpfr_strtofr(getWritePtr(), s.c_str(), NULL, 0, GMP_RNDN); return *this; }
1167  ampf& operator= (const ampf& r)
1168  {
1169  // TODO: may be copy ref
1170  if( this==&r )
1171  return *this;
1172  if( rval==r.rval )
1173  return *this;
1174  rval->refCount--;
1175  if( rval->refCount==0 )
1176  mpfr_storage::deleteMpfr(rval);
1177  rval = r.rval;
1178  rval->refCount++;
1179  //mpfr_set(getWritePtr(), r.getReadPtr(), GMP_RNDN);
1180  return *this;
1181  }
1182 #ifndef _AMP_NO_TEMPLATE_CONSTRUCTORS
1183  template<unsigned int Precision2>
1184  ampf& operator= (const ampf<Precision2>& r)
1185  {
1186  if( (void*)this==(void*)(&r) )
1187  return *this;
1188  mpfr_set(getWritePtr(), r.getReadPtr(), GMP_RNDN);
1189  return *this;
1190  }
1191 #endif
1192 
1193  //
1194  // in-place operators
1195  // TODO: optimize
1196  //
1197  template<class T> ampf& operator+=(const T& v){ *this = *this + v; return *this; };
1198  template<class T> ampf& operator-=(const T& v){ *this = *this - v; return *this; };
1199  template<class T> ampf& operator*=(const T& v){ *this = *this * v; return *this; };
1200  template<class T> ampf& operator/=(const T& v){ *this = *this / v; return *this; };
1201 
1202  //
1203  // MPFR access
1204  //
1205  mpfr_srcptr getReadPtr() const;
1206  mpfr_ptr getWritePtr();
1207 
1208  //
1209  // properties and information
1210  //
1211  bool isFiniteNumber() const;
1212  bool isPositiveNumber() const;
1213  bool isZero() const;
1214  bool isNegativeNumber() const;
1215  const ampf getUlpOf();
1216 
1217  //
1218  // conversions
1219  //
1220  double toDouble() const;
1221  std::string toHex() const;
1222  std::string toDec() const;
1223  char * toString() const;
1224 
1225 
1226  //
1227  // static methods
1228  //
1229  static const ampf getUlpOf(const ampf &x);
1230  static const ampf getUlp();
1231  static const ampf getUlp256();
1232  static const ampf getUlp512();
1233  static const ampf getMaxNumber();
1234  static const ampf getMinNumber();
1235  static const ampf getAlgoPascalEpsilon();
1236  static const ampf getAlgoPascalMaxNumber();
1237  static const ampf getAlgoPascalMinNumber();
1238  static const ampf getRandom();
1239  private:
1240  void CheckPrecision();
1241  void InitializeAsZero();
1242  void InitializeAsSLong(signed long v);
1243  void InitializeAsULong(unsigned long v);
1244  void InitializeAsDouble(long double v);
1245  void InitializeAsString(const char *s);
1246 
1247  //mpfr_reference ref;
1248  mpfr_record *rval;
1249  };
1250 
1251  /*void ampf<Precision>::CheckPrecision()
1252  {
1253  if( Precision<32 )
1254  throw incorrectPrecision();
1255  }***/
1256 
1257  template<unsigned int Precision>
1259  {
1260  if( Precision<32 )
1261  //throw incorrectPrecision();
1262  WerrorS("incorrectPrecision");
1263  }
1264 
1265  template<unsigned int Precision>
1267  {
1268  CheckPrecision();
1269  rval = mpfr_storage::newMpfr(Precision);
1270  mpfr_set_ui(getWritePtr(), 0, GMP_RNDN);
1271  }
1272 
1273  template<unsigned int Precision>
1274  void ampf<Precision>::InitializeAsSLong(signed long sv)
1275  {
1276  CheckPrecision();
1277  rval = mpfr_storage::newMpfr(Precision);
1278  mpfr_set_si(getWritePtr(), sv, GMP_RNDN);
1279  }
1280 
1281  template<unsigned int Precision>
1282  void ampf<Precision>::InitializeAsULong(unsigned long v)
1283  {
1284  CheckPrecision();
1285  rval = mpfr_storage::newMpfr(Precision);
1286  mpfr_set_ui(getWritePtr(), v, GMP_RNDN);
1287  }
1288 
1289  template<unsigned int Precision>
1290  void ampf<Precision>::InitializeAsDouble(long double v)
1291  {
1292  CheckPrecision();
1293  rval = mpfr_storage::newMpfr(Precision);
1294  mpfr_set_ld(getWritePtr(), v, GMP_RNDN);
1295  }
1296 
1297  template<unsigned int Precision>
1298  void ampf<Precision>::InitializeAsString(const char *s)
1299  {
1300  CheckPrecision();
1301  rval = mpfr_storage::newMpfr(Precision);
1302  mpfr_strtofr(getWritePtr(), s, NULL, 0, GMP_RNDN);
1303  }
1304 
1305  template<unsigned int Precision>
1306  mpfr_srcptr ampf<Precision>::getReadPtr() const
1307  {
1308  return rval->value;
1309  }
1310 
1311  template<unsigned int Precision>
1312  mpfr_ptr ampf<Precision>::getWritePtr()
1313  {
1314  if( rval->refCount==1 )
1315  return rval->value;
1316  mpfr_record *newrval = mpfr_storage::newMpfr(Precision);
1317  mpfr_set(newrval->value, rval->value, GMP_RNDN);
1318  rval->refCount--;
1319  rval = newrval;
1320  return rval->value;
1321  }
1322 
1323  template<unsigned int Precision>
1324  bool ampf<Precision>::isFiniteNumber() const
1325  {
1326  return mpfr_number_p(getReadPtr())!=0;
1327  }
1328 
1329  template<unsigned int Precision>
1331  {
1332  if( !isFiniteNumber() )
1333  return false;
1334  return mpfr_sgn(getReadPtr())>0;
1335  }
1336 
1337  template<unsigned int Precision>
1338  bool ampf<Precision>::isZero() const
1339  {
1340  return mpfr_zero_p(getReadPtr())!=0;
1341  }
1342 
1343  template<unsigned int Precision>
1345  {
1346  if( !isFiniteNumber() )
1347  return false;
1348  return mpfr_sgn(getReadPtr())<0;
1349  }
1350 
1351  template<unsigned int Precision>
1353  {
1354  return getUlpOf(*this);
1355  }
1356 
1357  template<unsigned int Precision>
1358  double ampf<Precision>::toDouble() const
1359  {
1360  return mpfr_get_d(getReadPtr(), GMP_RNDN);
1361  }
1362 
1363  template<unsigned int Precision>
1365  {
1366  //
1367  // some special cases
1368  //
1369  if( !isFiniteNumber() )
1370  {
1371  std::string r;
1372  mp_exp_t _e;
1373  char *ptr;
1374  ptr = mpfr_get_str(NULL, &_e, 16, 0, getReadPtr(), GMP_RNDN);
1375  r = ptr;
1376  mpfr_free_str(ptr);
1377  return r;
1378  }
1379 
1380  //
1381  // general case
1382  //
1383  std::string r;
1384  char buf_e[128];
1385  signed long iexpval;
1386  mp_exp_t expval;
1387  char *ptr;
1388  char *ptr2;
1389  ptr = mpfr_get_str(NULL, &expval, 16, 0, getReadPtr(), GMP_RNDN);
1390  ptr2 = ptr;
1391  iexpval = expval;
1392  if( iexpval!=expval )
1393  // throw internalError();
1394  WerrorS("internalError");
1395  sprintf(buf_e, "%ld", long(iexpval));
1396  if( *ptr=='-' )
1397  {
1398  r = "-";
1399  ptr++;
1400  }
1401  r += "0x0.";
1402  r += ptr;
1403  r += "@";
1404  r += buf_e;
1405  mpfr_free_str(ptr2);
1406  return r;
1407  }
1408 
1409  template<unsigned int Precision>
1411  {
1412  // TODO: advanced output formatting (zero, integers)
1413 
1414  //
1415  // some special cases
1416  //
1417  if( !isFiniteNumber() )
1418  {
1419  std::string r;
1420  mp_exp_t _e;
1421  char *ptr;
1422  ptr = mpfr_get_str(NULL, &_e, 10, 0, getReadPtr(), GMP_RNDN);
1423  r = ptr;
1424  mpfr_free_str(ptr);
1425  return r;
1426  }
1427 
1428  //
1429  // general case
1430  //
1431  std::string r;
1432  char buf_e[128];
1433  signed long iexpval;
1434  mp_exp_t expval;
1435  char *ptr;
1436  char *ptr2;
1437  ptr = mpfr_get_str(NULL, &expval, 10, 0, getReadPtr(), GMP_RNDN);
1438  ptr2 = ptr;
1439  iexpval = expval;
1440  if( iexpval!=expval )
1441  // throw internalError();
1442  WerrorS("internalError");
1443  sprintf(buf_e, "%ld", long(iexpval));
1444  if( *ptr=='-' )
1445  {
1446  r = "-";
1447  ptr++;
1448  }
1449  r += "0.";
1450  r += ptr;
1451  r += "E";
1452  r += buf_e;
1453  mpfr_free_str(ptr2);
1454  return r;
1455  }
1456  template<unsigned int Precision>
1457  char * ampf<Precision>::toString() const
1458  {
1459  char *toString_Block=(char *)omAlloc(256);
1460  //
1461  // some special cases
1462  //
1463  if( !isFiniteNumber() )
1464  {
1465  mp_exp_t _e;
1466  char *ptr;
1467  ptr = mpfr_get_str(NULL, &_e, 10, 0, getReadPtr(), GMP_RNDN);
1468  strcpy(toString_Block, ptr);
1469  mpfr_free_str(ptr);
1470  return toString_Block;
1471  }
1472 
1473  //
1474  // general case
1475  //
1476 
1477  char buf_e[128];
1478  signed long iexpval;
1479  mp_exp_t expval;
1480  char *ptr;
1481  char *ptr2;
1482  ptr = mpfr_get_str(NULL, &expval, 10, 0, getReadPtr(), GMP_RNDN);
1483  ptr2 = ptr;
1484  iexpval = expval;
1485  if( iexpval!=expval )
1486  //throw internalError();
1487  WerrorS("internalError");
1488  sprintf(buf_e, "%ld", long(iexpval));
1489  if( *ptr=='-' )
1490  {
1491  ptr++;
1492  sprintf(toString_Block,"-0.%sE%s",ptr,buf_e);
1493  }
1494  else
1495  sprintf(toString_Block,"0.%sE%s",ptr,buf_e);
1496  mpfr_free_str(ptr2);
1497  return toString_Block;
1498  }
1499 
1500  template<unsigned int Precision>
1502  {
1503  if( !x.isFiniteNumber() )
1504  return x;
1505  if( x.isZero() )
1506  return x;
1507  ampf<Precision> r(1);
1508  mpfr_nextabove(r.getWritePtr());
1509  mpfr_sub_ui(r.getWritePtr(), r.getWritePtr(), 1, GMP_RNDN);
1510  mpfr_mul_2si(
1511  r.getWritePtr(),
1512  r.getWritePtr(),
1513  mpfr_get_exp(x.getReadPtr()),
1514  GMP_RNDN);
1515  mpfr_div_2si(
1516  r.getWritePtr(),
1517  r.getWritePtr(),
1518  1,
1519  GMP_RNDN);
1520  return r;
1521  }
1522 
1523  template<unsigned int Precision>
1525  {
1526  ampf<Precision> r(1);
1527  mpfr_nextabove(r.getWritePtr());
1528  mpfr_sub_ui(r.getWritePtr(), r.getWritePtr(), 1, GMP_RNDN);
1529  return r;
1530  }
1531 
1532  template<unsigned int Precision>
1534  {
1535  ampf<Precision> r(1);
1536  mpfr_nextabove(r.getWritePtr());
1537  mpfr_sub_ui(r.getWritePtr(), r.getWritePtr(), 1, GMP_RNDN);
1538  mpfr_mul_2si(
1539  r.getWritePtr(),
1540  r.getWritePtr(),
1541  8,
1542  GMP_RNDN);
1543  return r;
1544  }
1545 
1546  template<unsigned int Precision>
1548  {
1549  ampf<Precision> r(1);
1550  mpfr_nextabove(r.getWritePtr());
1551  mpfr_sub_ui(r.getWritePtr(), r.getWritePtr(), 1, GMP_RNDN);
1552  mpfr_mul_2si(
1553  r.getWritePtr(),
1554  r.getWritePtr(),
1555  9,
1556  GMP_RNDN);
1557  return r;
1558  }
1559 
1560  template<unsigned int Precision>
1562  {
1563  ampf<Precision> r(1);
1564  mpfr_nextbelow(r.getWritePtr());
1565  mpfr_set_exp(r.getWritePtr(),mpfr_get_emax());
1566  return r;
1567  }
1568 
1569  template<unsigned int Precision>
1571  {
1572  ampf<Precision> r(1);
1573  mpfr_set_exp(r.getWritePtr(),mpfr_get_emin());
1574  return r;
1575  }
1576 
1577  template<unsigned int Precision>
1579  {
1580  return getUlp256();
1581  }
1582 
1583  template<unsigned int Precision>
1585  {
1586  ampf<Precision> r(1);
1587  mp_exp_t e1 = mpfr_get_emax();
1588  mp_exp_t e2 = -mpfr_get_emin();
1589  mp_exp_t e = e1>e2 ? e1 : e2;
1590  mpfr_set_exp(r.getWritePtr(), e-5);
1591  return r;
1592  }
1593 
1594  template<unsigned int Precision>
1596  {
1597  ampf<Precision> r(1);
1598  mp_exp_t e1 = mpfr_get_emax();
1599  mp_exp_t e2 = -mpfr_get_emin();
1600  mp_exp_t e = e1>e2 ? e1 : e2;
1601  mpfr_set_exp(r.getWritePtr(), 2-(e-5));
1602  return r;
1603  }
1604 
1605  template<unsigned int Precision>
1607  {
1608  ampf<Precision> r;
1609  while(mpfr_urandomb(r.getWritePtr(), *amp::mpfr_storage::getRandState()));
1610  return r;
1611  }
1612 
1613  //
1614  // comparison operators
1615  //
1616  template<unsigned int Precision>
1617  bool operator==(const ampf<Precision>& op1, const ampf<Precision>& op2)
1618  {
1619  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())==0;
1620  }
1621 
1622  template<unsigned int Precision>
1623  bool operator!=(const ampf<Precision>& op1, const ampf<Precision>& op2)
1624  {
1625  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())!=0;
1626  }
1627 
1628  template<unsigned int Precision>
1629  bool operator<(const ampf<Precision>& op1, const ampf<Precision>& op2)
1630  {
1631  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())<0;
1632  }
1633 
1634  template<unsigned int Precision>
1635  bool operator>(const ampf<Precision>& op1, const ampf<Precision>& op2)
1636  {
1637  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())>0;
1638  }
1639 
1640  template<unsigned int Precision>
1641  bool operator<=(const ampf<Precision>& op1, const ampf<Precision>& op2)
1642  {
1643  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())<=0;
1644  }
1645 
1646  template<unsigned int Precision>
1647  bool operator>=(const ampf<Precision>& op1, const ampf<Precision>& op2)
1648  {
1649  return mpfr_cmp(op1.getReadPtr(), op2.getReadPtr())>=0;
1650  }
1651 
1652  //
1653  // arithmetic operators
1654  //
1655  template<unsigned int Precision>
1656  const ampf<Precision> operator+(const ampf<Precision>& op1)
1657  {
1658  return op1;
1659  }
1660 
1661  template<unsigned int Precision>
1662  const ampf<Precision> operator-(const ampf<Precision>& op1)
1663  {
1664  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1665  mpfr_neg(v->value, op1.getReadPtr(), GMP_RNDN);
1666  return v;
1667  }
1668 
1669  template<unsigned int Precision>
1670  const ampf<Precision> operator+(const ampf<Precision>& op1, const ampf<Precision>& op2)
1671  {
1672  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1673  mpfr_add(v->value, op1.getReadPtr(), op2.getReadPtr(), GMP_RNDN);
1674  return v;
1675  }
1676 
1677  template<unsigned int Precision>
1678  const ampf<Precision> operator-(const ampf<Precision>& op1, const ampf<Precision>& op2)
1679  {
1680  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1681  mpfr_sub(v->value, op1.getReadPtr(), op2.getReadPtr(), GMP_RNDN);
1682  return v;
1683  }
1684 
1685 
1686  template<unsigned int Precision>
1687  const ampf<Precision> operator*(const ampf<Precision>& op1, const ampf<Precision>& op2)
1688  {
1689  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1690  mpfr_mul(v->value, op1.getReadPtr(), op2.getReadPtr(), GMP_RNDN);
1691  return v;
1692  }
1693 
1694  template<unsigned int Precision>
1695  const ampf<Precision> operator/(const ampf<Precision>& op1, const ampf<Precision>& op2)
1696  {
1697  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1698  mpfr_div(v->value, op1.getReadPtr(), op2.getReadPtr(), GMP_RNDN);
1699  return v;
1700  }
1701 
1702  //
1703  // basic functions
1704  //
1705  template<unsigned int Precision>
1706  const ampf<Precision> sqr(const ampf<Precision> &x)
1707  {
1708  // TODO: optimize temporary for return value
1710  mpfr_sqr(res.getWritePtr(), x.getReadPtr(), GMP_RNDN);
1711  return res;
1712  }
1713 
1714  template<unsigned int Precision>
1715  int sign(const ampf<Precision> &x)
1716  {
1717  int s = mpfr_sgn(x.getReadPtr());
1718  if( s>0 )
1719  return +1;
1720  if( s<0 )
1721  return -1;
1722  return 0;
1723  }
1724 
1725  template<unsigned int Precision>
1726  const ampf<Precision> abs(const ampf<Precision> &x)
1727  {
1728  // TODO: optimize temporary for return value
1730  mpfr_abs(res.getWritePtr(), x.getReadPtr(), GMP_RNDN);
1731  return res;
1732  }
1733 
1734  template<unsigned int Precision>
1735  const ampf<Precision> maximum(const ampf<Precision> &x, const ampf<Precision> &y)
1736  {
1737  // TODO: optimize temporary for return value
1739  mpfr_max(res.getWritePtr(), x.getReadPtr(), y.getReadPtr(), GMP_RNDN);
1740  return res;
1741  }
1742 
1743  template<unsigned int Precision>
1744  const ampf<Precision> minimum(const ampf<Precision> &x, const ampf<Precision> &y)
1745  {
1746  // TODO: optimize temporary for return value
1748  mpfr_min(res.getWritePtr(), x.getReadPtr(), y.getReadPtr(), GMP_RNDN);
1749  return res;
1750  }
1751 
1752  template<unsigned int Precision>
1753  const ampf<Precision> sqrt(const ampf<Precision> &x)
1754  {
1755  // TODO: optimize temporary for return value
1757  mpfr_sqrt(res.getWritePtr(), x.getReadPtr(), GMP_RNDN);
1758  return res;
1759  }
1760 
1761  template<unsigned int Precision>
1762  signed long trunc(const ampf<Precision> &x)
1763  {
1764  ampf<Precision> tmp;
1765  signed long r;
1766  mpfr_trunc(tmp.getWritePtr(), x.getReadPtr());
1767  if( mpfr_integer_p(tmp.getReadPtr())==0 )
1768  //throw invalidConversion();
1769  WerrorS("internalError");
1770  mpfr_clear_erangeflag();
1771  r = mpfr_get_si(tmp.getReadPtr(), GMP_RNDN);
1772  if( mpfr_erangeflag_p()!=0 )
1773  //throw invalidConversion();
1774  WerrorS("internalError");
1775  return r;
1776  }
1777 
1778  template<unsigned int Precision>
1779  const ampf<Precision> frac(const ampf<Precision> &x)
1780  {
1781  // TODO: optimize temporary for return value
1782  ampf<Precision> r;
1783  mpfr_frac(r.getWritePtr(), x.getReadPtr(), GMP_RNDN);
1784  return r;
1785  }
1786 
1787  template<unsigned int Precision>
1788  signed long floor(const ampf<Precision> &x)
1789  {
1790  ampf<Precision> tmp;
1791  signed long r;
1792  mpfr_floor(tmp.getWritePtr(), x.getReadPtr());
1793  if( mpfr_integer_p(tmp.getReadPtr())==0 )
1794  //throw invalidConversion();
1795  WerrorS("internalError");
1796  mpfr_clear_erangeflag();
1797  r = mpfr_get_si(tmp.getReadPtr(), GMP_RNDN);
1798  if( mpfr_erangeflag_p()!=0 )
1799  //throw invalidConversion();
1800  WerrorS("internalError");
1801  return r;
1802  }
1803 
1804  template<unsigned int Precision>
1805  signed long ceil(const ampf<Precision> &x)
1806  {
1807  ampf<Precision> tmp;
1808  signed long r;
1809  mpfr_ceil(tmp.getWritePtr(), x.getReadPtr());
1810  if( mpfr_integer_p(tmp.getReadPtr())==0 )
1811  //throw invalidConversion();
1812  WerrorS("internalError");
1813  mpfr_clear_erangeflag();
1814  r = mpfr_get_si(tmp.getReadPtr(), GMP_RNDN);
1815  if( mpfr_erangeflag_p()!=0 )
1816  //throw invalidConversion();
1817  WerrorS("internalError");
1818  return r;
1819  }
1820 
1821  template<unsigned int Precision>
1822  signed long round(const ampf<Precision> &x)
1823  {
1824  ampf<Precision> tmp;
1825  signed long r;
1826  mpfr_round(tmp.getWritePtr(), x.getReadPtr());
1827  if( mpfr_integer_p(tmp.getReadPtr())==0 )
1828  //throw invalidConversion();
1829  WerrorS("internalError");
1830  mpfr_clear_erangeflag();
1831  r = mpfr_get_si(tmp.getReadPtr(), GMP_RNDN);
1832  if( mpfr_erangeflag_p()!=0 )
1833  //throw invalidConversion();
1834  WerrorS("internalError");
1835  return r;
1836  }
1837 
1838  template<unsigned int Precision>
1839  const ampf<Precision> frexp2(const ampf<Precision> &x, mp_exp_t *exponent)
1840  {
1841  // TODO: optimize temporary for return value
1842  ampf<Precision> r;
1843  if( !x.isFiniteNumber() )
1844  //throw invalidConversion();
1845  WerrorS("internalError");
1846  if( x.isZero() )
1847  {
1848  *exponent = 0;
1849  r = 0;
1850  return r;
1851  }
1852  r = x;
1853  *exponent = mpfr_get_exp(r.getReadPtr());
1854  mpfr_set_exp(r.getWritePtr(),0);
1855  return r;
1856  }
1857 
1858  template<unsigned int Precision>
1859  const ampf<Precision> ldexp2(const ampf<Precision> &x, mp_exp_t exponent)
1860  {
1861  // TODO: optimize temporary for return value
1862  ampf<Precision> r;
1863  mpfr_mul_2si(r.getWritePtr(), x.getReadPtr(), exponent, GMP_RNDN);
1864  return r;
1865  }
1866 
1867  //
1868  // different types of arguments
1869  //
1870  #define __AMP_BINARY_OPI(type) \
1871  template<unsigned int Precision> const ampf<Precision> operator+(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)+op2; } \
1872  template<unsigned int Precision> const ampf<Precision> operator+(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)+op2; } \
1873  template<unsigned int Precision> const ampf<Precision> operator+(const ampf<Precision>& op1, const signed type& op2) { return op1+ampf<Precision>(op2); } \
1874  template<unsigned int Precision> const ampf<Precision> operator+(const ampf<Precision>& op1, const unsigned type& op2) { return op1+ampf<Precision>(op2); } \
1875  template<unsigned int Precision> const ampf<Precision> operator-(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)-op2; } \
1876  template<unsigned int Precision> const ampf<Precision> operator-(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)-op2; } \
1877  template<unsigned int Precision> const ampf<Precision> operator-(const ampf<Precision>& op1, const signed type& op2) { return op1-ampf<Precision>(op2); } \
1878  template<unsigned int Precision> const ampf<Precision> operator-(const ampf<Precision>& op1, const unsigned type& op2) { return op1-ampf<Precision>(op2); } \
1879  template<unsigned int Precision> const ampf<Precision> operator*(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)*op2; } \
1880  template<unsigned int Precision> const ampf<Precision> operator*(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)*op2; } \
1881  template<unsigned int Precision> const ampf<Precision> operator*(const ampf<Precision>& op1, const signed type& op2) { return op1*ampf<Precision>(op2); } \
1882  template<unsigned int Precision> const ampf<Precision> operator*(const ampf<Precision>& op1, const unsigned type& op2) { return op1*ampf<Precision>(op2); } \
1883  template<unsigned int Precision> const ampf<Precision> operator/(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)/op2; } \
1884  template<unsigned int Precision> const ampf<Precision> operator/(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)/op2; } \
1885  template<unsigned int Precision> const ampf<Precision> operator/(const ampf<Precision>& op1, const signed type& op2) { return op1/ampf<Precision>(op2); } \
1886  template<unsigned int Precision> const ampf<Precision> operator/(const ampf<Precision>& op1, const unsigned type& op2) { return op1/ampf<Precision>(op2); } \
1887  template<unsigned int Precision> bool operator==(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)==op2; } \
1888  template<unsigned int Precision> bool operator==(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)==op2; } \
1889  template<unsigned int Precision> bool operator==(const ampf<Precision>& op1, const signed type& op2) { return op1==ampf<Precision>(op2); } \
1890  template<unsigned int Precision> bool operator==(const ampf<Precision>& op1, const unsigned type& op2) { return op1==ampf<Precision>(op2); } \
1891  template<unsigned int Precision> bool operator!=(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)!=op2; } \
1892  template<unsigned int Precision> bool operator!=(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)!=op2; } \
1893  template<unsigned int Precision> bool operator!=(const ampf<Precision>& op1, const signed type& op2) { return op1!=ampf<Precision>(op2); } \
1894  template<unsigned int Precision> bool operator!=(const ampf<Precision>& op1, const unsigned type& op2) { return op1!=ampf<Precision>(op2); } \
1895  template<unsigned int Precision> bool operator<=(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<=op2; } \
1896  template<unsigned int Precision> bool operator<=(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<=op2; } \
1897  template<unsigned int Precision> bool operator<=(const ampf<Precision>& op1, const signed type& op2) { return op1<=ampf<Precision>(op2); } \
1898  template<unsigned int Precision> bool operator<=(const ampf<Precision>& op1, const unsigned type& op2) { return op1<=ampf<Precision>(op2); } \
1899  template<unsigned int Precision> bool operator>=(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>=op2; } \
1900  template<unsigned int Precision> bool operator>=(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>=op2; } \
1901  template<unsigned int Precision> bool operator>=(const ampf<Precision>& op1, const signed type& op2) { return op1>=ampf<Precision>(op2); } \
1902  template<unsigned int Precision> bool operator>=(const ampf<Precision>& op1, const unsigned type& op2) { return op1>=ampf<Precision>(op2); } \
1903  template<unsigned int Precision> bool operator<(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<op2; } \
1904  template<unsigned int Precision> bool operator<(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<op2; } \
1905  template<unsigned int Precision> bool operator<(const ampf<Precision>& op1, const signed type& op2) { return op1<ampf<Precision>(op2); } \
1906  template<unsigned int Precision> bool operator<(const ampf<Precision>& op1, const unsigned type& op2) { return op1<ampf<Precision>(op2); } \
1907  template<unsigned int Precision> bool operator>(const signed type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>op2; } \
1908  template<unsigned int Precision> bool operator>(const unsigned type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>op2; } \
1909  template<unsigned int Precision> bool operator>(const ampf<Precision>& op1, const signed type& op2) { return op1>ampf<Precision>(op2); } \
1910  template<unsigned int Precision> bool operator>(const ampf<Precision>& op1, const unsigned type& op2) { return op1>ampf<Precision>(op2); }
1911  __AMP_BINARY_OPI(char)
1912  __AMP_BINARY_OPI(short)
1913  __AMP_BINARY_OPI(long)
1914  __AMP_BINARY_OPI(int)
1915  #undef __AMP_BINARY_OPI
1916  #define __AMP_BINARY_OPF(type) \
1917  template<unsigned int Precision> const ampf<Precision> operator+(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)+op2; } \
1918  template<unsigned int Precision> const ampf<Precision> operator+(const ampf<Precision>& op1, const type& op2) { return op1+ampf<Precision>(op2); } \
1919  template<unsigned int Precision> const ampf<Precision> operator-(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)-op2; } \
1920  template<unsigned int Precision> const ampf<Precision> operator-(const ampf<Precision>& op1, const type& op2) { return op1-ampf<Precision>(op2); } \
1921  template<unsigned int Precision> const ampf<Precision> operator*(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)*op2; } \
1922  template<unsigned int Precision> const ampf<Precision> operator*(const ampf<Precision>& op1, const type& op2) { return op1*ampf<Precision>(op2); } \
1923  template<unsigned int Precision> const ampf<Precision> operator/(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)/op2; } \
1924  template<unsigned int Precision> const ampf<Precision> operator/(const ampf<Precision>& op1, const type& op2) { return op1/ampf<Precision>(op2); } \
1925  template<unsigned int Precision> bool operator==(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)==op2; } \
1926  template<unsigned int Precision> bool operator==(const ampf<Precision>& op1, const type& op2) { return op1==ampf<Precision>(op2); } \
1927  template<unsigned int Precision> bool operator!=(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)!=op2; } \
1928  template<unsigned int Precision> bool operator!=(const ampf<Precision>& op1, const type& op2) { return op1!=ampf<Precision>(op2); } \
1929  template<unsigned int Precision> bool operator<=(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<=op2; } \
1930  template<unsigned int Precision> bool operator<=(const ampf<Precision>& op1, const type& op2) { return op1<=ampf<Precision>(op2); } \
1931  template<unsigned int Precision> bool operator>=(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>=op2; } \
1932  template<unsigned int Precision> bool operator>=(const ampf<Precision>& op1, const type& op2) { return op1>=ampf<Precision>(op2); } \
1933  template<unsigned int Precision> bool operator<(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)<op2; } \
1934  template<unsigned int Precision> bool operator<(const ampf<Precision>& op1, const type& op2) { return op1<ampf<Precision>(op2); } \
1935  template<unsigned int Precision> bool operator>(const type& op1, const ampf<Precision>& op2) { return ampf<Precision>(op1)>op2; } \
1936  template<unsigned int Precision> bool operator>(const ampf<Precision>& op1, const type& op2) { return op1>ampf<Precision>(op2); }
1937  __AMP_BINARY_OPF(float)
1938  __AMP_BINARY_OPF(double)
1939  __AMP_BINARY_OPF(long double)
1940  #undef __AMP_BINARY_OPF
1941 
1942  //
1943  // transcendent functions
1944  //
1945  template<unsigned int Precision>
1946  const ampf<Precision> pi()
1947  {
1948  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1949  mpfr_const_pi(v->value, GMP_RNDN);
1950  return v;
1951  }
1952 
1953  template<unsigned int Precision>
1954  const ampf<Precision> halfpi()
1955  {
1956  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1957  mpfr_const_pi(v->value, GMP_RNDN);
1958  mpfr_mul_2si(v->value, v->value, -1, GMP_RNDN);
1959  return v;
1960  }
1961 
1962  template<unsigned int Precision>
1963  const ampf<Precision> twopi()
1964  {
1965  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1966  mpfr_const_pi(v->value, GMP_RNDN);
1967  mpfr_mul_2si(v->value, v->value, +1, GMP_RNDN);
1968  return v;
1969  }
1970 
1971  template<unsigned int Precision>
1972  const ampf<Precision> sin(const ampf<Precision> &x)
1973  {
1974  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1975  mpfr_sin(v->value, x.getReadPtr(), GMP_RNDN);
1976  return v;
1977  }
1978 
1979  template<unsigned int Precision>
1980  const ampf<Precision> cos(const ampf<Precision> &x)
1981  {
1982  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1983  mpfr_cos(v->value, x.getReadPtr(), GMP_RNDN);
1984  return v;
1985  }
1986 
1987  template<unsigned int Precision>
1988  const ampf<Precision> tan(const ampf<Precision> &x)
1989  {
1990  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1991  mpfr_tan(v->value, x.getReadPtr(), GMP_RNDN);
1992  return v;
1993  }
1994 
1995  template<unsigned int Precision>
1996  const ampf<Precision> asin(const ampf<Precision> &x)
1997  {
1998  mpfr_record *v = mpfr_storage::newMpfr(Precision);
1999  mpfr_asin(v->value, x.getReadPtr(), GMP_RNDN);
2000  return v;
2001  }
2002 
2003  template<unsigned int Precision>
2004  const ampf<Precision> acos(const ampf<Precision> &x)
2005  {
2006  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2007  mpfr_acos(v->value, x.getReadPtr(), GMP_RNDN);
2008  return v;
2009  }
2010 
2011  template<unsigned int Precision>
2012  const ampf<Precision> atan(const ampf<Precision> &x)
2013  {
2014  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2015  mpfr_atan(v->value, x.getReadPtr(), GMP_RNDN);
2016  return v;
2017  }
2018 
2019  template<unsigned int Precision>
2020  const ampf<Precision> atan2(const ampf<Precision> &y, const ampf<Precision> &x)
2021  {
2022  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2023  mpfr_atan2(v->value, y.getReadPtr(), x.getReadPtr(), GMP_RNDN);
2024  return v;
2025  }
2026 
2027  template<unsigned int Precision>
2028  const ampf<Precision> log(const ampf<Precision> &x)
2029  {
2030  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2031  mpfr_log(v->value, x.getReadPtr(), GMP_RNDN);
2032  return v;
2033  }
2034 
2035  template<unsigned int Precision>
2036  const ampf<Precision> log2(const ampf<Precision> &x)
2037  {
2038  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2039  mpfr_log2(v->value, x.getReadPtr(), GMP_RNDN);
2040  return v;
2041  }
2042 
2043  template<unsigned int Precision>
2044  const ampf<Precision> log10(const ampf<Precision> &x)
2045  {
2046  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2047  mpfr_log10(v->value, x.getReadPtr(), GMP_RNDN);
2048  return v;
2049  }
2050 
2051  template<unsigned int Precision>
2052  const ampf<Precision> exp(const ampf<Precision> &x)
2053  {
2054  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2055  mpfr_exp(v->value, x.getReadPtr(), GMP_RNDN);
2056  return v;
2057  }
2058 
2059  template<unsigned int Precision>
2060  const ampf<Precision> sinh(const ampf<Precision> &x)
2061  {
2062  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2063  mpfr_sinh(v->value, x.getReadPtr(), GMP_RNDN);
2064  return v;
2065  }
2066 
2067  template<unsigned int Precision>
2068  const ampf<Precision> cosh(const ampf<Precision> &x)
2069  {
2070  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2071  mpfr_cosh(v->value, x.getReadPtr(), GMP_RNDN);
2072  return v;
2073  }
2074 
2075  template<unsigned int Precision>
2076  const ampf<Precision> tanh(const ampf<Precision> &x)
2077  {
2078  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2079  mpfr_tanh(v->value, x.getReadPtr(), GMP_RNDN);
2080  return v;
2081  }
2082 
2083  template<unsigned int Precision>
2084  const ampf<Precision> pow(const ampf<Precision> &x, const ampf<Precision> &y)
2085  {
2086  mpfr_record *v = mpfr_storage::newMpfr(Precision);
2087  mpfr_pow(v->value, x.getReadPtr(), y.getReadPtr(), GMP_RNDN);
2088  return v;
2089  }
2090 
2091  //
2092  // complex ampf
2093  //
2094  template<unsigned int Precision>
2095  class campf
2096  {
2097  public:
2098  campf():x(0),y(0){};
2099  campf(long double v) { x=v; y=0; }
2100  campf(double v) { x=v; y=0; }
2101  campf(float v) { x=v; y=0; }
2102  campf(signed long v) { x=v; y=0; }
2103  campf(unsigned long v) { x=v; y=0; }
2104  campf(signed int v) { x=v; y=0; }
2105  campf(unsigned int v) { x=v; y=0; }
2106  campf(signed short v) { x=v; y=0; }
2107  campf(unsigned short v) { x=v; y=0; }
2108  campf(signed char v) { x=v; y=0; }
2109  campf(unsigned char v) { x=v; y=0; }
2110  campf(const ampf<Precision> &_x):x(_x),y(0){};
2111  campf(const ampf<Precision> &_x, const ampf<Precision> &_y):x(_x),y(_y){};
2112  campf(const campf &z):x(z.x),y(z.y){};
2113 #ifndef _AMP_NO_TEMPLATE_CONSTRUCTORS
2114  template<unsigned int Prec2>
2115  campf(const campf<Prec2> &z):x(z.x),y(z.y){};
2116 #endif
2117 
2118  campf& operator= (long double v) { x=v; y=0; return *this; }
2119  campf& operator= (double v) { x=v; y=0; return *this; }
2120  campf& operator= (float v) { x=v; y=0; return *this; }
2121  campf& operator= (signed long v) { x=v; y=0; return *this; }
2122  campf& operator= (unsigned long v) { x=v; y=0; return *this; }
2123  campf& operator= (signed int v) { x=v; y=0; return *this; }
2124  campf& operator= (unsigned int v) { x=v; y=0; return *this; }
2125  campf& operator= (signed short v) { x=v; y=0; return *this; }
2126  campf& operator= (unsigned short v) { x=v; y=0; return *this; }
2127  campf& operator= (signed char v) { x=v; y=0; return *this; }
2128  campf& operator= (unsigned char v) { x=v; y=0; return *this; }
2129  campf& operator= (const char *s) { x=s; y=0; return *this; }
2130  campf& operator= (const std::string &s) { x=s; y=0; return *this; }
2131  campf& operator= (const campf& r)
2132  {
2133  x = r.x;
2134  y = r.y;
2135  return *this;
2136  }
2137 #ifndef _AMP_NO_TEMPLATE_CONSTRUCTORS
2138  template<unsigned int Precision2>
2139  campf& operator= (const campf<Precision2>& r)
2140  {
2141  x = r.x;
2142  y = r.y;
2143  return *this;
2144  }
2145 #endif
2146 
2147  ampf<Precision> x, y;
2148  };
2149 
2150  //
2151  // complex operations
2152  //
2153  template<unsigned int Precision>
2154  bool operator==(const campf<Precision>& lhs, const campf<Precision>& rhs)
2155  { return lhs.x==rhs.x && lhs.y==rhs.y; }
2156 
2157  template<unsigned int Precision>
2158  bool operator!=(const campf<Precision>& lhs, const campf<Precision>& rhs)
2159  { return lhs.x!=rhs.x || lhs.y!=rhs.y; }
2160 
2161  template<unsigned int Precision>
2162  const campf<Precision> operator+(const campf<Precision>& lhs)
2163  { return lhs; }
2164 
2165  template<unsigned int Precision>
2167  { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
2168 
2169  template<unsigned int Precision>
2170  const campf<Precision> operator+(const campf<Precision>& lhs, const campf<Precision>& rhs)
2171  { campf<Precision> r = lhs; r += rhs; return r; }
2172 
2173  template<unsigned int Precision>
2174  const campf<Precision> operator-(const campf<Precision>& lhs)
2175  { return campf<Precision>(-lhs.x, -lhs.y); }
2176 
2177  template<unsigned int Precision>
2179  { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
2180 
2181  template<unsigned int Precision>
2182  const campf<Precision> operator-(const campf<Precision>& lhs, const campf<Precision>& rhs)
2183  { campf<Precision> r = lhs; r -= rhs; return r; }
2184 
2185  template<unsigned int Precision>
2187  {
2188  ampf<Precision> xx(lhs.x*rhs.x), yy(lhs.y*rhs.y), mm((lhs.x+lhs.y)*(rhs.x+rhs.y));
2189  lhs.x = xx-yy;
2190  lhs.y = mm-xx-yy;
2191  return lhs;
2192  }
2193 
2194  template<unsigned int Precision>
2195  const campf<Precision> operator*(const campf<Precision>& lhs, const campf<Precision>& rhs)
2196  { campf<Precision> r = lhs; r *= rhs; return r; }
2197 
2198  template<unsigned int Precision>
2199  const campf<Precision> operator/(const campf<Precision>& lhs, const campf<Precision>& rhs)
2200  {
2202  ampf<Precision> e;
2204  if( abs(rhs.y)<abs(rhs.x) )
2205  {
2206  e = rhs.y/rhs.x;
2207  f = rhs.x+rhs.y*e;
2208  result.x = (lhs.x+lhs.y*e)/f;
2209  result.y = (lhs.y-lhs.x*e)/f;
2210  }
2211  else
2212  {
2213  e = rhs.x/rhs.y;
2214  f = rhs.y+rhs.x*e;
2215  result.x = (lhs.y+lhs.x*e)/f;
2216  result.y = (-lhs.x+lhs.y*e)/f;
2217  }
2218  return result;
2219  }
2220 
2221  template<unsigned int Precision>
2223  {
2224  lhs = lhs/rhs;
2225  return lhs;
2226  }
2227 
2228  template<unsigned int Precision>
2230  {
2231  ampf<Precision> w, xabs, yabs, v;
2232 
2233  xabs = abs(z.x);
2234  yabs = abs(z.y);
2235  w = xabs>yabs ? xabs : yabs;
2236  v = xabs<yabs ? xabs : yabs;
2237  if( v==0 )
2238  return w;
2239  else
2240  {
2241  ampf<Precision> t = v/w;
2242  return w*sqrt(1+sqr(t));
2243  }
2244  }
2245 
2246  template<unsigned int Precision>
2247  const campf<Precision> conj(const campf<Precision> &z)
2248  {
2249  return campf<Precision>(z.x, -z.y);
2250  }
2251 
2252  template<unsigned int Precision>
2253  const campf<Precision> csqr(const campf<Precision> &z)
2254  {
2255  ampf<Precision> t = z.x*z.y;
2256  return campf<Precision>(sqr(z.x)-sqr(z.y), t+t);
2257  }
2258 
2259  //
2260  // different types of arguments
2261  //
2262  #define __AMP_BINARY_OPI(type) \
2263  template<unsigned int Precision> const campf<Precision> operator+ (const signed type& op1, const campf<Precision>& op2) { return campf<Precision>(op1+op2.x, op2.y); } \
2264  template<unsigned int Precision> const campf<Precision> operator+ (const unsigned type& op1, const campf<Precision>& op2) { return campf<Precision>(op1+op2.x, op2.y); } \
2265  template<unsigned int Precision> const campf<Precision> operator+ (const campf<Precision>& op1, const signed type& op2) { return campf<Precision>(op1.x+op2, op1.y); } \
2266  template<unsigned int Precision> const campf<Precision> operator+ (const campf<Precision>& op1, const unsigned type& op2) { return campf<Precision>(op1.x+op2, op1.y); } \
2267  template<unsigned int Precision> const campf<Precision> operator- (const signed type& op1, const campf<Precision>& op2) { return campf<Precision>(op1-op2.x, -op2.y); } \
2268  template<unsigned int Precision> const campf<Precision> operator- (const unsigned type& op1, const campf<Precision>& op2) { return campf<Precision>(op1-op2.x, -op2.y); } \
2269  template<unsigned int Precision> const campf<Precision> operator- (const campf<Precision>& op1, const signed type& op2) { return campf<Precision>(op1.x-op2, op1.y); } \
2270  template<unsigned int Precision> const campf<Precision> operator- (const campf<Precision>& op1, const unsigned type& op2) { return campf<Precision>(op1.x-op2, op1.y); } \
2271  template<unsigned int Precision> const campf<Precision> operator* (const signed type& op1, const campf<Precision>& op2) { return campf<Precision>(op1*op2.x, op1*op2.y); } \
2272  template<unsigned int Precision> const campf<Precision> operator* (const unsigned type& op1, const campf<Precision>& op2) { return campf<Precision>(op1*op2.x, op1*op2.y); } \
2273  template<unsigned int Precision> const campf<Precision> operator* (const campf<Precision>& op1, const signed type& op2) { return campf<Precision>(op2*op1.x, op2*op1.y); } \
2274  template<unsigned int Precision> const campf<Precision> operator* (const campf<Precision>& op1, const unsigned type& op2) { return campf<Precision>(op2*op1.x, op2*op1.y); } \
2275  template<unsigned int Precision> const campf<Precision> operator/ (const signed type& op1, const campf<Precision>& op2) { return campf<Precision>(ampf<Precision>(op1),ampf<Precision>(0))/op2; } \
2276  template<unsigned int Precision> const campf<Precision> operator/ (const unsigned type& op1, const campf<Precision>& op2) { return campf<Precision>(ampf<Precision>(op1),ampf<Precision>(0))/op2; } \
2277  template<unsigned int Precision> const campf<Precision> operator/ (const campf<Precision>& op1, const signed type& op2) { return campf<Precision>(op1.x/op2, op1.y/op2); } \
2278  template<unsigned int Precision> const campf<Precision> operator/ (const campf<Precision>& op1, const unsigned type& op2) { return campf<Precision>(op1.x/op2, op1.y/op2); } \
2279  template<unsigned int Precision> bool operator==(const signed type& op1, const campf<Precision>& op2) { return op1==op2.x && op2.y==0; } \
2280  template<unsigned int Precision> bool operator==(const unsigned type& op1, const campf<Precision>& op2) { return op1==op2.x && op2.y==0; } \
2281  template<unsigned int Precision> bool operator==(const campf<Precision>& op1, const signed type& op2) { return op1.x==op2 && op1.y==0; } \
2282  template<unsigned int Precision> bool operator==(const campf<Precision>& op1, const unsigned type& op2) { return op1.x==op2 && op1.y==0; } \
2283  template<unsigned int Precision> bool operator!=(const campf<Precision>& op1, const signed type& op2) { return op1.x!=op2 || op1.y!=0; } \
2284  template<unsigned int Precision> bool operator!=(const campf<Precision>& op1, const unsigned type& op2) { return op1.x!=op2 || op1.y!=0; } \
2285  template<unsigned int Precision> bool operator!=(const signed type& op1, const campf<Precision>& op2) { return op1!=op2.x || op2.y!=0; } \
2286  template<unsigned int Precision> bool operator!=(const unsigned type& op1, const campf<Precision>& op2) { return op1!=op2.x || op2.y!=0; }
2287  __AMP_BINARY_OPI(char)
2288  __AMP_BINARY_OPI(short)
2289  __AMP_BINARY_OPI(long)
2290  __AMP_BINARY_OPI(int)
2291  #undef __AMP_BINARY_OPI
2292  #define __AMP_BINARY_OPF(type) \
2293  template<unsigned int Precision> const campf<Precision> operator+ (const type& op1, const campf<Precision>& op2) { return campf<Precision>(op1+op2.x, op2.y); } \
2294  template<unsigned int Precision> const campf<Precision> operator+ (const campf<Precision>& op1, const type& op2) { return campf<Precision>(op1.x+op2, op1.y); } \
2295  template<unsigned int Precision> const campf<Precision> operator- (const type& op1, const campf<Precision>& op2) { return campf<Precision>(op1-op2.x, -op2.y); } \
2296  template<unsigned int Precision> const campf<Precision> operator- (const campf<Precision>& op1, const type& op2) { return campf<Precision>(op1.x-op2, op1.y); } \
2297  template<unsigned int Precision> const campf<Precision> operator* (const type& op1, const campf<Precision>& op2) { return campf<Precision>(op1*op2.x, op1*op2.y); } \
2298  template<unsigned int Precision> const campf<Precision> operator* (const campf<Precision>& op1, const type& op2) { return campf<Precision>(op2*op1.x, op2*op1.y); } \
2299  template<unsigned int Precision> const campf<Precision> operator/ (const type& op1, const campf<Precision>& op2) { return campf<Precision>(ampf<Precision>(op1),ampf<Precision>(0))/op2; } \
2300  template<unsigned int Precision> const campf<Precision> operator/ (const campf<Precision>& op1, const type& op2) { return campf<Precision>(op1.x/op2, op1.y/op2); } \
2301  template<unsigned int Precision> bool operator==(const type& op1, const campf<Precision>& op2) { return op1==op2.x && op2.y==0; } \
2302  template<unsigned int Precision> bool operator==(const campf<Precision>& op1, const type& op2) { return op1.x==op2 && op1.y==0; } \
2303  template<unsigned int Precision> bool operator!=(const type& op1, const campf<Precision>& op2) { return op1!=op2.x || op2.y!=0; } \
2304  template<unsigned int Precision> bool operator!=(const campf<Precision>& op1, const type& op2) { return op1.x!=op2 || op1.y!=0; }
2305  __AMP_BINARY_OPF(float)
2306  __AMP_BINARY_OPF(double)
2307  __AMP_BINARY_OPF(long double)
2308  __AMP_BINARY_OPF(ampf<Precision>)
2309  #undef __AMP_BINARY_OPF
2310 
2311  //
2312  // Real linear algebra
2313  //
2314  template<unsigned int Precision>
2315  ampf<Precision> vDotProduct(ap::const_raw_vector< ampf<Precision> > v1, ap::const_raw_vector< ampf<Precision> > v2)
2316  {
2317  ap::ap_error::make_assertion(v1.GetLength()==v2.GetLength());
2318  int i, cnt = v1.GetLength();
2319  const ampf<Precision> *p1 = v1.GetData();
2320  const ampf<Precision> *p2 = v2.GetData();
2321  mpfr_record *r = NULL;
2322  mpfr_record *t = NULL;
2323  //try
2324  {
2325  r = mpfr_storage::newMpfr(Precision);
2326  t = mpfr_storage::newMpfr(Precision);
2327  mpfr_set_ui(r->value, 0, GMP_RNDN);
2328  for(i=0; i<cnt; i++)
2329  {
2330  mpfr_mul(t->value, p1->getReadPtr(), p2->getReadPtr(), GMP_RNDN);
2331  mpfr_add(r->value, r->value, t->value, GMP_RNDN);
2332  p1 += v1.GetStep();
2333  p2 += v2.GetStep();
2334  }
2335  mpfr_storage::deleteMpfr(t);
2336  return r;
2337  }
2338  //catch(...)
2339  //{
2340  // if( r!=NULL )
2341  // mpfr_storage::deleteMpfr(r);
2342  // if( t!=NULL )
2343  // mpfr_storage::deleteMpfr(t);
2344  // throw;
2345  //}
2346  }
2347 
2348  template<unsigned int Precision>
2349  void vMove(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc)
2350  {
2351  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2352  int i, cnt = vDst.GetLength();
2353  ampf<Precision> *pDst = vDst.GetData();
2354  const ampf<Precision> *pSrc = vSrc.GetData();
2355  if( pDst==pSrc )
2356  return;
2357  for(i=0; i<cnt; i++)
2358  {
2359  *pDst = *pSrc;
2360  pDst += vDst.GetStep();
2361  pSrc += vSrc.GetStep();
2362  }
2363  }
2364 
2365  template<unsigned int Precision>
2366  void vMoveNeg(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc)
2367  {
2368  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2369  int i, cnt = vDst.GetLength();
2370  ampf<Precision> *pDst = vDst.GetData();
2371  const ampf<Precision> *pSrc = vSrc.GetData();
2372  for(i=0; i<cnt; i++)
2373  {
2374  *pDst = *pSrc;
2375  mpfr_ptr v = pDst->getWritePtr();
2376  mpfr_neg(v, v, GMP_RNDN);
2377  pDst += vDst.GetStep();
2378  pSrc += vSrc.GetStep();
2379  }
2380  }
2381 
2382  template<unsigned int Precision, class T2>
2383  void vMove(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc, T2 alpha)
2384  {
2385  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2386  int i, cnt = vDst.GetLength();
2387  ampf<Precision> *pDst = vDst.GetData();
2388  const ampf<Precision> *pSrc = vSrc.GetData();
2389  ampf<Precision> a(alpha);
2390  for(i=0; i<cnt; i++)
2391  {
2392  *pDst = *pSrc;
2393  mpfr_ptr v = pDst->getWritePtr();
2394  mpfr_mul(v, v, a.getReadPtr(), GMP_RNDN);
2395  pDst += vDst.GetStep();
2396  pSrc += vSrc.GetStep();
2397  }
2398  }
2399 
2400  template<unsigned int Precision>
2401  void vAdd(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc)
2402  {
2403  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2404  int i, cnt = vDst.GetLength();
2405  ampf<Precision> *pDst = vDst.GetData();
2406  const ampf<Precision> *pSrc = vSrc.GetData();
2407  for(i=0; i<cnt; i++)
2408  {
2409  mpfr_ptr v = pDst->getWritePtr();
2410  mpfr_srcptr vs = pSrc->getReadPtr();
2411  mpfr_add(v, v, vs, GMP_RNDN);
2412  pDst += vDst.GetStep();
2413  pSrc += vSrc.GetStep();
2414  }
2415  }
2416 
2417  template<unsigned int Precision, class T2>
2418  void vAdd(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc, T2 alpha)
2419  {
2420  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2421  int i, cnt = vDst.GetLength();
2422  ampf<Precision> *pDst = vDst.GetData();
2423  const ampf<Precision> *pSrc = vSrc.GetData();
2424  ampf<Precision> a(alpha), tmp;
2425  for(i=0; i<cnt; i++)
2426  {
2427  mpfr_ptr v = pDst->getWritePtr();
2428  mpfr_srcptr vs = pSrc->getReadPtr();
2429  mpfr_mul(tmp.getWritePtr(), a.getReadPtr(), vs, GMP_RNDN);
2430  mpfr_add(v, v, tmp.getWritePtr(), GMP_RNDN);
2431  pDst += vDst.GetStep();
2432  pSrc += vSrc.GetStep();
2433  }
2434  }
2435 
2436  template<unsigned int Precision>
2437  void vSub(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc)
2438  {
2439  ap::ap_error::make_assertion(vDst.GetLength()==vSrc.GetLength());
2440  int i, cnt = vDst.GetLength();
2441  ampf<Precision> *pDst = vDst.GetData();
2442  const ampf<Precision> *pSrc = vSrc.GetData();
2443  for(i=0; i<cnt; i++)
2444  {
2445  mpfr_ptr v = pDst->getWritePtr();
2446  mpfr_srcptr vs = pSrc->getReadPtr();
2447  mpfr_sub(v, v, vs, GMP_RNDN);
2448  pDst += vDst.GetStep();
2449  pSrc += vSrc.GetStep();
2450  }
2451  }
2452 
2453  template<unsigned int Precision, class T2>
2454  void vSub(ap::raw_vector< ampf<Precision> > vDst, ap::const_raw_vector< ampf<Precision> > vSrc, T2 alpha)
2455  {
2456  vAdd(vDst, vSrc, -alpha);
2457  }
2458 
2459  template<unsigned int Precision, class T2>
2460  void vMul(ap::raw_vector< ampf<Precision> > vDst, T2 alpha)
2461  {
2462  int i, cnt = vDst.GetLength();
2463  ampf<Precision> *pDst = vDst.GetData();
2464  ampf<Precision> a(alpha);
2465  for(i=0; i<cnt; i++)
2466  {
2467  mpfr_ptr v = pDst->getWritePtr();
2468  mpfr_mul(v, a.getReadPtr(), v, GMP_RNDN);
2469  pDst += vDst.GetStep();
2470  }
2471  }
2472 }
2473 
2474 /* stuff included from ./reflections.h */
2475 
2476 /*************************************************************************
2477 Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
2478 
2479 Contributors:
2480  * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
2481  pseudocode.
2482 
2483 See subroutines comments for additional copyrights.
2484 
2485 Redistribution and use in source and binary forms, with or without
2486 modification, are permitted provided that the following conditions are
2487 met:
2488 
2489 - Redistributions of source code must retain the above copyright
2490  notice, this list of conditions and the following disclaimer.
2491 
2492 - Redistributions in binary form must reproduce the above copyright
2493  notice, this list of conditions and the following disclaimer listed
2494  in this license in the documentation and/or other materials
2495  provided with the distribution.
2496 
2497 - Neither the name of the copyright holders nor the names of its
2498  contributors may be used to endorse or promote products derived from
2499  this software without specific prior written permission.
2500 
2501 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2502 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2503 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2504 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2505 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2506 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2507 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2508 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2509 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2511 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2512 *************************************************************************/
2513 
2514 namespace reflections
2515 {
2516  template<unsigned int Precision>
2518  int n,
2520  template<unsigned int Precision>
2524  int m1,
2525  int m2,
2526  int n1,
2527  int n2,
2529  template<unsigned int Precision>
2533  int m1,
2534  int m2,
2535  int n1,
2536  int n2,
2538 
2539 
2540  /*************************************************************************
2541  Generation of an elementary reflection transformation
2542 
2543  The subroutine generates elementary reflection H of order N, so that, for
2544  a given X, the following equality holds true:
2545 
2546  ( X(1) ) ( Beta )
2547  H * ( .. ) = ( 0 )
2548  ( X(n) ) ( 0 )
2549 
2550  where
2551  ( V(1) )
2552  H = 1 - Tau * ( .. ) * ( V(1), ..., V(n) )
2553  ( V(n) )
2554 
2555  where the first component of vector V equals 1.
2556 
2557  Input parameters:
2558  X - vector. Array whose index ranges within [1..N].
2559  N - reflection order.
2560 
2561  Output parameters:
2562  X - components from 2 to N are replaced with vector V.
2563  The first component is replaced with parameter Beta.
2564  Tau - scalar value Tau. If X is a null vector, Tau equals 0,
2565  otherwise 1 <= Tau <= 2.
2566 
2567  This subroutine is the modification of the DLARFG subroutines from
2568  the LAPACK library. It has a similar functionality except for the
2569  cause an overflow.
2570 
2571 
2572  MODIFICATIONS:
2573  24.12.2005 sign(Alpha) was replaced with an analogous to the Fortran SIGN code.
2574 
2575  -- LAPACK auxiliary routine (version 3.0) --
2576  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
2577  Courant Institute, Argonne National Lab, and Rice University
2578  September 30, 1994
2579  *************************************************************************/
2580  template<unsigned int Precision>
2582  int n,
2583  amp::ampf<Precision>& tau)
2584  {
2585  int j;
2587  amp::ampf<Precision> xnorm;
2591 
2592 
2593 
2594  //
2595  // Executable Statements ..
2596  //
2597  if( n<=1 )
2598  {
2599  tau = 0;
2600  return;
2601  }
2602 
2603  //
2604  // XNORM = DNRM2( N-1, X, INCX )
2605  //
2606  alpha = x(1);
2607  mx = 0;
2608  for(j=2; j<=n; j++)
2609  {
2610  mx = amp::maximum<Precision>(amp::abs<Precision>(x(j)), mx);
2611  }
2612  xnorm = 0;
2613  if( mx!=0 )
2614  {
2615  for(j=2; j<=n; j++)
2616  {
2617  xnorm = xnorm+amp::sqr<Precision>(x(j)/mx);
2618  }
2619  xnorm = amp::sqrt<Precision>(xnorm)*mx;
2620  }
2621  if( xnorm==0 )
2622  {
2623 
2624  //
2625  // H = I
2626  //
2627  tau = 0;
2628  return;
2629  }
2630 
2631  //
2632  // general case
2633  //
2634  mx = amp::maximum<Precision>(amp::abs<Precision>(alpha), amp::abs<Precision>(xnorm));
2635  beta = -mx*amp::sqrt<Precision>(amp::sqr<Precision>(alpha/mx)+amp::sqr<Precision>(xnorm/mx));
2636  if( alpha<0 )
2637  {
2638  beta = -beta;
2639  }
2640  tau = (beta-alpha)/beta;
2641  v = 1/(alpha-beta);
2642  ap::vmul(x.getvector(2, n), v);
2643  x(1) = beta;
2644  }
2645 
2646 
2647  /*************************************************************************
2648  Application of an elementary reflection to a rectangular matrix of size MxN
2649 
2650  The algorithm pre-multiplies the matrix by an elementary reflection transformation
2651  which is given by column V and scalar Tau (see the description of the
2652  GenerateReflection procedure). Not the whole matrix but only a part of it
2653  is transformed (rows from M1 to M2, columns from N1 to N2). Only the elements
2654  of this submatrix are changed.
2655 
2656  Input parameters:
2657  C - matrix to be transformed.
2658  Tau - scalar defining the transformation.
2659  V - column defining the transformation.
2660  Array whose index ranges within [1..M2-M1+1].
2661  M1, M2 - range of rows to be transformed.
2662  N1, N2 - range of columns to be transformed.
2663  WORK - working array whose indexes goes from N1 to N2.
2664 
2665  Output parameters:
2666  C - the result of multiplying the input matrix C by the
2667  transformation matrix which is given by Tau and V.
2668  If N1>N2 or M1>M2, C is not modified.
2669 
2670  -- LAPACK auxiliary routine (version 3.0) --
2671  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
2672  Courant Institute, Argonne National Lab, and Rice University
2673  September 30, 1994
2674  *************************************************************************/
2675  template<unsigned int Precision>
2679  int m1,
2680  int m2,
2681  int n1,
2682  int n2,
2684  {
2686  int i;
2687 
2688  if( tau==0 || n1>n2 || m1>m2 )
2689  {
2690  return;
2691  }
2692 
2693  //
2694  // w := C' * v
2695  //
2696  for(i=n1; i<=n2; i++)
2697  {
2698  work(i) = 0;
2699  }
2700  for(i=m1; i<=m2; i++)
2701  {
2702  t = v(i+1-m1);
2703  ap::vadd(work.getvector(n1, n2), c.getrow(i, n1, n2), t);
2704  }
2705 
2706  //
2707  // C := C - tau * v * w'
2708  //
2709  for(i=m1; i<=m2; i++)
2710  {
2711  t = v(i-m1+1)*tau;
2712  ap::vsub(c.getrow(i, n1, n2), work.getvector(n1, n2), t);
2713  }
2714  }
2715 
2716 
2717  /*************************************************************************
2718  Application of an elementary reflection to a rectangular matrix of size MxN
2719 
2720  The algorithm post-multiplies the matrix by an elementary reflection transformation
2721  which is given by column V and scalar Tau (see the description of the
2722  GenerateReflection procedure). Not the whole matrix but only a part of it
2723  is transformed (rows from M1 to M2, columns from N1 to N2). Only the
2724  elements of this submatrix are changed.
2725 
2726  Input parameters:
2727  C - matrix to be transformed.
2728  Tau - scalar defining the transformation.
2729  V - column defining the transformation.
2730  Array whose index ranges within [1..N2-N1+1].
2731  M1, M2 - range of rows to be transformed.
2732  N1, N2 - range of columns to be transformed.
2733  WORK - working array whose indexes goes from M1 to M2.
2734 
2735  Output parameters:
2736  C - the result of multiplying the input matrix C by the
2737  transformation matrix which is given by Tau and V.
2738  If N1>N2 or M1>M2, C is not modified.
2739 
2740  -- LAPACK auxiliary routine (version 3.0) --
2741  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
2742  Courant Institute, Argonne National Lab, and Rice University
2743  September 30, 1994
2744  *************************************************************************/
2745  template<unsigned int Precision>
2749  int m1,
2750  int m2,
2751  int n1,
2752  int n2,
2754  {
2756  int i;
2757  int vm;
2758 
2759 
2760  if( tau==0 || n1>n2 || m1>m2 )
2761  {
2762  return;
2763  }
2764 
2765  //
2766  // w := C * v
2767  //
2768  vm = n2-n1+1;
2769  for(i=m1; i<=m2; i++)
2770  {
2771  t = ap::vdotproduct(c.getrow(i, n1, n2), v.getvector(1, vm));
2772  work(i) = t;
2773  }
2774 
2775  //
2776  // C := C - w * v'
2777  //
2778  for(i=m1; i<=m2; i++)
2779  {
2780  t = work(i)*tau;
2781  ap::vsub(c.getrow(i, n1, n2), v.getvector(1, vm), t);
2782  }
2783  }
2784 } // namespace
2785 
2786 /* stuff included from ./bidiagonal.h */
2787 
2788 /*************************************************************************
2789 Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
2790 
2791 Contributors:
2792  * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
2793  pseudocode.
2794 
2795 See subroutines comments for additional copyrights.
2796 
2797 Redistribution and use in source and binary forms, with or without
2798 modification, are permitted provided that the following conditions are
2799 met:
2800 
2801 - Redistributions of source code must retain the above copyright
2802  notice, this list of conditions and the following disclaimer.
2803 
2804 - Redistributions in binary form must reproduce the above copyright
2805  notice, this list of conditions and the following disclaimer listed
2806  in this license in the documentation and/or other materials
2807  provided with the distribution.
2808 
2809 - Neither the name of the copyright holders nor the names of its
2810  contributors may be used to endorse or promote products derived from
2811  this software without specific prior written permission.
2812 
2813 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2814 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2815 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2816 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2817 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2818 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2819 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2820 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2821 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2822 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2823 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2824 *************************************************************************/
2825 
2826 namespace bidiagonal
2827 {
2828  template<unsigned int Precision>
2830  int m,
2831  int n,
2834  template<unsigned int Precision>
2836  int m,
2837  int n,
2839  int qcolumns,
2841  template<unsigned int Precision>
2843  int m,
2844  int n,
2847  int zrows,
2848  int zcolumns,
2849  bool fromtheright,
2850  bool dotranspose);
2851  template<unsigned int Precision>
2853  int m,
2854  int n,
2856  int ptrows,
2858  template<unsigned int Precision>
2860  int m,
2861  int n,
2864  int zrows,
2865  int zcolumns,
2866  bool fromtheright,
2867  bool dotranspose);
2868  template<unsigned int Precision>
2870  int m,
2871  int n,
2872  bool& isupper,
2875  template<unsigned int Precision>
2877  int m,
2878  int n,
2881  template<unsigned int Precision>
2883  int m,
2884  int n,
2886  int qcolumns,
2888  template<unsigned int Precision>
2890  int m,
2891  int n,
2894  int zrows,
2895  int zcolumns,
2896  bool fromtheright,
2897  bool dotranspose);
2898  template<unsigned int Precision>
2900  int m,
2901  int n,
2903  int ptrows,
2905  template<unsigned int Precision>
2907  int m,
2908  int n,
2911  int zrows,
2912  int zcolumns,
2913  bool fromtheright,
2914  bool dotranspose);
2915  template<unsigned int Precision>
2917  int m,
2918  int n,
2919  bool& isupper,
2922 
2923 
2924  /*************************************************************************
2925  Reduction of a rectangular matrix to bidiagonal form
2926 
2927  The algorithm reduces the rectangular matrix A to bidiagonal form by
2928  orthogonal transformations P and Q: A = Q*B*P.
2929 
2930  Input parameters:
2931  A - source matrix. array[0..M-1, 0..N-1]
2932  M - number of rows in matrix A.
2933  N - number of columns in matrix A.
2934 
2935  Output parameters:
2936  A - matrices Q, B, P in compact form (see below).
2937  TauQ - scalar factors which are used to form matrix Q.
2938  TauP - scalar factors which are used to form matrix P.
2939 
2940  The main diagonal and one of the secondary diagonals of matrix A are
2941  replaced with bidiagonal matrix B. Other elements contain elementary
2942  reflections which form MxM matrix Q and NxN matrix P, respectively.
2943 
2944  If M>=N, B is the upper bidiagonal MxN matrix and is stored in the
2945  corresponding elements of matrix A. Matrix Q is represented as a
2946  product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where
2947  H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and
2948  vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is
2949  stored in elements A(i+1:m-1,i). Matrix P is as follows: P =
2950  G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i],
2951  u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1).
2952 
2953  If M<N, B is the lower bidiagonal MxN matrix and is stored in the
2954  corresponding elements of matrix A. Q = H(0)*H(1)*...*H(m-2), where
2955  H(i) = 1 - tau*v*v', tau is stored in TauQ, v(0:i)=0, v(i+1)=1, v(i+2:m-1)
2956  is stored in elements A(i+2:m-1,i). P = G(0)*G(1)*...*G(m-1),
2957  G(i) = 1-tau*u*u', tau is stored in TauP, u(0:i-1)=0, u(i)=1, u(i+1:n-1)
2958  is stored in A(i,i+1:n-1).
2959 
2960  EXAMPLE:
2961 
2962  m=6, n=5 (m > n): m=5, n=6 (m < n):
2963 
2964  ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 )
2965  ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 )
2966  ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 )
2967  ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 )
2968  ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 )
2969  ( v1 v2 v3 v4 v5 )
2970 
2971  Here vi and ui are vectors which form H(i) and G(i), and d and e -
2972  are the diagonal and off-diagonal elements of matrix B.
2973  *************************************************************************/
2974  template<unsigned int Precision>
2976  int m,
2977  int n,
2980  {
2983  int minmn;
2984  int maxmn;
2985  int i;
2986  int j;
2987  amp::ampf<Precision> ltau;
2988 
2989 
2990 
2991  //
2992  // Prepare
2993  //
2994  if( n<=0 || m<=0 )
2995  {
2996  return;
2997  }
2998  minmn = ap::minint(m, n);
2999  maxmn = ap::maxint(m, n);
3000  work.setbounds(0, maxmn);
3001  t.setbounds(0, maxmn);
3002  if( m>=n )
3003  {
3004  tauq.setbounds(0, n-1);
3005  taup.setbounds(0, n-1);
3006  }
3007  else
3008  {
3009  tauq.setbounds(0, m-1);
3010  taup.setbounds(0, m-1);
3011  }
3012  if( m>=n )
3013  {
3014 
3015  //
3016  // Reduce to upper bidiagonal form
3017  //
3018  for(i=0; i<=n-1; i++)
3019  {
3020 
3021  //
3022  // Generate elementary reflector H(i) to annihilate A(i+1:m-1,i)
3023  //
3024  ap::vmove(t.getvector(1, m-i), a.getcolumn(i, i, m-1));
3025  reflections::generatereflection<Precision>(t, m-i, ltau);
3026  tauq(i) = ltau;
3027  ap::vmove(a.getcolumn(i, i, m-1), t.getvector(1, m-i));
3028  t(1) = 1;
3029 
3030  //
3031  // Apply H(i) to A(i:m-1,i+1:n-1) from the left
3032  //
3033  reflections::applyreflectionfromtheleft<Precision>(a, ltau, t, i, m-1, i+1, n-1, work);
3034  if( i<n-1 )
3035  {
3036 
3037  //
3038  // Generate elementary reflector G(i) to annihilate
3039  // A(i,i+2:n-1)
3040  //
3041  ap::vmove(t.getvector(1, n-i-1), a.getrow(i, i+1, n-1));
3042  reflections::generatereflection<Precision>(t, n-1-i, ltau);
3043  taup(i) = ltau;
3044  ap::vmove(a.getrow(i, i+1, n-1), t.getvector(1, n-1-i));
3045  t(1) = 1;
3046 
3047  //
3048  // Apply G(i) to A(i+1:m-1,i+1:n-1) from the right
3049  //
3050  reflections::applyreflectionfromtheright<Precision>(a, ltau, t, i+1, m-1, i+1, n-1, work);
3051  }
3052  else
3053  {
3054  taup(i) = 0;
3055  }
3056  }
3057  }
3058  else
3059  {
3060 
3061  //
3062  // Reduce to lower bidiagonal form
3063  //
3064  for(i=0; i<=m-1; i++)
3065  {
3066 
3067  //
3068  // Generate elementary reflector G(i) to annihilate A(i,i+1:n-1)
3069  //
3070  ap::vmove(t.getvector(1, n-i), a.getrow(i, i, n-1));
3071  reflections::generatereflection<Precision>(t, n-i, ltau);
3072  taup(i) = ltau;
3073  ap::vmove(a.getrow(i, i, n-1), t.getvector(1, n-i));
3074  t(1) = 1;
3075 
3076  //
3077  // Apply G(i) to A(i+1:m-1,i:n-1) from the right
3078  //
3079  reflections::applyreflectionfromtheright<Precision>(a, ltau, t, i+1, m-1, i, n-1, work);
3080  if( i<m-1 )
3081  {
3082 
3083  //
3084  // Generate elementary reflector H(i) to annihilate
3085  // A(i+2:m-1,i)
3086  //
3087  ap::vmove(t.getvector(1, m-1-i), a.getcolumn(i, i+1, m-1));
3088  reflections::generatereflection<Precision>(t, m-1-i, ltau);
3089  tauq(i) = ltau;
3090  ap::vmove(a.getcolumn(i, i+1, m-1), t.getvector(1, m-1-i));
3091  t(1) = 1;
3092 
3093  //
3094  // Apply H(i) to A(i+1:m-1,i+1:n-1) from the left
3095  //
3096  reflections::applyreflectionfromtheleft<Precision>(a, ltau, t, i+1, m-1, i+1, n-1, work);
3097  }
3098  else
3099  {
3100  tauq(i) = 0;
3101  }
3102  }
3103  }
3104  }
3105 
3106 
3107  /*************************************************************************
3108  Unpacking matrix Q which reduces a matrix to bidiagonal form.
3109 
3110  Input parameters:
3111  QP - matrices Q and P in compact form.
3112  Output of ToBidiagonal subroutine.
3113  M - number of rows in matrix A.
3114  N - number of columns in matrix A.
3115  TAUQ - scalar factors which are used to form Q.
3116  Output of ToBidiagonal subroutine.
3117  QColumns - required number of columns in matrix Q.
3118  M>=QColumns>=0.
3119 
3120  Output parameters:
3121  Q - first QColumns columns of matrix Q.
3122  Array[0..M-1, 0..QColumns-1]
3123  If QColumns=0, the array is not modified.
3124 
3125  -- ALGLIB --
3126  Copyright 2005 by Bochkanov Sergey
3127  *************************************************************************/
3128  template<unsigned int Precision>
3130  int m,
3131  int n,
3133  int qcolumns,
3135  {
3136  int i;
3137  int j;
3138 
3139 
3140  ap::ap_error::make_assertion(qcolumns<=m);
3141  ap::ap_error::make_assertion(qcolumns>=0);
3142  if( m==0 || n==0 || qcolumns==0 )
3143  {
3144  return;
3145  }
3146 
3147  //
3148  // prepare Q
3149  //
3150  q.setbounds(0, m-1, 0, qcolumns-1);
3151  for(i=0; i<=m-1; i++)
3152  {
3153  for(j=0; j<=qcolumns-1; j++)
3154  {
3155  if( i==j )
3156  {
3157  q(i,j) = 1;
3158  }
3159  else
3160  {
3161  q(i,j) = 0;
3162  }
3163  }
3164  }
3165 
3166  //
3167  // Calculate
3168  //
3169  rmatrixbdmultiplybyq<Precision>(qp, m, n, tauq, q, m, qcolumns, false, false);
3170  }
3171 
3172 
3173  /*************************************************************************
3174  Multiplication by matrix Q which reduces matrix A to bidiagonal form.
3175 
3176  The algorithm allows pre- or post-multiply by Q or Q'.
3177 
3178  Input parameters:
3179  QP - matrices Q and P in compact form.
3180  Output of ToBidiagonal subroutine.
3181  M - number of rows in matrix A.
3182  N - number of columns in matrix A.
3183  TAUQ - scalar factors which are used to form Q.
3184  Output of ToBidiagonal subroutine.
3185  Z - multiplied matrix.
3186  array[0..ZRows-1,0..ZColumns-1]
3187  ZRows - number of rows in matrix Z. If FromTheRight=False,
3188  ZRows=M, otherwise ZRows can be arbitrary.
3189  ZColumns - number of columns in matrix Z. If FromTheRight=True,
3190  ZColumns=M, otherwise ZColumns can be arbitrary.
3191  FromTheRight - pre- or post-multiply.
3192  DoTranspose - multiply by Q or Q'.
3193 
3194  Output parameters:
3195  Z - product of Z and Q.
3196  Array[0..ZRows-1,0..ZColumns-1]
3197  If ZRows=0 or ZColumns=0, the array is not modified.
3198 
3199  -- ALGLIB --
3200  Copyright 2005 by Bochkanov Sergey
3201  *************************************************************************/
3202  template<unsigned int Precision>
3204  int m,
3205  int n,
3208  int zrows,
3209  int zcolumns,
3210  bool fromtheright,
3211  bool dotranspose)
3212  {
3213  int i;
3214  int i1;
3215  int i2;
3216  int istep;
3219  int mx;
3220 
3221 
3222  if( m<=0 || n<=0 || zrows<=0 || zcolumns<=0 )
3223  {
3224  return;
3225  }
3226  ap::ap_error::make_assertion(fromtheright && zcolumns==m || !fromtheright && zrows==m);
3227 
3228  //
3229  // init
3230  //
3231  mx = ap::maxint(m, n);
3232  mx = ap::maxint(mx, zrows);
3233  mx = ap::maxint(mx, zcolumns);
3234  v.setbounds(0, mx);
3235  work.setbounds(0, mx);
3236  if( m>=n )
3237  {
3238 
3239  //
3240  // setup
3241  //
3242  if( fromtheright )
3243  {
3244  i1 = 0;
3245  i2 = n-1;
3246  istep = +1;
3247  }
3248  else
3249  {
3250  i1 = n-1;
3251  i2 = 0;
3252  istep = -1;
3253  }
3254  if( dotranspose )
3255  {
3256  i = i1;
3257  i1 = i2;
3258  i2 = i;
3259  istep = -istep;
3260  }
3261 
3262  //
3263  // Process
3264  //
3265  i = i1;
3266  do
3267  {
3268  ap::vmove(v.getvector(1, m-i), qp.getcolumn(i, i, m-1));
3269  v(1) = 1;
3270  if( fromtheright )
3271  {
3272  reflections::applyreflectionfromtheright<Precision>(z, tauq(i), v, 0, zrows-1, i, m-1, work);
3273  }
3274  else
3275  {
3276  reflections::applyreflectionfromtheleft<Precision>(z, tauq(i), v, i, m-1, 0, zcolumns-1, work);
3277  }
3278  i = i+istep;
3279  }
3280  while( i!=i2+istep );
3281  }
3282  else
3283  {
3284 
3285  //
3286  // setup
3287  //
3288  if( fromtheright )
3289  {
3290  i1 = 0;
3291  i2 = m-2;
3292  istep = +1;
3293  }
3294  else
3295  {
3296  i1 = m-2;
3297  i2 = 0;
3298  istep = -1;
3299  }
3300  if( dotranspose )
3301  {
3302  i = i1;
3303  i1 = i2;
3304  i2 = i;
3305  istep = -istep;
3306  }
3307 
3308  //
3309  // Process
3310  //
3311  if( m-1>0 )
3312  {
3313  i = i1;
3314  do
3315  {
3316  ap::vmove(v.getvector(1, m-i-1), qp.getcolumn(i, i+1, m-1));
3317  v(1) = 1;
3318  if( fromtheright )
3319  {
3320  reflections::applyreflectionfromtheright<Precision>(z, tauq(i), v, 0, zrows-1, i+1, m-1, work);
3321  }
3322  else
3323  {
3324  reflections::applyreflectionfromtheleft<Precision>(z, tauq(i), v, i+1, m-1, 0, zcolumns-1, work);
3325  }
3326  i = i+istep;
3327  }
3328  while( i!=i2+istep );
3329  }
3330  }
3331  }
3332 
3333 
3334  /*************************************************************************
3335  Unpacking matrix P which reduces matrix A to bidiagonal form.
3336  The subroutine returns transposed matrix P.
3337 
3338  Input parameters:
3339  QP - matrices Q and P in compact form.
3340  Output of ToBidiagonal subroutine.
3341  M - number of rows in matrix A.
3342  N - number of columns in matrix A.
3343  TAUP - scalar factors which are used to form P.
3344  Output of ToBidiagonal subroutine.
3345  PTRows - required number of rows of matrix P^T. N >= PTRows >= 0.
3346 
3347  Output parameters:
3348  PT - first PTRows columns of matrix P^T
3349  Array[0..PTRows-1, 0..N-1]
3350  If PTRows=0, the array is not modified.
3351 
3352  -- ALGLIB --
3353  Copyright 2005-2007 by Bochkanov Sergey
3354  *************************************************************************/
3355  template<unsigned int Precision>
3357  int m,
3358  int n,
3360  int ptrows,
3362  {
3363  int i;
3364  int j;
3365 
3366 
3367  ap::ap_error::make_assertion(ptrows<=n);
3368  ap::ap_error::make_assertion(ptrows>=0);
3369  if( m==0 || n==0 || ptrows==0 )
3370  {
3371  return;
3372  }
3373 
3374  //
3375  // prepare PT
3376  //
3377  pt.setbounds(0, ptrows-1, 0, n-1);
3378  for(i=0; i<=ptrows-1; i++)
3379  {
3380  for(j=0; j<=n-1; j++)
3381  {
3382  if( i==j )
3383  {
3384  pt(i,j) = 1;
3385  }
3386  else
3387  {
3388  pt(i,j) = 0;
3389  }
3390  }
3391  }
3392 
3393  //
3394  // Calculate
3395  //
3396  rmatrixbdmultiplybyp<Precision>(qp, m, n, taup, pt, ptrows, n, true, true);
3397  }
3398 
3399 
3400  /*************************************************************************
3401  Multiplication by matrix P which reduces matrix A to bidiagonal form.
3402 
3403  The algorithm allows pre- or post-multiply by P or P'.
3404 
3405  Input parameters:
3406  QP - matrices Q and P in compact form.
3407  Output of RMatrixBD subroutine.
3408  M - number of rows in matrix A.
3409  N - number of columns in matrix A.
3410  TAUP - scalar factors which are used to form P.
3411  Output of RMatrixBD subroutine.
3412  Z - multiplied matrix.
3413  Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
3414  ZRows - number of rows in matrix Z. If FromTheRight=False,
3415  ZRows=N, otherwise ZRows can be arbitrary.
3416  ZColumns - number of columns in matrix Z. If FromTheRight=True,
3417  ZColumns=N, otherwise ZColumns can be arbitrary.
3418  FromTheRight - pre- or post-multiply.
3419  DoTranspose - multiply by P or P'.
3420 
3421  Output parameters:
3422  Z - product of Z and P.
3423  Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
3424  If ZRows=0 or ZColumns=0, the array is not modified.
3425 
3426  -- ALGLIB --
3427  Copyright 2005-2007 by Bochkanov Sergey
3428  *************************************************************************/
3429  template<unsigned int Precision>
3431  int m,
3432  int n,
3435  int zrows,
3436  int zcolumns,
3437  bool fromtheright,
3438  bool dotranspose)
3439  {
3440  int i;
3443  int mx;
3444  int i1;
3445  int i2;
3446  int istep;
3447 
3448 
3449  if( m<=0 || n<=0 || zrows<=0 || zcolumns<=0 )
3450  {
3451  return;
3452  }
3453  ap::ap_error::make_assertion(fromtheright && zcolumns==n || !fromtheright && zrows==n);
3454 
3455  //
3456  // init
3457  //
3458  mx = ap::maxint(m, n);
3459  mx = ap::maxint(mx, zrows);
3460  mx = ap::maxint(mx, zcolumns);
3461  v.setbounds(0, mx);
3462  work.setbounds(0, mx);
3463  v.setbounds(0, mx);
3464  work.setbounds(0, mx);
3465  if( m>=n )
3466  {
3467 
3468  //
3469  // setup
3470  //
3471  if( fromtheright )
3472  {
3473  i1 = n-2;
3474  i2 = 0;
3475  istep = -1;
3476  }
3477  else
3478  {
3479  i1 = 0;
3480  i2 = n-2;
3481  istep = +1;
3482  }
3483  if( !dotranspose )
3484  {
3485  i = i1;
3486  i1 = i2;
3487  i2 = i;
3488  istep = -istep;
3489  }
3490 
3491  //
3492  // Process
3493  //
3494  if( n-1>0 )
3495  {
3496  i = i1;
3497  do
3498  {
3499  ap::vmove(v.getvector(1, n-1-i), qp.getrow(i, i+1, n-1));
3500  v(1) = 1;
3501  if( fromtheright )
3502  {
3503  reflections::applyreflectionfromtheright<Precision>(z, taup(i), v, 0, zrows-1, i+1, n-1, work);
3504  }
3505  else
3506  {
3507  reflections::applyreflectionfromtheleft<Precision>(z, taup(i), v, i+1, n-1, 0, zcolumns-1, work);
3508  }
3509  i = i+istep;
3510  }
3511  while( i!=i2+istep );
3512  }
3513  }
3514  else
3515  {
3516 
3517  //
3518  // setup
3519  //
3520  if( fromtheright )
3521  {
3522  i1 = m-1;
3523  i2 = 0;
3524  istep = -1;
3525  }
3526  else
3527  {
3528  i1 = 0;
3529  i2 = m-1;
3530  istep = +1;
3531  }
3532  if( !dotranspose )
3533  {
3534  i = i1;
3535  i1 = i2;
3536  i2 = i;
3537  istep = -istep;
3538  }
3539 
3540  //
3541  // Process
3542  //
3543  i = i1;
3544  do
3545  {
3546  ap::vmove(v.getvector(1, n-i), qp.getrow(i, i, n-1));
3547  v(1) = 1;
3548  if( fromtheright )
3549  {
3550  reflections::applyreflectionfromtheright<Precision>(z, taup(i), v, 0, zrows-1, i, n-1, work);
3551  }
3552  else
3553  {
3554  reflections::applyreflectionfromtheleft<Precision>(z, taup(i), v, i, n-1, 0, zcolumns-1, work);
3555  }
3556  i = i+istep;
3557  }
3558  while( i!=i2+istep );
3559  }
3560  }
3561 
3562 
3563  /*************************************************************************
3564  Unpacking of the main and secondary diagonals of bidiagonal decomposition
3565  of matrix A.
3566 
3567  Input parameters:
3568  B - output of RMatrixBD subroutine.
3569  M - number of rows in matrix B.
3570  N - number of columns in matrix B.
3571 
3572  Output parameters:
3573  IsUpper - True, if the matrix is upper bidiagonal.
3574  otherwise IsUpper is False.
3575  D - the main diagonal.
3576  Array whose index ranges within [0..Min(M,N)-1].
3577  E - the secondary diagonal (upper or lower, depending on
3578  the value of IsUpper).
3579  Array index ranges within [0..Min(M,N)-1], the last
3580  element is not used.
3581 
3582  -- ALGLIB --
3583  Copyright 2005-2007 by Bochkanov Sergey
3584  *************************************************************************/
3585  template<unsigned int Precision>
3587  int m,
3588  int n,
3589  bool& isupper,
3592  {
3593  int i;
3594 
3595 
3596  isupper = m>=n;
3597  if( m<=0 || n<=0 )
3598  {
3599  return;
3600  }
3601  if( isupper )
3602  {
3603  d.setbounds(0, n-1);
3604  e.setbounds(0, n-1);
3605  for(i=0; i<=n-2; i++)
3606  {
3607  d(i) = b(i,i);
3608  e(i) = b(i,i+1);
3609  }
3610  d(n-1) = b(n-1,n-1);
3611  }
3612  else
3613  {
3614  d.setbounds(0, m-1);
3615  e.setbounds(0, m-1);
3616  for(i=0; i<=m-2; i++)
3617  {
3618  d(i) = b(i,i);
3619  e(i) = b(i+1,i);
3620  }
3621  d(m-1) = b(m-1,m-1);
3622  }
3623  }
3624 
3625 
3626  /*************************************************************************
3627  Obsolete 1-based subroutine.
3628  See RMatrixBD for 0-based replacement.
3629  *************************************************************************/
3630  template<unsigned int Precision>
3632  int m,
3633  int n,
3636  {
3639  int minmn;
3640  int maxmn;
3641  int i;
3642  amp::ampf<Precision> ltau;
3643  int mmip1;
3644  int nmi;
3645  int ip1;
3646  int nmip1;
3647  int mmi;
3648 
3649 
3650  minmn = ap::minint(m, n);
3651  maxmn = ap::maxint(m, n);
3652  work.setbounds(1, maxmn);
3653  t.setbounds(1, maxmn);
3654  taup.setbounds(1, minmn);
3655  tauq.setbounds(1, minmn);
3656  if( m>=n )
3657  {
3658 
3659  //
3660  // Reduce to upper bidiagonal form
3661  //
3662  for(i=1; i<=n; i++)
3663  {
3664 
3665  //
3666  // Generate elementary reflector H(i) to annihilate A(i+1:m,i)
3667  //
3668  mmip1 = m-i+1;
3669  ap::vmove(t.getvector(1, mmip1), a.getcolumn(i, i, m));
3670  reflections::generatereflection<Precision>(t, mmip1, ltau);
3671  tauq(i) = ltau;
3672  ap::vmove(a.getcolumn(i, i, m), t.getvector(1, mmip1));
3673  t(1) = 1;
3674 
3675  //
3676  // Apply H(i) to A(i:m,i+1:n) from the left
3677  //
3678  reflections::applyreflectionfromtheleft<Precision>(a, ltau, t, i, m, i+1, n, work);
3679  if( i<n )
3680  {
3681 
3682  //
3683  // Generate elementary reflector G(i) to annihilate
3684  // A(i,i+2:n)
3685  //
3686  nmi = n-i;
3687  ip1 = i+1;
3688  ap::vmove(t.getvector(1, nmi), a.getrow(i, ip1, n));
3689  reflections::generatereflection<Precision>(t, nmi, ltau);
3690  taup(i) = ltau;
3691  ap::vmove(a.getrow(i, ip1, n), t.getvector(1, nmi));
3692  t(1) = 1;
3693 
3694  //
3695  // Apply G(i) to A(i+1:m,i+1:n) from the right
3696  //
3697  reflections::applyreflectionfromtheright<Precision>(a, ltau, t, i+1, m, i+1, n, work);
3698  }
3699  else
3700  {
3701  taup(i) = 0;
3702  }
3703  }
3704  }
3705  else
3706  {
3707 
3708  //
3709  // Reduce to lower bidiagonal form
3710  //
3711  for(i=1; i<=m; i++)
3712  {
3713 
3714  //
3715  // Generate elementary reflector G(i) to annihilate A(i,i+1:n)
3716  //
3717  nmip1 = n-i+1;
3718  ap::vmove(t.getvector(1, nmip1), a.getrow(i, i, n));
3719  reflections::generatereflection<Precision>(t, nmip1, ltau);
3720  taup(i) = ltau;
3721  ap::vmove(a.getrow(i, i, n), t.getvector(1, nmip1));
3722  t(1) = 1;
3723 
3724  //
3725  // Apply G(i) to A(i+1:m,i:n) from the right
3726  //
3727  reflections::applyreflectionfromtheright<Precision>(a, ltau, t, i+1, m, i, n, work);
3728  if( i<m )
3729  {
3730 
3731  //
3732  // Generate elementary reflector H(i) to annihilate
3733  // A(i+2:m,i)
3734  //
3735  mmi = m-i;
3736  ip1 = i+1;
3737  ap::vmove(t.getvector(1, mmi), a.getcolumn(i, ip1, m));
3738  reflections::generatereflection<Precision>(t, mmi, ltau);
3739  tauq(i) = ltau;
3740  ap::vmove(a.getcolumn(i, ip1, m), t.getvector(1, mmi));
3741  t(1) = 1;
3742 
3743  //
3744  // Apply H(i) to A(i+1:m,i+1:n) from the left
3745  //
3746  reflections::applyreflectionfromtheleft<Precision>(a, ltau, t, i+1, m, i+1, n, work);
3747  }
3748  else
3749  {
3750  tauq(i) = 0;
3751  }
3752  }
3753  }
3754  }
3755 
3756 
3757  /*************************************************************************
3758  Obsolete 1-based subroutine.
3759  See RMatrixBDUnpackQ for 0-based replacement.
3760  *************************************************************************/
3761  template<unsigned int Precision>
3763  int m,
3764  int n,
3766  int qcolumns,
3768  {
3769  int i;
3770  int j;
3771  int ip1;
3774  int vm;
3775 
3776 
3777  ap::ap_error::make_assertion(qcolumns<=m);
3778  if( m==0 || n==0 || qcolumns==0 )
3779  {
3780  return;
3781  }
3782 
3783  //
3784  // init
3785  //
3786  q.setbounds(1, m, 1, qcolumns);
3787  v.setbounds(1, m);
3788  work.setbounds(1, qcolumns);
3789 
3790  //
3791  // prepare Q
3792  //
3793  for(i=1; i<=m; i++)
3794  {
3795  for(j=1; j<=qcolumns; j++)
3796  {
3797  if( i==j )
3798  {
3799  q(i,j) = 1;
3800  }
3801  else
3802  {
3803  q(i,j) = 0;
3804  }
3805  }
3806  }
3807  if( m>=n )
3808  {
3809  for(i=ap::minint(n, qcolumns); i>=1; i--)
3810  {
3811  vm = m-i+1;
3812  ap::vmove(v.getvector(1, vm), qp.getcolumn(i, i, m));
3813  v(1) = 1;
3814  reflections::applyreflectionfromtheleft<Precision>(q, tauq(i), v, i, m, 1, qcolumns, work);
3815  }
3816  }
3817  else
3818  {
3819  for(i=ap::minint(m-1, qcolumns-1); i>=1; i--)
3820  {
3821  vm = m-i;
3822  ip1 = i+1;
3823  ap::vmove(v.getvector(1, vm), qp.getcolumn(i, ip1, m));
3824  v(1) = 1;
3825  reflections::applyreflectionfromtheleft<Precision>(q, tauq(i), v, i+1, m, 1, qcolumns, work);
3826  }
3827  }
3828  }
3829 
3830 
3831  /*************************************************************************
3832  Obsolete 1-based subroutine.
3833  See RMatrixBDMultiplyByQ for 0-based replacement.
3834  *************************************************************************/
3835  template<unsigned int Precision>
3837  int m,
3838  int n,
3841  int zrows,
3842  int zcolumns,
3843  bool fromtheright,
3844  bool dotranspose)
3845  {
3846  int i;
3847  int ip1;
3848  int i1;
3849  int i2;
3850  int istep;
3853  int vm;
3854  int mx;
3855 
3856 
3857  if( m<=0 || n<=0 || zrows<=0 || zcolumns<=0 )
3858  {
3859  return;
3860  }
3861  ap::ap_error::make_assertion(fromtheright && zcolumns==m || !fromtheright && zrows==m);
3862 
3863  //
3864  // init
3865  //
3866  mx = ap::maxint(m, n);
3867  mx = ap::maxint(mx, zrows);
3868  mx = ap::maxint(mx, zcolumns);
3869  v.setbounds(1, mx);
3870  work.setbounds(1, mx);
3871  if( m>=n )
3872  {
3873 
3874  //
3875  // setup
3876  //
3877  if( fromtheright )
3878  {
3879  i1 = 1;
3880  i2 = n;
3881  istep = +1;
3882  }
3883  else
3884  {
3885  i1 = n;
3886  i2 = 1;
3887  istep = -1;
3888  }
3889  if( dotranspose )
3890  {
3891  i = i1;
3892  i1 = i2;
3893  i2 = i;
3894  istep = -istep;
3895  }
3896 
3897  //
3898  // Process
3899  //
3900  i = i1;
3901  do
3902  {
3903  vm = m-i+1;
3904  ap::vmove(v.getvector(1, vm), qp.getcolumn(i, i, m));
3905  v(1) = 1;
3906  if( fromtheright )
3907  {
3908  reflections::applyreflectionfromtheright<Precision>(z, tauq(i), v, 1, zrows, i, m, work);
3909  }
3910  else
3911  {
3912  reflections::applyreflectionfromtheleft<Precision>(z, tauq(i), v, i, m, 1, zcolumns, work);
3913  }
3914  i = i+istep;
3915  }
3916  while( i!=i2+istep );
3917  }
3918  else
3919  {
3920 
3921  //
3922  // setup
3923  //
3924  if( fromtheright )
3925  {
3926  i1 = 1;
3927  i2 = m-1;
3928  istep = +1;
3929  }
3930  else
3931  {
3932  i1 = m-1;
3933  i2 = 1;
3934  istep = -1;
3935  }
3936  if( dotranspose )
3937  {
3938  i = i1;
3939  i1 = i2;
3940  i2 = i;
3941  istep = -istep;
3942  }
3943 
3944  //
3945  // Process
3946  //
3947  if( m-1>0 )
3948  {
3949  i = i1;
3950  do
3951  {
3952  vm = m-i;
3953  ip1 = i+1;
3954  ap::vmove(v.getvector(1, vm), qp.getcolumn(i, ip1, m));
3955  v(1) = 1;
3956  if( fromtheright )
3957  {
3958  reflections::applyreflectionfromtheright<Precision>(z, tauq(i), v, 1, zrows, i+1, m, work);
3959  }
3960  else
3961  {
3962  reflections::applyreflectionfromtheleft<Precision>(z, tauq(i), v, i+1, m, 1, zcolumns, work);
3963  }
3964  i = i+istep;
3965  }
3966  while( i!=i2+istep );
3967  }
3968  }
3969  }
3970 
3971 
3972  /*************************************************************************
3973  Obsolete 1-based subroutine.
3974  See RMatrixBDUnpackPT for 0-based replacement.
3975  *************************************************************************/
3976  template<unsigned int Precision>
3978  int m,
3979  int n,
3981  int ptrows,
3983  {
3984  int i;
3985  int j;
3986  int ip1;
3989  int vm;
3990 
3991 
3992  ap::ap_error::make_assertion(ptrows<=n);
3993  if( m==0 || n==0 || ptrows==0 )
3994  {
3995  return;
3996  }
3997 
3998  //
3999  // init
4000  //
4001  pt.setbounds(1, ptrows, 1, n);
4002  v.setbounds(1, n);
4003  work.setbounds(1, ptrows);
4004 
4005  //
4006  // prepare PT
4007  //
4008  for(i=1; i<=ptrows; i++)
4009  {
4010  for(j=1; j<=n; j++)
4011  {
4012  if( i==j )
4013  {
4014  pt(i,j) = 1;
4015  }
4016  else
4017  {
4018  pt(i,j) = 0;
4019  }
4020  }
4021  }
4022  if( m>=n )
4023  {
4024  for(i=ap::minint(n-1, ptrows-1); i>=1; i--)
4025  {
4026  vm = n-i;
4027  ip1 = i+1;
4028  ap::vmove(v.getvector(1, vm), qp.getrow(i, ip1, n));
4029  v(1) = 1;
4030  reflections::applyreflectionfromtheright<Precision>(pt, taup(i), v, 1, ptrows, i+1, n, work);
4031  }
4032  }
4033  else
4034  {
4035  for(i=ap::minint(m, ptrows); i>=1; i--)
4036  {
4037  vm = n-i+1;
4038  ap::vmove(v.getvector(1, vm), qp.getrow(i, i, n));
4039  v(1) = 1;
4040  reflections::applyreflectionfromtheright<Precision>(pt, taup(i), v, 1, ptrows, i, n, work);
4041  }
4042  }
4043  }
4044 
4045 
4046  /*************************************************************************
4047  Obsolete 1-based subroutine.
4048  See RMatrixBDMultiplyByP for 0-based replacement.
4049  *************************************************************************/
4050  template<unsigned int Precision>
4052  int m,
4053  int n,
4056  int zrows,
4057  int zcolumns,
4058  bool fromtheright,
4059  bool dotranspose)
4060  {
4061  int i;
4062  int ip1;
4065  int vm;
4066  int mx;
4067  int i1;
4068  int i2;
4069  int istep;
4070 
4071 
4072  if( m<=0 || n<=0 || zrows<=0 || zcolumns<=0 )
4073  {
4074  return;
4075  }
4076  ap::ap_error::make_assertion(fromtheright && zcolumns==n || !fromtheright && zrows==n);
4077 
4078  //
4079  // init
4080  //
4081  mx = ap::maxint(m, n);
4082  mx = ap::maxint(mx, zrows);
4083  mx = ap::maxint(mx, zcolumns);
4084  v.setbounds(1, mx);
4085  work.setbounds(1, mx);
4086  v.setbounds(1, mx);
4087  work.setbounds(1, mx);
4088  if( m>=n )
4089  {
4090 
4091  //
4092  // setup
4093  //
4094  if( fromtheright )
4095  {
4096  i1 = n-1;
4097  i2 = 1;
4098  istep = -1;
4099  }
4100  else
4101  {
4102  i1 = 1;
4103  i2 = n-1;
4104  istep = +1;
4105  }
4106  if( !dotranspose )
4107  {
4108  i = i1;
4109  i1 = i2;
4110  i2 = i;
4111  istep = -istep;
4112  }
4113 
4114  //
4115  // Process
4116  //
4117  if( n-1>0 )
4118  {
4119  i = i1;
4120  do
4121  {
4122  vm = n-i;
4123  ip1 = i+1;
4124  ap::vmove(v.getvector(1, vm), qp.getrow(i, ip1, n));
4125  v(1) = 1;
4126  if( fromtheright )
4127  {
4128  reflections::applyreflectionfromtheright<Precision>(z, taup(i), v, 1, zrows, i+1, n, work);
4129  }
4130  else
4131  {
4132  reflections::applyreflectionfromtheleft<Precision>(z, taup(i), v, i+1, n, 1, zcolumns, work);
4133  }
4134  i = i+istep;
4135  }
4136  while( i!=i2+istep );
4137  }
4138  }
4139  else
4140  {
4141 
4142  //
4143  // setup
4144  //
4145  if( fromtheright )
4146  {
4147  i1 = m;
4148  i2 = 1;
4149  istep = -1;
4150  }
4151  else
4152  {
4153  i1 = 1;
4154  i2 = m;
4155  istep = +1;
4156  }
4157  if( !dotranspose )
4158  {
4159  i = i1;
4160  i1 = i2;
4161  i2 = i;
4162  istep = -istep;
4163  }
4164 
4165  //
4166  // Process
4167  //
4168  i = i1;
4169  do
4170  {
4171  vm = n-i+1;
4172  ap::vmove(v.getvector(1, vm), qp.getrow(i, i, n));
4173  v(1) = 1;
4174  if( fromtheright )
4175  {
4176  reflections::applyreflectionfromtheright<Precision>(z, taup(i), v, 1, zrows, i, n, work);
4177  }
4178  else
4179  {
4180  reflections::applyreflectionfromtheleft<Precision>(z, taup(i), v, i, n, 1, zcolumns, work);
4181  }
4182  i = i+istep;
4183  }
4184  while( i!=i2+istep );
4185  }
4186  }
4187 
4188 
4189  /*************************************************************************
4190  Obsolete 1-based subroutine.
4191  See RMatrixBDUnpackDiagonals for 0-based replacement.
4192  *************************************************************************/
4193  template<unsigned int Precision>
4195  int m,
4196  int n,
4197  bool& isupper,
4200  {
4201  int i;
4202 
4203 
4204  isupper = m>=n;
4205  if( m==0 || n==0 )
4206  {
4207  return;
4208  }
4209  if( isupper )
4210  {
4211  d.setbounds(1, n);
4212  e.setbounds(1, n);
4213  for(i=1; i<=n-1; i++)
4214  {
4215  d(i) = b(i,i);
4216  e(i) = b(i,i+1);
4217  }
4218  d(n) = b(n,n);
4219  }
4220  else
4221  {
4222  d.setbounds(1, m);
4223  e.setbounds(1, m);
4224  for(i=1; i<=m-1; i++)
4225  {
4226  d(i) = b(i,i);
4227  e(i) = b(i+1,i);
4228  }
4229  d(m) = b(m,m);
4230  }
4231  }
4232 } // namespace
4233 
4234 /* stuff included from ./qr.h */
4235 
4236 /*************************************************************************
4237 Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
4238 
4239 Contributors:
4240  * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
4241  pseudocode.
4242 
4243 See subroutines comments for additional copyrights.
4244 
4245 Redistribution and use in source and binary forms, with or without
4246 modification, are permitted provided that the following conditions are
4247 met:
4248 
4249 - Redistributions of source code must retain the above copyright
4250  notice, this list of conditions and the following disclaimer.
4251 
4252 - Redistributions in binary form must reproduce the above copyright
4253  notice, this list of conditions and the following disclaimer listed
4254  in this license in the documentation and/or other materials
4255  provided with the distribution.
4256 
4257 - Neither the name of the copyright holders nor the names of its
4258  contributors may be used to endorse or promote products derived from
4259  this software without specific prior written permission.
4260 
4261 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4262 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4263 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4264 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4265 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4266 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4267 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4268 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4269 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4270 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4271 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4272 *************************************************************************/
4273 
4274 namespace qr
4275 {
4276  template<unsigned int Precision>
4278  int m,
4279  int n,
4281  template<unsigned int Precision>
4283  int m,
4284  int n,
4286  int qcolumns,
4288  template<unsigned int Precision>
4290  int m,
4291  int n,
4293  template<unsigned int Precision>
4295  int m,
4296  int n,
4298  template<unsigned int Precision>
4300  int m,
4301  int n,
4303  int qcolumns,
4305  template<unsigned int Precision>
4307  int m,
4308  int n,
4311 
4312 
4313  /*************************************************************************
4314  QR decomposition of a rectangular matrix of size MxN
4315 
4316  Input parameters:
4317  A - matrix A whose indexes range within [0..M-1, 0..N-1].
4318  M - number of rows in matrix A.
4319  N - number of columns in matrix A.
4320 
4321  Output parameters:
4322  A - matrices Q and R in compact form (see below).
4323  Tau - array of scalar factors which are used to form
4324  matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)].
4325 
4326  Matrix A is represented as A = QR, where Q is an orthogonal matrix of size
4327  MxM, R - upper triangular (or upper trapezoid) matrix of size M x N.
4328 
4329  The elements of matrix R are located on and above the main diagonal of
4330  matrix A. The elements which are located in Tau array and below the main
4331  diagonal of matrix A are used to form matrix Q as follows:
4332 
4333  Matrix Q is represented as a product of elementary reflections
4334 
4335  Q = H(0)*H(2)*...*H(k-1),
4336 
4337  where k = min(m,n), and each H(i) is in the form
4338 
4339  H(i) = 1 - tau * v * (v^T)
4340 
4341  where tau is a scalar stored in Tau[I]; v - real vector,
4342  so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i).
4343 
4344  -- LAPACK routine (version 3.0) --
4345  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
4346  Courant Institute, Argonne National Lab, and Rice University
4347  February 29, 1992.
4348  Translation from FORTRAN to pseudocode (AlgoPascal)
4349  by Sergey Bochkanov, ALGLIB project, 2005-2007.
4350  *************************************************************************/
4351  template<unsigned int Precision>
4353  int m,
4354  int n,
4356  {
4359  int i;
4360  int k;
4361  int minmn;
4363 
4364 
4365  if( m<=0 || n<=0 )
4366  {
4367  return;
4368  }
4369  minmn = ap::minint(m, n);
4370  work.setbounds(0, n-1);
4371  t.setbounds(1, m);
4372  tau.setbounds(0, minmn-1);
4373 
4374  //
4375  // Test the input arguments
4376  //
4377  k = minmn;
4378  for(i=0; i<=k-1; i++)
4379  {
4380 
4381  //
4382  // Generate elementary reflector H(i) to annihilate A(i+1:m,i)
4383  //
4384  ap::vmove(t.getvector(1, m-i), a.getcolumn(i, i, m-1));
4385  reflections::generatereflection<Precision>(t, m-i, tmp);
4386  tau(i) = tmp;
4387  ap::vmove(a.getcolumn(i, i, m-1), t.getvector(1, m-i));
4388  t(1) = 1;
4389  if( i<n )
4390  {
4391 
4392  //
4393  // Apply H(i) to A(i:m-1,i+1:n-1) from the left
4394  //
4395  reflections::applyreflectionfromtheleft<Precision>(a, tau(i), t, i, m-1, i+1, n-1, work);
4396  }
4397  }
4398  }
4399 
4400 
4401  /*************************************************************************
4402  Partial unpacking of matrix Q from the QR decomposition of a matrix A
4403 
4404  Input parameters:
4405  A - matrices Q and R in compact form.
4406  Output of RMatrixQR subroutine.
4407  M - number of rows in given matrix A. M>=0.
4408  N - number of columns in given matrix A. N>=0.
4409  Tau - scalar factors which are used to form Q.
4410  Output of the RMatrixQR subroutine.
4411  QColumns - required number of columns of matrix Q. M>=QColumns>=0.
4412 
4413  Output parameters:
4414  Q - first QColumns columns of matrix Q.
4415  Array whose indexes range within [0..M-1, 0..QColumns-1].
4416  If QColumns=0, the array remains unchanged.
4417 
4418  -- ALGLIB --
4419  Copyright 2005 by Bochkanov Sergey
4420  *************************************************************************/
4421  template<unsigned int Precision>
4423  int m,
4424  int n,
4426  int qcolumns,
4428  {
4429  int i;
4430  int j;
4431  int k;
4432  int minmn;
4435 
4436 
4437  ap::ap_error::make_assertion(qcolumns<=m);
4438  if( m<=0 || n<=0 || qcolumns<=0 )
4439  {
4440  return;
4441  }
4442 
4443  //
4444  // init
4445  //
4446  minmn = ap::minint(m, n);
4447  k = ap::minint(minmn, qcolumns);
4448  q.setbounds(0, m-1, 0, qcolumns-1);
4449  v.setbounds(1, m);
4450  work.setbounds(0, qcolumns-1);
4451  for(i=0; i<=m-1; i++)
4452  {
4453  for(j=0; j<=qcolumns-1; j++)
4454  {
4455  if( i==j )
4456  {
4457  q(i,j) = 1;
4458  }
4459  else
4460  {
4461  q(i,j) = 0;
4462  }
4463  }
4464  }
4465 
4466  //
4467  // unpack Q
4468  //
4469  for(i=k-1; i>=0; i--)
4470  {
4471 
4472  //
4473  // Apply H(i)
4474  //
4475  ap::vmove(v.getvector(1, m-i), a.getcolumn(i, i, m-1));
4476  v(1) = 1;
4477  reflections::applyreflectionfromtheleft<Precision>(q, tau(i), v, i, m-1, 0, qcolumns-1, work);
4478  }
4479  }
4480 
4481 
4482  /*************************************************************************
4483  Unpacking of matrix R from the QR decomposition of a matrix A
4484 
4485  Input parameters:
4486  A - matrices Q and R in compact form.
4487  Output of RMatrixQR subroutine.
4488  M - number of rows in given matrix A. M>=0.
4489  N - number of columns in given matrix A. N>=0.
4490 
4491  Output parameters:
4492  R - matrix R, array[0..M-1, 0..N-1].
4493 
4494  -- ALGLIB --
4495  Copyright 2005 by Bochkanov Sergey
4496  *************************************************************************/
4497  template<unsigned int Precision>
4499  int m,
4500  int n,
4502  {
4503  int i;
4504  int k;
4505 
4506 
4507  if( m<=0 || n<=0 )
4508  {
4509  return;
4510  }
4511  k = ap::minint(m, n);
4512  r.setbounds(0, m-1, 0, n-1);
4513  for(i=0; i<=n-1; i++)
4514  {
4515  r(0,i) = 0;
4516  }
4517  for(i=1; i<=m-1; i++)
4518  {
4519  ap::vmove(r.getrow(i, 0, n-1), r.getrow(0, 0, n-1));
4520  }
4521  for(i=0; i<=k-1; i++)
4522  {
4523  ap::vmove(r.getrow(i, i, n-1), a.getrow(i, i, n-1));
4524  }
4525  }
4526 
4527 
4528  /*************************************************************************
4529  Obsolete 1-based subroutine. See RMatrixQR for 0-based replacement.
4530  *************************************************************************/
4531  template<unsigned int Precision>
4533  int m,
4534  int n,
4536  {
4539  int i;
4540  int k;
4541  int mmip1;
4542  int minmn;
4544 
4545 
4546  minmn = ap::minint(m, n);
4547  work.setbounds(1, n);
4548  t.setbounds(1, m);
4549  tau.setbounds(1, minmn);
4550 
4551  //
4552  // Test the input arguments
4553  //
4554  k = ap::minint(m, n);
4555  for(i=1; i<=k; i++)
4556  {
4557 
4558  //
4559  // Generate elementary reflector H(i) to annihilate A(i+1:m,i)
4560  //
4561  mmip1 = m-i+1;
4562  ap::vmove(t.getvector(1, mmip1), a.getcolumn(i, i, m));
4563  reflections::generatereflection<Precision>(t, mmip1, tmp);
4564  tau(i) = tmp;
4565  ap::vmove(a.getcolumn(i, i, m), t.getvector(1, mmip1));
4566  t(1) = 1;
4567  if( i<n )
4568  {
4569 
4570  //
4571  // Apply H(i) to A(i:m,i+1:n) from the left
4572  //
4573  reflections::applyreflectionfromtheleft<Precision>(a, tau(i), t, i, m, i+1, n, work);
4574  }
4575  }
4576  }
4577 
4578 
4579  /*************************************************************************
4580  Obsolete 1-based subroutine. See RMatrixQRUnpackQ for 0-based replacement.
4581  *************************************************************************/
4582  template<unsigned int Precision>
4584  int m,
4585  int n,
4587  int qcolumns,
4589  {
4590  int i;
4591  int j;
4592  int k;
4593  int minmn;
4596  int vm;
4597 
4598 
4599  ap::ap_error::make_assertion(qcolumns<=m);
4600  if( m==0 || n==0 || qcolumns==0 )
4601  {
4602  return;
4603  }
4604 
4605  //
4606  // init
4607  //
4608  minmn = ap::minint(m, n);
4609  k = ap::minint(minmn, qcolumns);
4610  q.setbounds(1, m, 1, qcolumns);
4611  v.setbounds(1, m);
4612  work.setbounds(1, qcolumns);
4613  for(i=1; i<=m; i++)
4614  {
4615  for(j=1; j<=qcolumns; j++)
4616  {
4617  if( i==j )
4618  {
4619  q(i,j) = 1;
4620  }
4621  else
4622  {
4623  q(i,j) = 0;
4624  }
4625  }
4626  }
4627 
4628  //
4629  // unpack Q
4630  //
4631  for(i=k; i>=1; i--)
4632  {
4633 
4634  //
4635  // Apply H(i)
4636  //
4637  vm = m-i+1;
4638  ap::vmove(v.getvector(1, vm), a.getcolumn(i, i, m));
4639  v(1) = 1;
4640  reflections::applyreflectionfromtheleft<Precision>(q, tau(i), v, i, m, 1, qcolumns, work);
4641  }
4642  }
4643 
4644 
4645  /*************************************************************************
4646  Obsolete 1-based subroutine. See RMatrixQR for 0-based replacement.
4647  *************************************************************************/
4648  template<unsigned int Precision>
4650  int m,
4651  int n,
4654  {
4655  int i;
4656  int k;
4660 
4661 
4662  k = ap::minint(m, n);
4663  if( n<=0 )
4664  {
4665  return;
4666  }
4667  work.setbounds(1, m);
4668  v.setbounds(1, m);
4669  q.setbounds(1, m, 1, m);
4670  r.setbounds(1, m, 1, n);
4671 
4672  //
4673  // QRDecomposition
4674  //
4675  qrdecomposition<Precision>(a, m, n, tau);
4676 
4677  //
4678  // R
4679  //
4680  for(i=1; i<=n; i++)
4681  {
4682  r(1,i) = 0;
4683  }
4684  for(i=2; i<=m; i++)
4685  {
4686  ap::vmove(r.getrow(i, 1, n), r.getrow(1, 1, n));
4687  }
4688  for(i=1; i<=k; i++)
4689  {
4690  ap::vmove(r.getrow(i, i, n), a.getrow(i, i, n));
4691  }
4692 
4693  //
4694  // Q
4695  //
4696  unpackqfromqr<Precision>(a, m, n, tau, m, q);
4697  }
4698 } // namespace
4699 
4700 /* stuff included from ./lq.h */
4701 
4702 /*************************************************************************
4703 Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
4704 
4705 Redistribution and use in source and binary forms, with or without
4706 modification, are permitted provided that the following conditions are
4707 met:
4708 
4709 - Redistributions of source code must retain the above copyright
4710  notice, this list of conditions and the following disclaimer.
4711 
4712 - Redistributions in binary form must reproduce the above copyright
4713  notice, this list of conditions and the following disclaimer listed
4714  in this license in the documentation and/or other materials
4715  provided with the distribution.
4716 
4717 - Neither the name of the copyright holders nor the names of its
4718  contributors may be used to endorse or promote products derived from
4719  this software without specific prior written permission.
4720 
4721 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4722 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4723 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4724 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4725 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4726 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4727 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4728 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4729 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4730 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4731 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4732 *************************************************************************/
4733 
4734 namespace lq
4735 {
4736  template<unsigned int Precision>
4738  int m,
4739  int n,
4741  template<unsigned int Precision>
4743  int m,
4744  int n,
4746  int qrows,
4748  template<unsigned int Precision>
4750  int m,
4751  int n,
4753  template<unsigned int Precision>
4755  int m,
4756  int n,
4758  template<unsigned int Precision>
4760  int m,
4761  int n,
4763  int qrows,
4765  template<unsigned int Precision>
4767  int m,
4768  int n,
4771 
4772 
4773  /*************************************************************************
4774  LQ decomposition of a rectangular matrix of size MxN
4775 
4776  Input parameters:
4777  A - matrix A whose indexes range within [0..M-1, 0..N-1].
4778  M - number of rows in matrix A.
4779  N - number of columns in matrix A.
4780 
4781  Output parameters:
4782  A - matrices L and Q in compact form (see below)
4783  Tau - array of scalar factors which are used to form
4784  matrix Q. Array whose index ranges within [0..Min(M,N)-1].
4785 
4786  Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
4787  MxM, L - lower triangular (or lower trapezoid) matrix of size M x N.
4788 
4789  The elements of matrix L are located on and below the main diagonal of
4790  matrix A. The elements which are located in Tau array and above the main
4791  diagonal of matrix A are used to form matrix Q as follows:
4792 
4793  Matrix Q is represented as a product of elementary reflections
4794 
4795  Q = H(k-1)*H(k-2)*...*H(1)*H(0),
4796 
4797  where k = min(m,n), and each H(i) is of the form
4798 
4799  H(i) = 1 - tau * v * (v^T)
4800 
4801  where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0,
4802  v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1).
4803 
4804  -- ALGLIB --
4805  Copyright 2005-2007 by Bochkanov Sergey
4806  *************************************************************************/
4807  template<unsigned int Precision>
4809  int m,
4810  int n,
4812  {
4815  int i;
4816  int k;
4817  int minmn;
4818  int maxmn;
4820 
4821 
4822  minmn = ap::minint(m, n);
4823  maxmn = ap::maxint(m, n);
4824  work.setbounds(0, m);
4825  t.setbounds(0, n);
4826  tau.setbounds(0, minmn-1);
4827  k = ap::minint(m, n);
4828  for(i=0; i<=k-1; i++)
4829  {
4830 
4831  //
4832  // Generate elementary reflector H(i) to annihilate A(i,i+1:n-1)
4833  //
4834  ap::vmove(t.getvector(1, n-i), a.getrow(i, i, n-1));
4835  reflections::generatereflection<Precision>(t, n-i, tmp);
4836  tau(i) = tmp;
4837  ap::vmove(a.getrow(i, i, n-1), t.getvector(1, n-i));
4838  t(1) = 1;
4839  if( i<n )
4840  {
4841 
4842  //
4843  // Apply H(i) to A(i+1:m,i:n) from the right
4844  //
4845  reflections::applyreflectionfromtheright<Precision>(a, tau(i), t, i+1, m-1, i, n-1, work);
4846  }
4847  }
4848  }
4849 
4850 
4851  /*************************************************************************
4852  Partial unpacking of matrix Q from the LQ decomposition of a matrix A
4853 
4854  Input parameters:
4855  A - matrices L and Q in compact form.
4856  Output of RMatrixLQ subroutine.
4857  M - number of rows in given matrix A. M>=0.
4858  N - number of columns in given matrix A. N>=0.
4859  Tau - scalar factors which are used to form Q.
4860  Output of the RMatrixLQ subroutine.
4861  QRows - required number of rows in matrix Q. N>=QRows>=0.
4862 
4863  Output parameters:
4864  Q - first QRows rows of matrix Q. Array whose indexes range
4865  within [0..QRows-1, 0..N-1]. If QRows=0, the array remains
4866  unchanged.
4867 
4868  -- ALGLIB --
4869  Copyright 2005 by Bochkanov Sergey
4870  *************************************************************************/
4871  template<unsigned int Precision>
4873  int m,
4874  int n,
4876  int qrows,
4878  {
4879  int i;
4880  int j;
4881  int k;
4882  int minmn;
4885 
4886 
4887  ap::ap_error::make_assertion(qrows<=n);
4888  if( m<=0 || n<=0 || qrows<=0 )
4889  {
4890  return;
4891  }
4892 
4893  //
4894  // init
4895  //
4896  minmn = ap::minint(m, n);
4897  k = ap::minint(minmn, qrows);
4898  q.setbounds(0, qrows-1, 0, n-1);
4899  v.setbounds(0, n);
4900  work.setbounds(0, qrows);
4901  for(i=0; i<=qrows-1; i++)
4902  {
4903  for(j=0; j<=n-1; j++)
4904  {
4905  if( i==j )
4906  {
4907  q(i,j) = 1;
4908  }
4909  else
4910  {
4911  q(i,j) = 0;
4912  }
4913  }
4914  }
4915 
4916  //
4917  // unpack Q
4918  //
4919  for(i=k-1; i>=0; i--)
4920  {
4921 
4922  //
4923  // Apply H(i)
4924  //
4925  ap::vmove(v.getvector(1, n-i), a.getrow(i, i, n-1));
4926  v(1) = 1;
4927  reflections::applyreflectionfromtheright<Precision>(q, tau(i), v, 0, qrows-1, i, n-1, work);
4928  }
4929  }
4930 
4931 
4932  /*************************************************************************
4933  Unpacking of matrix L from the LQ decomposition of a matrix A
4934 
4935  Input parameters:
4936  A - matrices Q and L in compact form.
4937  Output of RMatrixLQ subroutine.
4938  M - number of rows in given matrix A. M>=0.
4939  N - number of columns in given matrix A. N>=0.
4940 
4941  Output parameters:
4942  L - matrix L, array[0..M-1, 0..N-1].
4943 
4944  -- ALGLIB --
4945  Copyright 2005 by Bochkanov Sergey
4946  *************************************************************************/
4947  template<unsigned int Precision>
4949  int m,
4950  int n,
4952  {
4953  int i;
4954  int k;
4955 
4956 
4957  if( m<=0 || n<=0 )
4958  {
4959  return;
4960  }
4961  l.setbounds(0, m-1, 0, n-1);
4962  for(i=0; i<=n-1; i++)
4963  {
4964  l(0,i) = 0;
4965  }
4966  for(i=1; i<=m-1; i++)
4967  {
4968  ap::vmove(l.getrow(i, 0, n-1), l.getrow(0, 0, n-1));
4969  }
4970  for(i=0; i<=m-1; i++)
4971  {
4972  k = ap::minint(i, n-1);
4973  ap::vmove(l.getrow(i, 0, k), a.getrow(i, 0, k));
4974  }
4975  }
4976 
4977 
4978  /*************************************************************************
4979  Obsolete 1-based subroutine
4980  See RMatrixLQ for 0-based replacement.
4981  *************************************************************************/
4982  template<unsigned int Precision>
4984  int m,
4985  int n,
4987  {
4990  int i;
4991  int k;
4992  int nmip1;
4993  int minmn;
4994  int maxmn;
4996 
4997 
4998  minmn = ap::minint(m, n);
4999  maxmn = ap::maxint(m, n);
5000  work.setbounds(1, m);
5001  t.setbounds(1, n);
5002  tau.setbounds(1, minmn);
5003 
5004  //
5005  // Test the input arguments
5006  //
5007  k = ap::minint(m, n);
5008  for(i=1; i<=k; i++)
5009  {
5010 
5011  //
5012  // Generate elementary reflector H(i) to annihilate A(i,i+1:n)
5013  //
5014  nmip1 = n-i+1;
5015  ap::vmove(t.getvector(1, nmip1), a.getrow(i, i, n));
5016  reflections::generatereflection<Precision>(t, nmip1, tmp);
5017  tau(i) = tmp;
5018  ap::vmove(a.getrow(i, i, n), t.getvector(1, nmip1));
5019  t(1) = 1;
5020  if( i<n )
5021  {
5022 
5023  //
5024  // Apply H(i) to A(i+1:m,i:n) from the right
5025  //
5026  reflections::applyreflectionfromtheright<Precision>(a, tau(i), t, i+1, m, i, n, work);
5027  }
5028  }
5029  }
5030 
5031 
5032  /*************************************************************************
5033  Obsolete 1-based subroutine
5034  See RMatrixLQUnpackQ for 0-based replacement.
5035  *************************************************************************/
5036  template<unsigned int Precision>
5038  int m,
5039  int n,
5041  int qrows,
5043  {
5044  int i;
5045  int j;
5046  int k;
5047  int minmn;
5050  int vm;
5051 
5052 
5053  ap::ap_error::make_assertion(qrows<=n);
5054  if( m==0 || n==0 || qrows==0 )
5055  {
5056  return;
5057  }
5058 
5059  //
5060  // init
5061  //
5062  minmn = ap::minint(m, n);
5063  k = ap::minint(minmn, qrows);
5064  q.setbounds(1, qrows, 1, n);
5065  v.setbounds(1, n);
5066  work.setbounds(1, qrows);
5067  for(i=1; i<=qrows; i++)
5068  {
5069  for(j=1; j<=n; j++)
5070  {
5071  if( i==j )
5072  {
5073  q(i,j) = 1;
5074  }
5075  else
5076  {
5077  q(i,j) = 0;
5078  }
5079  }
5080  }
5081 
5082  //
5083  // unpack Q
5084  //
5085  for(i=k; i>=1; i--)
5086  {
5087 
5088  //
5089  // Apply H(i)
5090  //
5091  vm = n-i+1;
5092  ap::vmove(v.getvector(1, vm), a.getrow(i, i, n));
5093  v(1) = 1;
5094  reflections::applyreflectionfromtheright<Precision>(q, tau(i), v, 1, qrows, i, n, work);
5095  }
5096  }
5097 
5098 
5099  /*************************************************************************
5100  Obsolete 1-based subroutine
5101  *************************************************************************/
5102  template<unsigned int Precision>
5104  int m,
5105  int n,
5108  {
5109  int i;
5110  int j;
5112 
5113 
5114  if( n<=0 )
5115  {
5116  return;
5117  }
5118  q.setbounds(1, n, 1, n);
5119  l.setbounds(1, m, 1, n);
5120 
5121  //
5122  // LQDecomposition
5123  //
5124  lqdecomposition<Precision>(a, m, n, tau);
5125 
5126  //
5127  // L
5128  //
5129  for(i=1; i<=m; i++)
5130  {
5131  for(j=1; j<=n; j++)
5132  {
5133  if( j>i )
5134  {
5135  l(i,j) = 0;
5136  }
5137  else
5138  {
5139  l(i,j) = a(i,j);
5140  }
5141  }
5142  }
5143 
5144  //
5145  // Q
5146  //
5147  unpackqfromlq<Precision>(a, m, n, tau, n, q);
5148  }
5149 } // namespace
5150 
5151 /* stuff included from ./blas.h */
5152 
5153 /*************************************************************************
5154 Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
5155 
5156 Redistribution and use in source and binary forms, with or without
5157 modification, are permitted provided that the following conditions are
5158 met:
5159 
5160 - Redistributions of source code must retain the above copyright
5161  notice, this list of conditions and the following disclaimer.
5162 
5163 - Redistributions in binary form must reproduce the above copyright
5164  notice, this list of conditions and the following disclaimer listed
5165  in this license in the documentation and/or other materials
5166  provided with the distribution.
5167 
5168 - Neither the name of the copyright holders nor the names of its
5169  contributors may be used to endorse or promote products derived from
5170  this software without specific prior written permission.
5171 
5172 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5173 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5174 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5175 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5176 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5177 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5178 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5179 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5180 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5181 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5182 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5183 *************************************************************************/
5184 
5185 namespace blas
5186 {
5187  template<unsigned int Precision>
5189  int i1,
5190  int i2);
5191  template<unsigned int Precision>
5193  int i1,
5194  int i2);
5195  template<unsigned int Precision>
5197  int i1,
5198  int i2,
5199  int j);
5200  template<unsigned int Precision>
5202  int j1,
5203  int j2,
5204  int i);
5205  template<unsigned int Precision>
5207  int i1,
5208  int i2,
5209  int j1,
5210  int j2,
5212  template<unsigned int Precision>
5214  int is1,
5215  int is2,
5216  int js1,
5217  int js2,
5219  int id1,
5220  int id2,
5221  int jd1,
5222  int jd2);
5223  template<unsigned int Precision>
5225  int i1,
5226  int i2,
5227  int j1,
5228  int j2,
5230  template<unsigned int Precision>
5232  int is1,
5233  int is2,
5234  int js1,
5235  int js2,
5237  int id1,
5238  int id2,
5239  int jd1,
5240  int jd2);
5241  template<unsigned int Precision>
5243  int i1,
5244  int i2,
5245  int j1,
5246  int j2,
5247  bool trans,
5249  int ix1,
5250  int ix2,
5253  int iy1,
5254  int iy2,
5256  template<unsigned int Precision>
5259  template<unsigned int Precision>
5261  int ai1,
5262  int ai2,
5263  int aj1,
5264  int aj2,
5265  bool transa,
5267  int bi1,
5268  int bi2,
5269  int bj1,
5270  int bj2,
5271  bool transb,
5272  amp::ampf<Precision> alpha,
5274  int ci1,
5275  int ci2,
5276  int cj1,
5277  int cj2,
5278  amp::ampf<Precision> beta,
5280 
5281 
5282  template<unsigned int Precision>
5284  int i1,
5285  int i2)
5286  {
5288  int n;
5289  int ix;
5290  amp::ampf<Precision> absxi;
5293 
5294 
5295  n = i2-i1+1;
5296  if( n<1 )
5297  {
5298  result = 0;
5299  return result;
5300  }
5301  if( n==1 )
5302  {
5303  result = amp::abs<Precision>(x(i1));
5304  return result;
5305  }
5306  scl = 0;
5307  ssq = 1;
5308  for(ix=i1; ix<=i2; ix++)
5309  {
5310  if( x(ix)!=0 )
5311  {
5312  absxi = amp::abs<Precision>(x(ix));
5313  if( scl<absxi )
5314  {
5315  ssq = 1+ssq*amp::sqr<Precision>(scl/absxi);
5316  scl = absxi;
5317  }
5318  else
5319  {
5320  ssq = ssq+amp::sqr<Precision>(absxi/scl);
5321  }
5322  }
5323  }
5324  result = scl*amp::sqrt<Precision>(ssq);
5325  return result;
5326  }
5327 
5328 
5329  template<unsigned int Precision>
5331  int i1,
5332  int i2)
5333  {
5334  int result;
5335  int i;
5337 
5338 
5339  result = i1;
5340  a = amp::abs<Precision>(x(result));
5341  for(i=i1+1; i<=i2; i++)
5342  {
5343  if( amp::abs<Precision>(x(i))>amp::abs<Precision>(x(result)) )
5344  {
5345  result = i;
5346  }
5347  }
5348  return result;
5349  }
5350 
5351 
5352  template<unsigned int Precision>
5354  int i1,
5355  int i2,
5356  int j)
5357  {
5358  int result;
5359  int i;
5361 
5362 
5363  result = i1;
5364  a = amp::abs<Precision>(x(result,j));
5365  for(i=i1+1; i<=i2; i++)
5366  {
5367  if( amp::abs<Precision>(x(i,j))>amp::abs<Precision>(x(result,j)) )
5368  {
5369  result = i;
5370  }
5371  }
5372  return result;
5373  }
5374 
5375 
5376  template<unsigned int Precision>
5378  int j1,
5379  int j2,
5380  int i)
5381  {
5382  int result;
5383  int j;
5385 
5386 
5387  result = j1;
5388  a = amp::abs<Precision>(x(i,result));
5389  for(j=j1+1; j<=j2; j++)
5390  {
5391  if( amp::abs<Precision>(x(i,j))>amp::abs<Precision>(x(i,result)) )
5392  {
5393  result = j;
5394  }
5395  }
5396  return result;
5397  }
5398 
5399 
5400  template<unsigned int Precision>
5402  int i1,
5403  int i2,
5404  int j1,
5405  int j2,
5407  {
5409  int i;
5410  int j;
5411 
5412 
5413  ap::ap_error::make_assertion(i2-i1==j2-j1);
5414  for(j=j1; j<=j2; j++)
5415  {
5416  work(j) = 0;
5417  }
5418  for(i=i1; i<=i2; i++)
5419  {
5420  for(j=ap::maxint(j1, j1+i-i1-1); j<=j2; j++)
5421  {
5422  work(j) = work(j)+amp::abs<Precision>(a(i,j));
5423  }
5424  }
5425  result = 0;
5426  for(j=j1; j<=j2; j++)
5427  {
5428  result = amp::maximum<Precision>(result, work(j));
5429  }
5430  return result;
5431  }
5432 
5433 
5434  template<unsigned int Precision>
5436  int is1,
5437  int is2,
5438  int js1,
5439  int js2,
5441  int id1,
5442  int id2,
5443  int jd1,
5444  int jd2)
5445  {
5446  int isrc;
5447  int idst;
5448 
5449 
5450  if( is1>is2 || js1>js2 )
5451  {
5452  return;
5453  }
5454  ap::ap_error::make_assertion(is2-is1==id2-id1);
5455  ap::ap_error::make_assertion(js2-js1==jd2-jd1);
5456  for(isrc=is1; isrc<=is2; isrc++)
5457  {
5458  idst = isrc-is1+id1;
5459  ap::vmove(b.getrow(idst, jd1, jd2), a.getrow(isrc, js1, js2));
5460  }
5461  }
5462 
5463 
5464  template<unsigned int Precision>
5466  int i1,
5467  int i2,
5468  int j1,
5469  int j2,
5471  {
5472  int i;
5473  int j;
5474  int ips;
5475  int jps;
5476  int l;
5477 
5478 
5479  if( i1>i2 || j1>j2 )
5480  {
5481  return;
5482  }
5483  ap::ap_error::make_assertion(i1-i2==j1-j2);
5484  for(i=i1; i<=i2-1; i++)
5485  {
5486  j = j1+i-i1;
5487  ips = i+1;
5488  jps = j1+ips-i1;
5489  l = i2-i;
5490  ap::vmove(work.getvector(1, l), a.getcolumn(j, ips, i2));
5491  ap::vmove(a.getcolumn(j, ips, i2), a.getrow(i, jps, j2));
5492  ap::vmove(a.getrow(i, jps, j2), work.getvector(1, l));
5493  }
5494  }
5495 
5496 
5497  template<unsigned int Precision>
5499  int is1,
5500  int is2,
5501  int js1,
5502  int js2,
5504  int id1,
5505  int id2,
5506  int jd1,
5507  int jd2)
5508  {
5509  int isrc;
5510  int jdst;
5511 
5512 
5513  if( is1>is2 || js1>js2 )
5514  {
5515  return;
5516  }
5517  ap::ap_error::make_assertion(is2-is1==jd2-jd1);
5518  ap::ap_error::make_assertion(js2-js1==id2-id1);
5519  for(isrc=is1; isrc<=is2; isrc++)
5520  {
5521  jdst = isrc-is1+jd1;
5522  ap::vmove(b.getcolumn(jdst, id1, id2), a.getrow(isrc, js1, js2));
5523  }
5524  }
5525 
5526 
5527  template<unsigned int Precision>
5529  int i1,
5530  int i2,
5531  int j1,
5532  int j2,
5533  bool trans,
5535  int ix1,
5536  int ix2,
5537  amp::ampf<Precision> alpha,
5539  int iy1,
5540  int iy2,
5541  amp::ampf<Precision> beta)
5542  {
5543  int i;
5545 
5546 
5547  if( !trans )
5548  {
5549 
5550  //
5551  // y := alpha*A*x + beta*y;
5552  //
5553  if( i1>i2 || j1>j2 )
5554  {
5555  return;
5556  }
5557  ap::ap_error::make_assertion(j2-j1==ix2-ix1);
5558  ap::ap_error::make_assertion(i2-i1==iy2-iy1);
5559 
5560  //
5561  // beta*y
5562  //
5563  if( beta==0 )
5564  {
5565  for(i=iy1; i<=iy2; i++)
5566  {
5567  y(i) = 0;
5568  }
5569  }
5570  else
5571  {
5572  ap::vmul(y.getvector(iy1, iy2), beta);
5573  }
5574 
5575  //
5576  // alpha*A*x
5577  //
5578  for(i=i1; i<=i2; i++)
5579  {
5580  v = ap::vdotproduct(a.getrow(i, j1, j2), x.getvector(ix1, ix2));
5581  y(iy1+i-i1) = y(iy1+i-i1)+alpha*v;
5582  }
5583  }
5584  else
5585  {
5586 
5587  //
5588  // y := alpha*A'*x + beta*y;
5589  //
5590  if( i1>i2 || j1>j2 )
5591  {
5592  return;
5593  }
5594  ap::ap_error::make_assertion(i2-i1==ix2-ix1);
5595  ap::ap_error::make_assertion(j2-j1==iy2-iy1);
5596 
5597  //
5598  // beta*y
5599  //
5600  if( beta==0 )
5601  {
5602  for(i=iy1; i<=iy2; i++)
5603  {
5604  y(i) = 0;
5605  }
5606  }
5607  else
5608  {
5609  ap::vmul(y.getvector(iy1, iy2), beta);
5610  }
5611 
5612  //
5613  // alpha*A'*x
5614  //
5615  for(i=i1; i<=i2; i++)
5616  {
5617  v = alpha*x(ix1+i-i1);
5618  ap::vadd(y.getvector(iy1, iy2), a.getrow(i, j1, j2), v);
5619  }
5620  }
5621  }
5622 
5623 
5624  template<unsigned int Precision>
5627  {
5630  amp::ampf<Precision> xabs;
5631  amp::ampf<Precision> yabs;
5633 
5634 
5635  xabs = amp::abs<Precision>(x);
5636  yabs = amp::abs<Precision>(y);
5637  w = amp::maximum<Precision>(xabs, yabs);
5638  z = amp::minimum<Precision>(xabs, yabs);
5639  if( z==0 )
5640  {
5641  result = w;
5642  }
5643  else
5644  {
5645  result = w*amp::sqrt<Precision>(1+amp::sqr<Precision>(z/w));
5646  }
5647  return result;
5648  }
5649 
5650 
5651  template<unsigned int Precision>
5653  int ai1,
5654  int ai2,
5655  int aj1,
5656  int aj2,
5657  bool transa,
5659  int bi1,
5660  int bi2,
5661  int bj1,
5662  int bj2,
5663  bool transb,
5664  amp::ampf<Precision> alpha,
5666  int ci1,
5667  int ci2,
5668  int cj1,
5669  int cj2,
5670  amp::ampf<Precision> beta,
5672  {
5673  int arows;
5674  int acols;
5675  int brows;
5676  int bcols;
5677  int crows;
5678  int ccols;
5679  int i;
5680  int j;
5681  int k;
5682  int l;
5683  int r;
5685 
5686 
5687 
5688  //
5689  // Setup
5690  //
5691  if( !transa )
5692  {
5693  arows = ai2-ai1+1;
5694  acols = aj2-aj1+1;
5695  }
5696  else
5697  {
5698  arows = aj2-aj1+1;
5699  acols = ai2-ai1+1;
5700  }
5701  if( !transb )
5702  {
5703  brows = bi2-bi1+1;
5704  bcols = bj2-bj1+1;
5705  }
5706  else
5707  {
5708  brows = bj2-bj1+1;
5709  bcols = bi2-bi1+1;
5710  }
5711  ap::ap_error::make_assertion(acols==brows);
5712  if( arows<=0 || acols<=0 || brows<=0 || bcols<=0 )
5713  {
5714  return;
5715  }
5716  crows = arows;
5717  ccols = bcols;
5718 
5719  //
5720  // Test WORK
5721  //
5722  i = ap::maxint(arows, acols);
5723  i = ap::maxint(brows, i);
5724  i = ap::maxint(i, bcols);
5725  work(1) = 0;
5726  work(i) = 0;
5727 
5728  //
5729  // Prepare C
5730  //
5731  if( beta==0 )
5732  {
5733  for(i=ci1; i<=ci2; i++)
5734  {
5735  for(j=cj1; j<=cj2; j++)
5736  {
5737  c(i,j) = 0;
5738  }
5739  }
5740  }
5741  else
5742  {
5743  for(i=ci1; i<=ci2; i++)
5744  {
5745  ap::vmul(c.getrow(i, cj1, cj2), beta);
5746  }
5747  }
5748 
5749  //
5750  // A*B
5751  //
5752  if( !transa && !transb )
5753  {
5754  for(l=ai1; l<=ai2; l++)
5755  {
5756  for(r=bi1; r<=bi2; r++)
5757  {
5758  v = alpha*a(l,aj1+r-bi1);
5759  k = ci1+l-ai1;
5760  ap::vadd(c.getrow(k, cj1, cj2), b.getrow(r, bj1, bj2), v);
5761  }
5762  }
5763  return;
5764  }
5765 
5766  //
5767  // A*B'
5768  //
5769  if( !transa && transb )
5770  {
5771  if( arows*acols<brows*bcols )
5772  {
5773  for(r=bi1; r<=bi2; r++)
5774  {
5775  for(l=ai1; l<=ai2; l++)
5776  {
5777  v = ap::vdotproduct(a.getrow(l, aj1, aj2), b.getrow(r, bj1, bj2));
5778  c(ci1+l-ai1,cj1+r-bi1) = c(ci1+l-ai1,cj1+r-bi1)+alpha*v;
5779  }
5780  }
5781  return;
5782  }
5783  else
5784  {
5785  for(l=ai1; l<=ai2; l++)
5786  {
5787  for(r=bi1; r<=bi2; r++)
5788  {
5789  v = ap::vdotproduct(a.getrow(l, aj1, aj2), b.getrow(r, bj1, bj2));
5790  c(ci1+l-ai1,cj1+r-bi1) = c(ci1+l-ai1,cj1+r-bi1)+alpha*v;
5791  }
5792  }
5793  return;
5794  }
5795  }
5796 
5797  //
5798  // A'*B
5799  //
5800  if( transa && !transb )
5801  {
5802  for(l=aj1; l<=aj2; l++)
5803  {
5804  for(r=bi1; r<=bi2; r++)
5805  {
5806  v = alpha*a(ai1+r-bi1,l);
5807  k = ci1+l-aj1;
5808  ap::vadd(c.getrow(k, cj1, cj2), b.getrow(r, bj1, bj2), v);
5809  }
5810  }
5811  return;
5812  }
5813 
5814  //
5815  // A'*B'
5816  //
5817  if( transa && transb )
5818  {
5819  if( arows*acols<brows*bcols )
5820  {
5821  for(r=bi1; r<=bi2; r++)
5822  {
5823  for(i=1; i<=crows; i++)
5824  {
5825  work(i) = amp::ampf<Precision>("0.0");
5826  }
5827  for(l=ai1; l<=ai2; l++)
5828  {
5829  v = alpha*b(r,bj1+l-ai1);
5830  k = cj1+r-bi1;
5831  ap::vadd(work.getvector(1, crows), a.getrow(l, aj1, aj2), v);
5832  }
5833  ap::vadd(c.getcolumn(k, ci1, ci2), work.getvector(1, crows));
5834  }
5835  return;
5836  }
5837  else
5838  {
5839  for(l=aj1; l<=aj2; l++)
5840  {
5841  k = ai2-ai1+1;
5842  ap::vmove(work.getvector(1, k), a.getcolumn(l, ai1, ai2));
5843  for(r=bi1; r<=bi2; r++)
5844  {
5845  v = ap::vdotproduct(work.getvector(1, k), b.getrow(r, bj1, bj2));
5846  c(ci1+l-aj1,cj1+r-bi1) = c(ci1+l-aj1,cj1+r-bi1)+alpha*v;
5847  }
5848  }
5849  return;
5850  }
5851  }
5852  }
5853 } // namespace
5854 
5855 /* stuff included from ./rotations.h */
5856 
5857 /*************************************************************************
5858 Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
5859 
5860 Contributors:
5861  * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
5862  pseudocode.
5863 
5864 See subroutines comments for additional copyrights.
5865 
5866 Redistribution and use in source and binary forms, with or without
5867 modification, are permitted provided that the following conditions are
5868 met:
5869 
5870 - Redistributions of source code must retain the above copyright
5871  notice, this list of conditions and the following disclaimer.
5872 
5873 - Redistributions in binary form must reproduce the above copyright
5874  notice, this list of conditions and the following disclaimer listed
5875  in this license in the documentation and/or other materials
5876  provided with the distribution.
5877 
5878 - Neither the name of the copyright holders nor the names of its
5879  contributors may be used to endorse or promote products derived from
5880  this software without specific prior written permission.
5881 
5882 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5883 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5884 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5885 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5886 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5887 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5888 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5889 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5890 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5891 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5892 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5893 *************************************************************************/
5894 
5895 namespace rotations
5896 {
5897  template<unsigned int Precision>
5898  void applyrotationsfromtheleft(bool isforward,
5899  int m1,
5900  int m2,
5901  int n1,
5902  int n2,
5907  template<unsigned int Precision>
5908  void applyrotationsfromtheright(bool isforward,
5909  int m1,
5910  int m2,
5911  int n1,
5912  int n2,
5917  template<unsigned int Precision>
5923 
5924 
5925  /*************************************************************************
5926  Application of a sequence of elementary rotations to a matrix
5927 
5928  The algorithm pre-multiplies the matrix by a sequence of rotation
5929  transformations which is given by arrays C and S. Depending on the value
5930  of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
5931  rows are rotated, or the rows N and N-1, N-2 and N-3 and so on, are rotated.
5932 
5933  Not the whole matrix but only a part of it is transformed (rows from M1 to
5934  M2, columns from N1 to N2). Only the elements of this submatrix are changed.
5935 
5936  Input parameters:
5937  IsForward - the sequence of the rotation application.
5938  M1,M2 - the range of rows to be transformed.
5939  N1, N2 - the range of columns to be transformed.
5940  C,S - transformation coefficients.
5941  Array whose index ranges within [1..M2-M1].
5942  A - processed matrix.
5943  WORK - working array whose index ranges within [N1..N2].
5944 
5945  Output parameters:
5946  A - transformed matrix.
5947 
5948  Utility subroutine.
5949  *************************************************************************/
5950  template<unsigned int Precision>
5951  void applyrotationsfromtheleft(bool isforward,
5952  int m1,
5953  int m2,
5954  int n1,
5955  int n2,
5960  {
5961  int j;
5962  int jp1;
5963  amp::ampf<Precision> ctemp;
5964  amp::ampf<Precision> stemp;
5965  amp::ampf<Precision> temp;
5966 
5967 
5968  if( m1>m2 || n1>n2 )
5969  {
5970  return;
5971  }
5972 
5973  //
5974  // Form P * A
5975  //
5976  if( isforward )
5977  {
5978  if( n1!=n2 )
5979  {
5980 
5981  //
5982  // Common case: N1<>N2
5983  //
5984  for(j=m1; j<=m2-1; j++)
5985  {
5986  ctemp = c(j-m1+1);
5987  stemp = s(j-m1+1);
5988  if( ctemp!=1 || stemp!=0 )
5989  {
5990  jp1 = j+1;
5991  ap::vmove(work.getvector(n1, n2), a.getrow(jp1, n1, n2), ctemp);
5992  ap::vsub(work.getvector(n1, n2), a.getrow(j, n1, n2), stemp);
5993  ap::vmul(a.getrow(j, n1, n2), ctemp);
5994  ap::vadd(a.getrow(j, n1, n2), a.getrow(jp1, n1, n2), stemp);
5995  ap::vmove(a.getrow(jp1, n1, n2), work.getvector(n1, n2));
5996  }
5997  }
5998  }
5999  else
6000  {
6001 
6002  //
6003  // Special case: N1=N2
6004  //
6005  for(j=m1; j<=m2-1; j++)
6006  {
6007  ctemp = c(j-m1+1);
6008  stemp = s(j-m1+1);
6009  if( ctemp!=1 || stemp!=0 )
6010  {
6011  temp = a(j+1,n1);
6012  a(j+1,n1) = ctemp*temp-stemp*a(j,n1);
6013  a(j,n1) = stemp*temp+ctemp*a(j,n1);
6014  }
6015  }
6016  }
6017  }
6018  else
6019  {
6020  if( n1!=n2 )
6021  {
6022 
6023  //
6024  // Common case: N1<>N2
6025  //
6026  for(j=m2-1; j>=m1; j--)
6027  {
6028  ctemp = c(j-m1+1);
6029  stemp = s(j-m1+1);
6030  if( ctemp!=1 || stemp!=0 )
6031  {
6032  jp1 = j+1;
6033  ap::vmove(work.getvector(n1, n2), a.getrow(jp1, n1, n2), ctemp);
6034  ap::vsub(work.getvector(n1, n2), a.getrow(j, n1, n2), stemp);
6035  ap::vmul(a.getrow(j, n1, n2), ctemp);
6036  ap::vadd(a.getrow(j, n1, n2), a.getrow(jp1, n1, n2), stemp);
6037  ap::vmove(a.getrow(jp1, n1, n2), work.getvector(n1, n2));
6038  }
6039  }
6040  }
6041  else
6042  {
6043 
6044  //
6045  // Special case: N1=N2
6046  //
6047  for(j=m2-1; j>=m1; j--)
6048  {
6049  ctemp = c(j-m1+1);
6050  stemp = s(j-m1+1);
6051  if( ctemp!=1 || stemp!=0 )
6052  {
6053  temp = a(j+1,n1);
6054  a(j+1,n1) = ctemp*temp-stemp*a(j,n1);
6055  a(j,n1) = stemp*temp+ctemp*a(j,n1);
6056  }
6057  }
6058  }
6059  }
6060  }
6061 
6062 
6063  /*************************************************************************
6064  Application of a sequence of elementary rotations to a matrix
6065 
6066  The algorithm post-multiplies the matrix by a sequence of rotation
6067  transformations which is given by arrays C and S. Depending on the value
6068  of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
6069  rows are rotated, or the rows N and N-1, N-2 and N-3 and so on are rotated.
6070 
6071  Not the whole matrix but only a part of it is transformed (rows from M1
6072  to M2, columns from N1 to N2). Only the elements of this submatrix are changed.
6073 
6074  Input parameters:
6075  IsForward - the sequence of the rotation application.
6076  M1,M2 - the range of rows to be transformed.
6077  N1, N2 - the range of columns to be transformed.
6078  C,S - transformation coefficients.
6079  Array whose index ranges within [1..N2-N1].
6080  A - processed matrix.
6081  WORK - working array whose index ranges within [M1..M2].
6082 
6083  Output parameters:
6084  A - transformed matrix.
6085 
6086  Utility subroutine.
6087  *************************************************************************/
6088  template<unsigned int Precision>
6089  void applyrotationsfromtheright(bool isforward,
6090  int m1,
6091  int m2,
6092  int n1,
6093  int n2,
6098  {
6099  int j;
6100  int jp1;
6101  amp::ampf<Precision> ctemp;
6102  amp::ampf<Precision> stemp;
6103  amp::ampf<Precision> temp;
6104 
6105 
6106 
6107  //
6108  // Form A * P'
6109  //
6110  if( isforward )
6111  {
6112  if( m1!=m2 )
6113  {
6114 
6115  //
6116  // Common case: M1<>M2
6117  //
6118  for(j=n1; j<=n2-1; j++)
6119  {
6120  ctemp = c(j-n1+1);
6121  stemp = s(j-n1+1);
6122  if( ctemp!=1 || stemp!=0 )
6123  {
6124  jp1 = j+1;
6125  ap::vmove(work.getvector(m1, m2), a.getcolumn(jp1, m1, m2), ctemp);
6126  ap::vsub(work.getvector(m1, m2), a.getcolumn(j, m1, m2), stemp);
6127  ap::vmul(a.getcolumn(j, m1, m2), ctemp);
6128  ap::vadd(a.getcolumn(j, m1, m2), a.getcolumn(jp1, m1, m2), stemp);
6129  ap::vmove(a.getcolumn(jp1, m1, m2), work.getvector(m1, m2));
6130  }
6131  }
6132  }
6133  else
6134  {
6135 
6136  //
6137  // Special case: M1=M2
6138  //
6139  for(j=n1; j<=n2-1; j++)
6140  {
6141  ctemp = c(j-n1+1);
6142  stemp = s(j-n1+1);
6143  if( ctemp!=1 || stemp!=0 )
6144  {
6145  temp = a(m1,j+1);
6146  a(m1,j+1) = ctemp*temp-stemp*a(m1,j);
6147  a(m1,j) = stemp*temp+ctemp*a(m1,j);
6148  }
6149  }
6150  }
6151  }
6152  else
6153  {
6154  if( m1!=m2 )
6155  {
6156 
6157  //
6158  // Common case: M1<>M2
6159  //
6160  for(j=n2-1; j>=n1; j--)
6161  {
6162  ctemp = c(j-n1+1);
6163  stemp = s(j-n1+1);
6164  if( ctemp!=1 || stemp!=0 )
6165  {
6166  jp1 = j+1;
6167  ap::vmove(work.getvector(m1, m2), a.getcolumn(jp1, m1, m2), ctemp);
6168  ap::vsub(work.getvector(m1, m2), a.getcolumn(j, m1, m2), stemp);
6169  ap::vmul(a.getcolumn(j, m1, m2), ctemp);
6170  ap::vadd(a.getcolumn(j, m1, m2), a.getcolumn(jp1, m1, m2), stemp);
6171  ap::vmove(a.getcolumn(jp1, m1, m2), work.getvector(m1, m2));
6172  }
6173  }
6174  }
6175  else
6176  {
6177 
6178  //
6179  // Special case: M1=M2
6180  //
6181  for(j=n2-1; j>=n1; j--)
6182  {
6183  ctemp = c(j-n1+1);
6184  stemp = s(j-n1+1);
6185  if( ctemp!=1 || stemp!=0 )
6186  {
6187  temp = a(m1,j+1);
6188  a(m1,j+1) = ctemp*temp-stemp*a(m1,j);
6189  a(m1,j) = stemp*temp+ctemp*a(m1,j);
6190  }
6191  }
6192  }
6193  }
6194  }
6195 
6196 
6197  /*************************************************************************
6198  The subroutine generates the elementary rotation, so that:
6199 
6200  [ CS SN ] . [ F ] = [ R ]
6201  [ -SN CS ] [ G ] [ 0 ]
6202 
6203  CS**2 + SN**2 = 1
6204  *************************************************************************/
6205  template<unsigned int Precision>
6211  {
6214 
6215 
6216  if( g==0 )
6217  {
6218  cs = 1;
6219  sn = 0;
6220  r = f;
6221  }
6222  else
6223  {
6224  if( f==0 )
6225  {
6226  cs = 0;
6227  sn = 1;
6228  r = g;
6229  }
6230  else
6231  {
6232  f1 = f;
6233  g1 = g;
6234  r = amp::sqrt<Precision>(amp::sqr<Precision>(f1)+amp::sqr<Precision>(g1));
6235  cs = f1/r;
6236  sn = g1/r;
6237  if( amp::abs<Precision>(f)>amp::abs<Precision>(g) && cs<0 )
6238  {
6239  cs = -cs;
6240  sn = -sn;
6241  r = -r;
6242  }
6243  }
6244  }
6245  }
6246 } // namespace
6247 
6248 /* stuff included from ./bdsvd.h */
6249 
6250 /*************************************************************************
6251 Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
6252 
6253 Contributors:
6254  * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
6255  pseudocode.
6256 
6257 See subroutines comments for additional copyrights.
6258 
6259 Redistribution and use in source and binary forms, with or without
6260 modification, are permitted provided that the following conditions are
6261 met:
6262 
6263 - Redistributions of source code must retain the above copyright
6264  notice, this list of conditions and the following disclaimer.
6265 
6266 - Redistributions in binary form must reproduce the above copyright
6267  notice, this list of conditions and the following disclaimer listed
6268  in this license in the documentation and/or other materials
6269  provided with the distribution.
6270 
6271 - Neither the name of the copyright holders nor the names of its
6272  contributors may be used to endorse or promote products derived from
6273  this software without specific prior written permission.
6274 
6275 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6276 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6277 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6278 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6279 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6280 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6281 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6282 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6283 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6284 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6285 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6286 *************************************************************************/
6287 
6288 namespace bdsvd
6289 {
6290  template<unsigned int Precision>
6293  int n,
6294  bool isupper,
6295  bool isfractionalaccuracyrequired,
6297  int nru,
6299  int ncc,
6301  int ncvt);
6302  template<unsigned int Precision>
6305  int n,
6306  bool isupper,
6307  bool isfractionalaccuracyrequired,
6309  int nru,
6311  int ncc,
6313  int ncvt);
6314  template<unsigned int Precision>
6317  int n,
6318  bool isupper,
6319  bool isfractionalaccuracyrequired,
6321  int ustart,
6322  int nru,
6324  int cstart,
6325  int ncc,
6327  int vstart,
6328  int ncvt);
6329  template<unsigned int Precision>
6332  template<unsigned int Precision>
6336  amp::ampf<Precision>& ssmin,
6337  amp::ampf<Precision>& ssmax);
6338  template<unsigned int Precision>
6342  amp::ampf<Precision>& ssmin,
6343  amp::ampf<Precision>& ssmax,
6344  amp::ampf<Precision>& snr,
6345  amp::ampf<Precision>& csr,
6346  amp::ampf<Precision>& snl,
6347  amp::ampf<Precision>& csl);
6348 
6349 
6350  /*************************************************************************
6351  Singular value decomposition of a bidiagonal matrix (extended algorithm)
6352 
6353  The algorithm performs the singular value decomposition of a bidiagonal
6354  matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P -
6355  orthogonal matrices, S - diagonal matrix with non-negative elements on the
6356  main diagonal, in descending order.
6357 
6358  The algorithm finds singular values. In addition, the algorithm can
6359  calculate matrices Q and P (more precisely, not the matrices, but their
6360  product with given matrices U and VT - U*Q and (P^T)*VT)). Of course,
6361  matrices U and VT can be of any type, including identity. Furthermore, the
6362  algorithm can calculate Q'*C (this product is calculated more effectively
6363  than U*Q, because this calculation operates with rows instead of matrix
6364  columns).
6365 
6366  The feature of the algorithm is its ability to find all singular values
6367  including those which are arbitrarily close to 0 with relative accuracy
6368  close to machine precision. If the parameter IsFractionalAccuracyRequired
6369  is set to True, all singular values will have high relative accuracy close
6370  to machine precision. If the parameter is set to False, only the biggest
6371  singular value will have relative accuracy close to machine precision.
6372  The absolute error of other singular values is equal to the absolute error
6373  of the biggest singular value.
6374 
6375  Input parameters:
6376  D - main diagonal of matrix B.
6377  Array whose index ranges within [0..N-1].
6378  E - superdiagonal (or subdiagonal) of matrix B.
6379  Array whose index ranges within [0..N-2].
6380  N - size of matrix B.
6381  IsUpper - True, if the matrix is upper bidiagonal.
6382  IsFractionalAccuracyRequired -
6383  accuracy to search singular values with.
6384  U - matrix to be multiplied by Q.
6385  Array whose indexes range within [0..NRU-1, 0..N-1].
6386  The matrix can be bigger, in that case only the submatrix
6387  [0..NRU-1, 0..N-1] will be multiplied by Q.
6388  NRU - number of rows in matrix U.
6389  C - matrix to be multiplied by Q'.
6390  Array whose indexes range within [0..N-1, 0..NCC-1].
6391  The matrix can be bigger, in that case only the submatrix
6392  [0..N-1, 0..NCC-1] will be multiplied by Q'.
6393  NCC - number of columns in matrix C.
6394  VT - matrix to be multiplied by P^T.
6395  Array whose indexes range within [0..N-1, 0..NCVT-1].
6396  The matrix can be bigger, in that case only the submatrix
6397  [0..N-1, 0..NCVT-1] will be multiplied by P^T.
6398  NCVT - number of columns in matrix VT.
6399 
6400  Output parameters:
6401  D - singular values of matrix B in descending order.
6402  U - if NRU>0, contains matrix U*Q.
6403  VT - if NCVT>0, contains matrix (P^T)*VT.
6404  C - if NCC>0, contains matrix Q'*C.
6405 
6406  Result:
6407  True, if the algorithm has converged.
6408  False, if the algorithm hasn't converged (rare case).
6409 
6410  Additional information:
6411  The type of convergence is controlled by the internal parameter TOL.
6412  If the parameter is greater than 0, the singular values will have
6413  relative accuracy TOL. If TOL<0, the singular values will have
6414  absolute accuracy ABS(TOL)*norm(B).
6415  By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon,
6416  where Epsilon is the machine precision. It is not recommended to use
6417  TOL less than 10*Epsilon since this will considerably slow down the
6418  algorithm and may not lead to error decreasing.
6419  History:
6420  * 31 March, 2007.
6421  changed MAXITR from 6 to 12.
6422 
6423  -- LAPACK routine (version 3.0) --
6424  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
6425  Courant Institute, Argonne National Lab, and Rice University
6426  October 31, 1999.
6427  *************************************************************************/
6428  template<unsigned int Precision>
6431  int n,
6432  bool isupper,
6433  bool isfractionalaccuracyrequired,
6435  int nru,
6437  int ncc,
6439  int ncvt)
6440  {
6441  bool result;
6444 
6445 
6446  d1.setbounds(1, n);
6447  ap::vmove(d1.getvector(1, n), d.getvector(0, n-1));
6448  if( n>1 )
6449  {
6450  e1.setbounds(1, n-1);
6451  ap::vmove(e1.getvector(1, n-1), e.getvector(0, n-2));
6452  }
6453  result = bidiagonalsvddecompositioninternal<Precision>(d1, e1, n, isupper, isfractionalaccuracyrequired, u, 0, nru, c, 0, ncc, vt, 0, ncvt);
6454  ap::vmove(d.getvector(0, n-1), d1.getvector(1, n));
6455  return result;
6456  }
6457 
6458 
6459  /*************************************************************************
6460  Obsolete 1-based subroutine. See RMatrixBDSVD for 0-based replacement.
6461 
6462  History:
6463  * 31 March, 2007.
6464  changed MAXITR from 6 to 12.
6465 
6466  -- LAPACK routine (version 3.0) --
6467  Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
6468  Courant Institute, Argonne National Lab, and Rice University
6469  October 31, 1999.
6470  *************************************************************************/
6471  template<unsigned int Precision>
6474  int n,
6475  bool isupper,
6476  bool isfractionalaccuracyrequired,
6478  int nru,
6480  int ncc,
6482  int ncvt)
6483  {
6484  bool result;
6485 
6486 
6487  result = bidiagonalsvddecompositioninternal<Precision>(d, e, n, isupper, isfractionalaccuracyrequired, u, 1, nru, c, 1, ncc, vt, 1, ncvt);
6488  return result;
6489  }
6490 
6491 
6492  /*************************************************************************
6493  Internal working subroutine for bidiagonal decomposition
6494  *************************************************************************/
6495  template<unsigned int Precision>
6498  int n,
6499  bool isupper,
6500  bool isfractionalaccuracyrequired,
6502  int ustart,
6503  int nru,
6505  int cstart,
6506  int ncc,
6508  int vstart,
6509  int ncvt)
6510  {
6511  bool result;
6512  int i;
6513  int idir;
6514  int isub;
6515  int iter;
6516  int j;
6517  int ll;
6518  int lll;
6519  int m;
6520  int maxit;
6521  int oldll;
6522  int oldm;
6523  amp::ampf<Precision> abse;
6524  amp::ampf<Precision> abss;
6525  amp::ampf<Precision> cosl;
6526  amp::ampf<Precision> cosr;
6533  amp::ampf<Precision> oldcs;
6534  amp::ampf<Precision> oldsn;
6536  amp::ampf<Precision> shift;
6537  amp::ampf<Precision> sigmn;
6538  amp::ampf<Precision> sigmx;
6539  amp::ampf<Precision> sinl;
6540  amp::ampf<Precision> sinr;
6542  amp::ampf<Precision> smax;
6543  amp::ampf<Precision> smin;
6544  amp::ampf<Precision> sminl;
6545  amp::ampf<Precision> sminlo;
6546  amp::ampf<Precision> sminoa;
6548  amp::ampf<Precision> thresh;
6550  amp::ampf<Precision> tolmul;
6551  amp::ampf<Precision> unfl;
6556  int maxitr;
6557  bool matrixsplitflag;
6558  bool iterflag;
6563  bool fwddir;
6565  int mm1;
6566  int mm0;
6567  bool bchangedir;
6568  int uend;
6569  int cend;
6570  int vend;
6571 
6572 
6573  result = true;
6574  if( n==0 )
6575  {
6576  return result;
6577  }
6578  if( n==1 )
6579  {
6580  if( d(1)<0 )
6581  {
6582  d(1) = -d(1);
6583  if( ncvt>0 )
6584  {
6585  ap::vmul(vt.getrow(vstart, vstart, vstart+ncvt-1), -1);
6586  }
6587  }
6588  return result;
6589  }
6590 
6591  //
6592  // init
6593  //
6594  work0.setbounds(1, n-1);
6595  work1.setbounds(1, n-1);
6596  work2.setbounds(1, n-1);
6597  work3.setbounds(1, n-1);
6598  uend = ustart+ap::maxint(nru-1, 0);
6599  vend = vstart+ap::maxint(ncvt-1, 0);
6600  cend = cstart+ap::maxint(ncc-1, 0);
6601  utemp.setbounds(ustart, uend);
6602  vttemp.setbounds(vstart, vend);
6603  ctemp.setbounds(cstart, cend);
6604  maxitr = 12;
6605  fwddir = true;
6606 
6607  //
6608  // resize E from N-1 to N
6609  //
6610  etemp.setbounds(1, n);
6611  for(i=1; i<=n-1; i++)
6612  {
6613  etemp(i) = e(i);
6614  }
6615  e.setbounds(1, n);
6616  for(i=1; i<=n-1; i++)
6617  {
6618  e(i) = etemp(i);
6619  }
6620  e(n) = 0;
6621  idir = 0;
6622 
6623  //
6624  // Get machine constants
6625  //
6628 
6629  //
6630  // If matrix lower bidiagonal, rotate to be upper bidiagonal
6631  // by applying Givens rotations on the left
6632  //
6633  if( !isupper )
6634  {
6635  for(i=1; i<=n-1; i++)
6636  {
6637  rotations::generaterotation<Precision>(d(i), e(i), cs, sn, r);
6638  d(i) = r;
6639  e(i) = sn*d(i+1);
6640  d(i+1) = cs*d(i+1);
6641  work0(i) = cs;
6642  work1(i) = sn;
6643  }
6644 
6645  //
6646  // Update singular vectors if desired
6647  //
6648  if( nru>0 )
6649  {
6650  rotations::applyrotationsfromtheright<Precision>(fwddir, ustart, uend, 1+ustart-1, n+ustart-1, work0, work1, u, utemp);
6651  }
6652  if( ncc>0 )
6653  {
6654  rotations::applyrotationsfromtheleft<Precision>(fwddir, 1+cstart-1, n+cstart-1, cstart, cend, work0, work1, c, ctemp);
6655  }
6656  }
6657 
6658  //
6659  // Compute singular values to relative accuracy TOL
6660  // (By setting TOL to be negative, algorithm will compute
6661  // singular values to absolute accuracy ABS(TOL)*norm(input matrix))
6662  //
6663  tolmul = amp::maximum<Precision>(10, amp::minimum<Precision>(100, amp::pow<Precision>(eps, -amp::ampf<Precision>("0.125"))));
6664  tol = tolmul*eps;
6665  if( !isfractionalaccuracyrequired )
6666  {
6667  tol = -tol;
6668  }
6669 
6670  //
6671  // Compute approximate maximum, minimum singular values
6672  //
6673  smax = 0;
6674  for(i=1; i<=n; i++)
6675  {
6676  smax = amp::maximum<Precision>(smax, amp::abs<Precision>(d(i)));
6677  }
6678  for(i=1; i<=n-1; i++)
6679  {
6680  smax = amp::maximum<Precision>(smax, amp::abs<Precision>(e(i)));
6681  }
6682  sminl = 0;
6683  if( tol>=0 )
6684  {
6685 
6686  //
6687  // Relative accuracy desired
6688  //
6689  sminoa = amp::abs<Precision>(d(1));
6690  if( sminoa!=0 )
6691  {
6692  mu = sminoa;
6693  for(i=2; i<=n; i++)
6694  {
6695  mu = amp::abs<Precision>(d(i))*(mu/(mu+amp::abs<Precision>(e(i-1))));
6696  sminoa = amp::minimum<Precision>(sminoa, mu);
6697  if( sminoa==0 )
6698  {
6699  break;
6700  }
6701  }
6702  }
6703  sminoa = sminoa/amp::sqrt<Precision>(n);
6704  thresh = amp::maximum<Precision>(tol*sminoa, maxitr*n*n*unfl);
6705  }
6706  else
6707  {
6708 
6709  //
6710  // Absolute accuracy desired
6711  //
6712  thresh = amp::maximum<Precision>(amp::abs<Precision>(tol)*smax, maxitr*n*n*unfl);
6713  }
6714 
6715  //
6716  // Prepare for main iteration loop for the singular values
6717  // (MAXIT is the maximum number of passes through the inner
6718  // loop permitted before nonconvergence signalled.)
6719  //
6720  maxit = maxitr*n*n;
6721  iter = 0;
6722  oldll = -1;
6723  oldm = -1;
6724 
6725  //
6726  // M points to last element of unconverged part of matrix
6727  //
6728  m = n;
6729 
6730  //
6731  // Begin main iteration loop
6732  //
6733  while( true )
6734  {
6735 
6736  //
6737  // Check for convergence or exceeding iteration count
6738  //
6739  if( m<=1 )
6740  {
6741  break;
6742  }
6743  if( iter>maxit )
6744  {
6745  result = false;
6746  return result;
6747  }
6748 
6749  //
6750  // Find diagonal block of matrix to work on
6751  //
6752  if( tol<0 && amp::abs<Precision>(d(m))<=thresh )
6753  {
6754  d(m) = 0;
6755  }
6756  smax = amp::abs<Precision>(d(m));
6757  smin = smax;
6758  matrixsplitflag = false;
6759  for(lll=1; lll<=m-1; lll++)
6760  {
6761  ll = m-lll;
6762  abss = amp::abs<Precision>(d(ll));
6763  abse = amp::abs<Precision>(e(ll));
6764  if( tol<0 && abss<=thresh )
6765  {
6766  d(ll) = 0;
6767  }
6768  if( abse<=thresh )
6769  {
6770  matrixsplitflag = true;
6771  break;
6772  }
6773  smin = amp::minimum<Precision>(smin, abss);
6774  smax = amp::maximum<Precision>(smax, amp::maximum<Precision>(abss, abse));
6775  }
6776  if( !matrixsplitflag )
6777  {
6778  ll = 0;
6779  }
6780  else
6781  {
6782 
6783  //
6784  // Matrix splits since E(LL) = 0
6785  //
6786  e(ll) = 0;
6787  if( ll==m-1 )
6788  {
6789 
6790  //
6791  // Convergence of bottom singular value, return to top of loop
6792  //
6793  m = m-1;
6794  continue;
6795  }
6796  }
6797  ll = ll+1;
6798 
6799  //
6800  // E(LL) through E(M-1) are nonzero, E(LL-1) is zero
6801  //
6802  if( ll==m-1 )
6803  {
6804 
6805  //
6806  // 2 by 2 block, handle separately
6807  //
6808  svdv2x2<Precision>(d(m-1), e(m-1), d(m), sigmn, sigmx, sinr, cosr, sinl, cosl);
6809  d(m-1) = sigmx;
6810  e(m-1) = 0;
6811  d(m) = sigmn;
6812 
6813  //
6814  // Compute singular vectors, if desired
6815  //
6816  if( ncvt>0 )
6817  {
6818  mm0 = m+(vstart-1);
6819  mm1 = m-1+(vstart-1);
6820  ap::vmove(vttemp.getvector(vstart, vend), vt.getrow(mm1, vstart, vend), cosr);
6821  ap::vadd(vttemp.getvector(vstart, vend), vt.getrow(mm0, vstart, vend), sinr);
6822  ap::vmul(vt.getrow(mm0, vstart, vend), cosr);
6823  ap::vsub(vt.getrow(mm0, vstart, vend), vt.getrow(mm1, vstart, vend), sinr);
6824  ap::vmove(vt.getrow(mm1, vstart, vend), vttemp.getvector(vstart, vend));
6825  }
6826  if( nru>0 )
6827  {
6828  mm0 = m+ustart-1;
6829  mm1 = m-1+ustart-1;
6830  ap::vmove(utemp.getvector(ustart, uend), u.getcolumn(mm1, ustart, uend), cosl);
6831  ap::vadd(utemp.getvector(ustart, uend), u.getcolumn(mm0, ustart, uend), sinl);
6832  ap::vmul(u.getcolumn(mm0, ustart, uend), cosl);
6833  ap::vsub(u.getcolumn(mm0, ustart, uend), u.getcolumn(mm1, ustart, uend), sinl);
6834  ap::vmove(u.getcolumn(mm1, ustart, uend), utemp.getvector(ustart, uend));
6835  }
6836  if( ncc>0 )
6837  {
6838  mm0 = m+cstart-1;
6839  mm1 = m-1+cstart-1;
6840  ap::vmove(ctemp.getvector(cstart, cend), c.getrow(mm1, cstart, cend), cosl);
6841  ap::vadd(ctemp.getvector(cstart, cend), c.getrow(mm0, cstart, cend), sinl);
6842  ap::vmul(c.getrow(mm0, cstart, cend), cosl);
6843  ap::vsub(c.getrow(mm0, cstart, cend), c.getrow(mm1, cstart, cend), sinl);
6844  ap::vmove(c.getrow(mm1, cstart, cend), ctemp.getvector(cstart, cend));
6845  }
6846  m = m-2;
6847  continue;
6848  }
6849 
6850  //
6851  // If working on new submatrix, choose shift direction
6852  // (from larger end diagonal element towards smaller)
6853  //
6854  // Previously was
6855  // "if (LL>OLDM) or (M<OLDLL) then"
6856  // fixed thanks to Michael Rolle < m@rolle.name >
6857  // Very strange that LAPACK still contains it.
6858  //
6859  bchangedir = false;
6860  if( idir==1 && amp::abs<Precision>(d(ll))<amp::ampf<Precision>("1.0E-3")*amp::abs<Precision>(d(m)) )
6861  {
6862  bchangedir = true;
6863  }
6864  if( idir==2 && amp::abs<Precision>(d(m))<amp::ampf<Precision>("1.0E-3")*amp::abs<Precision>(d(ll)) )
6865  {
6866  bchangedir = true;
6867  }
6868  if( ll!=oldll || m!=oldm || bchangedir )
6869  {
6870  if( amp::abs<Precision>(d(ll))>=amp::abs<Precision>(d(m)) )
6871  {
6872 
6873  //
6874  // Chase bulge from top (big end) to bottom (small end)
6875  //
6876  idir = 1;
6877  }
6878  else
6879  {
6880 
6881  //
6882  // Chase bulge from bottom (big end) to top (small end)
6883  //
6884  idir = 2;
6885  }
6886  }
6887 
6888  //
6889  // Apply convergence tests
6890  //
6891  if( idir==1 )
6892  {
6893 
6894  //
6895  // Run convergence test in forward direction
6896  // First apply standard test to bottom of matrix
6897  //
6898  if( amp::abs<Precision>(e(m-1))<=amp::abs<Precision>(tol)*amp::abs<Precision>(d(m)) || tol<0 && amp::abs<Precision>(e(m-1))<=thresh )
6899  {
6900  e(m-1) = 0;
6901  continue;
6902  }
6903  if( tol>=0 )
6904  {
6905 
6906  //
6907  // If relative accuracy desired,
6908  // apply convergence criterion forward
6909  //
6910  mu = amp::abs<Precision>(d(ll));
6911  sminl = mu;
6912  iterflag = false;
6913  for(lll=ll; lll<=m-1; lll++)
6914  {
6915  if( amp::abs<Precision>(e(lll))<=tol*mu )
6916  {
6917  e(lll) = 0;
6918  iterflag = true;
6919  break;
6920  }
6921  sminlo = sminl;
6922  mu = amp::abs<Precision>(d(lll+1))*(mu/(mu+amp::abs<Precision>(e(lll))));
6923  sminl = amp::minimum<Precision>(sminl, mu);
6924  }
6925  if( iterflag )
6926  {
6927  continue;
6928  }
6929  }
6930  }
6931  else
6932  {
6933 
6934  //
6935  // Run convergence test in backward direction
6936  // First apply standard test to top of matrix
6937  //
6938  if( amp::abs<Precision>(e(ll))<=amp::abs<Precision>(tol)*amp::abs<Precision>(d(ll)) || tol<0 && amp::abs<Precision>(e(ll))<=thresh )
6939  {
6940  e(ll) = 0;
6941  continue;
6942  }
6943  if( tol>=0 )
6944  {
6945 
6946  //
6947  // If relative accuracy desired,
6948  // apply convergence criterion backward
6949  //
6950  mu = amp::abs<Precision>(d(m));
6951  sminl = mu;
6952  iterflag = false;
6953  for(lll=m-1; lll>=ll; lll--)
6954  {
6955  if( amp::abs<Precision>(e(lll))<=tol*mu )
6956  {
6957  e(lll) = 0;
6958  iterflag = true;
6959  break;
6960  }
6961  sminlo = sminl;
6962  mu = amp::abs<Precision>(d(lll))*(mu/(mu+amp::abs<Precision>(e(lll))));
6963  sminl = amp::minimum<Precision>(sminl, mu);
6964  }
6965  if( iterflag )
6966  {
6967  continue;
6968  }
6969  }
6970  }
6971  oldll = ll;
6972  oldm = m;
6973 
6974  //
6975  // Compute shift. First, test if shifting would ruin relative
6976  // accuracy, and if so set the shift to zero.
6977  //
6978  if( tol>=0 && n*tol*(sminl/smax)<=amp::maximum<Precision>(eps, amp::ampf<Precision>("0.01")*tol) )
6979  {
6980 
6981  //
6982  // Use a zero shift to avoid loss of relative accuracy
6983  //
6984  shift = 0;
6985  }
6986  else
6987  {
6988 
6989  //
6990  // Compute the shift from 2-by-2 block at end of matrix
6991  //
6992  if( idir==1 )
6993  {
6994  sll = amp::abs<Precision>(d(ll));
6995  svd2x2<Precision>(d(m-1), e(m-1), d(m), shift, r);
6996  }
6997  else
6998  {
6999  sll = amp::abs<Precision>(d(m));
7000  svd2x2<Precision>(d(ll), e(ll), d(ll+1), shift, r);
7001  }
7002 
7003  //
7004  // Test if shift negligible, and if so set to zero
7005  //
7006  if( sll>0 )
7007  {
7008  if( amp::sqr<Precision>(shift/sll)<eps )
7009  {
7010  shift = 0;
7011  }
7012  }
7013  }
7014 
7015  //
7016  // Increment iteration count
7017  //
7018  iter = iter+m-ll;
7019 
7020  //
7021  // If SHIFT = 0, do simplified QR iteration
7022  //
7023  if( shift==0 )
7024  {
7025  if( idir==1 )
7026  {
7027 
7028  //
7029  // Chase bulge from top to bottom
7030  // Save cosines and sines for later singular vector updates
7031  //
7032  cs = 1;
7033  oldcs = 1;
7034  for(i=ll; i<=m-1; i++)
7035  {
7036  rotations::generaterotation<Precision>(d(i)*cs, e(i), cs, sn, r);
7037  if( i>ll )
7038  {
7039  e(i-1) = oldsn*r;
7040  }
7041  rotations::generaterotation<Precision>(oldcs*r, d(i+1)*sn, oldcs, oldsn, tmp);
7042  d(i) = tmp;
7043  work0(i-ll+1) = cs;
7044  work1(i-ll+1) = sn;
7045  work2(i-ll+1) = oldcs;
7046  work3(i-ll+1) = oldsn;
7047  }
7048  h = d(m)*cs;
7049  d(m) = h*oldcs;
7050  e(m-1) = h*oldsn;
7051 
7052  //
7053  // Update singular vectors
7054  //
7055  if( ncvt>0 )
7056  {
7057  rotations::applyrotationsfromtheleft<Precision>(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, work0, work1, vt, vttemp);
7058  }
7059  if( nru>0 )
7060  {
7061  rotations::applyrotationsfromtheright<Precision>(fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work2, work3, u, utemp);
7062  }
7063  if( ncc>0 )
7064  {
7065  rotations::applyrotationsfromtheleft<Precision>(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work2, work3, c, ctemp);
7066  }
7067 
7068  //
7069  // Test convergence
7070  //
7071  if( amp::abs<Precision>(e(m-1))<=thresh )
7072  {
7073  e(m-1) = 0;
7074  }
7075  }
7076  else
7077  {
7078 
7079  //
7080  // Chase bulge from bottom to top
7081  // Save cosines and sines for later singular vector updates
7082  //
7083  cs = 1;
7084  oldcs = 1;
7085  for(i=m; i>=ll+1; i--)
7086  {
7087  rotations::generaterotation<Precision>(d(i)*cs, e(i-1), cs, sn, r);
7088  if( i<m )
7089  {
7090  e(i) = oldsn*r;
7091  }
7092  rotations::generaterotation<Precision>(oldcs*r, d(i-1)*sn, oldcs, oldsn, tmp);
7093  d(i) = tmp;
7094  work0(i-ll) = cs;
7095  work1(i-ll) = -sn;
7096  work2(i-ll) = oldcs;
7097  work3(i-ll) = -oldsn;
7098  }
7099  h = d(ll)*cs;
7100  d(ll) = h*oldcs;
7101  e(ll) = h*oldsn;
7102 
7103  //
7104  // Update singular vectors
7105  //
7106  if( ncvt>0 )
7107  {
7108  rotations::applyrotationsfromtheleft<Precision>(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, work2, work3, vt, vttemp);
7109  }
7110  if( nru>0 )
7111  {
7112  rotations::applyrotationsfromtheright<Precision>(!fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work0, work1, u, utemp);
7113  }
7114  if( ncc>0 )
7115  {
7116  rotations::applyrotationsfromtheleft<Precision>(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work0, work1, c, ctemp);
7117  }
7118 
7119  //
7120  // Test convergence
7121  //
7122  if( amp::abs<Precision>(e(ll))<=thresh )
7123  {
7124  e(ll) = 0;
7125  }
7126  }
7127  }
7128  else
7129  {
7130 
7131  //
7132  // Use nonzero shift
7133  //
7134  if( idir==1 )
7135  {
7136 
7137  //
7138  // Chase bulge from top to bottom
7139  // Save cosines and sines for later singular vector updates
7140  //
7141  f = (amp::abs<Precision>(d(ll))-shift)*(extsignbdsqr<Precision>(1, d(ll))+shift/d(ll));
7142  g = e(ll);
7143  for(i=ll; i<=m-1; i++)
7144  {
7145  rotations::generaterotation<Precision>(f, g, cosr, sinr, r);
7146  if( i>ll )
7147  {
7148  e(i-1) = r;
7149  }
7150  f = cosr*d(i)+sinr*e(i);
7151  e(i) = cosr*e(i)-sinr*d(i);
7152  g = sinr*d(i+1);
7153  d(i+1) = cosr*d(i+1);
7154  rotations::generaterotation<Precision>(f, g, cosl, sinl, r);
7155  d(i) = r;
7156  f = cosl*e(i)+sinl*d(i+1);
7157  d(i+1) = cosl*d(i+1)-sinl*e(i);
7158  if( i<m-1 )
7159  {
7160  g = sinl*e(i+1);
7161  e(i+1) = cosl*e(i+1);
7162  }
7163  work0(i-ll+1) = cosr;
7164  work1(i-ll+1) = sinr;
7165  work2(i-ll+1) = cosl;
7166  work3(i-ll+1) = sinl;
7167  }
7168  e(m-1) = f;
7169 
7170  //
7171  // Update singular vectors
7172  //
7173  if( ncvt>0 )
7174  {
7175  rotations::applyrotationsfromtheleft<Precision>(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, work0, work1, vt, vttemp);
7176  }
7177  if( nru>0 )
7178  {
7179  rotations::applyrotationsfromtheright<Precision>(fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work2, work3, u, utemp);
7180  }
7181  if( ncc>0 )
7182  {
7183  rotations::applyrotationsfromtheleft<Precision>(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work2, work3, c, ctemp);
7184  }
7185 
7186  //
7187  // Test convergence
7188  //
7189  if( amp::abs<Precision>(e(m-1))<=thresh )
7190  {
7191  e(m-1) = 0;
7192  }
7193  }
7194  else
7195  {
7196 
7197  //
7198  // Chase bulge from bottom to top
7199  // Save cosines and sines for later singular vector updates
7200  //
7201  f = (amp::abs<Precision>(d(m))-shift)*(extsignbdsqr<Precision>(1, d(m))+shift/d(m));
7202  g = e(m-1);
7203  for(i=m; i>=ll+1; i--)
7204  {
7205  rotations::generaterotation<Precision>(f, g, cosr, sinr, r);
7206  if( i<m )
7207  {
7208  e(i) = r;
7209  }
7210  f = cosr*d(i)+sinr*e(i-1);
7211  e(i-1) = cosr*e(i-1)-sinr*d(i);
7212  g = sinr*d(i-1);
7213  d(i-1) = cosr*d(i-1);
7214  rotations::generaterotation<Precision>(f, g, cosl, sinl, r);
7215  d(i) = r;
7216  f = cosl*e(i-1)+sinl*d(i-1);
7217  d(i-1) = cosl*d(i-1)-sinl*e(i-1);
7218  if( i>ll+1 )
7219  {
7220  g = sinl*e(i-2);
7221  e(i-2) = cosl*e(i-2);
7222  }
7223  work0(i-ll) = cosr;
7224  work1(i-ll) = -sinr;
7225  work2(i-ll) = cosl;
7226  work3(i-ll) = -sinl;
7227  }
7228  e(ll) = f;
7229 
7230  //
7231  // Test convergence
7232  //
7233  if( amp::abs<Precision>(e(ll))<=thresh )
7234  {
7235  e(ll) = 0;
7236  }
7237 
7238  //
7239  // Update singular vectors if desired
7240  //
7241  if( ncvt>0 )
7242  {
7243  rotations::applyrotationsfromtheleft<Precision>(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, work2, work3, vt, vttemp);
7244  }
7245  if( nru>0 )
7246  {
7247  rotations::applyrotationsfromtheright<Precision>(!fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work0, work1, u, utemp);
7248  }
7249  if( ncc>0 )
7250  {
7251  rotations::applyrotationsfromtheleft<Precision>(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work0, work1, c, ctemp);
7252  }
7253  }
7254  }
7255 
7256  //
7257  // QR iteration finished, go back and check convergence
7258  //
7259  continue;
7260  }
7261 
7262  //
7263  // All singular values converged, so make them positive
7264  //
7265  for(i=1; i<=n; i++)
7266  {
7267  if( d(i)<0 )
7268  {
7269  d(i) = -d(i);
7270 
7271  //
7272  // Change sign of singular vectors, if desired
7273  //
7274  if( ncvt>0 )
7275  {
7276  ap::vmul(vt.getrow(i+vstart-1, vstart, vend), -1);
7277  }
7278  }
7279  }
7280 
7281  //
7282  // Sort the singular values into decreasing order (insertion sort on
7283  // singular values, but only one transposition per singular vector)
7284  //
7285  for(i=1; i<=n-1; i++)
7286  {
7287 
7288  //
7289  // Scan for smallest D(I)
7290  //
7291  isub = 1;
7292  smin = d(1);
7293  for(j=2; j<=n+1-i; j++)
7294  {
7295  if( d(j)<=smin )
7296  {
7297  isub = j;
7298  smin = d(j);
7299  }
7300  }
7301  if( isub!=n+1-i )
7302  {
7303 
7304  //
7305  // Swap singular values and vectors
7306  //
7307  d(isub) = d(n+1-i);
7308  d(n+1-i) = smin;
7309  if( ncvt>0 )
7310  {
7311  j = n+1-i;
7312  ap::vmove(vttemp.getvector(vstart, vend), vt.getrow(isub+vstart-1, vstart, vend));
7313  ap::vmove(vt.getrow(isub+vstart-1, vstart, vend), vt.getrow(j+vstart-1, vstart, vend));
7314  ap::vmove(vt.getrow(j+vstart-1, vstart, vend), vttemp.getvector(vstart, vend));
7315  }
7316  if( nru>0 )
7317  {
7318  j = n+1-i;
7319  ap::vmove(utemp.getvector(ustart, uend), u.getcolumn(isub+ustart-1, ustart, uend));
7320  ap::vmove(u.getcolumn(isub+ustart-1, ustart, uend), u.getcolumn(j+ustart-1, ustart, uend));
7321  ap::vmove(u.getcolumn(j+ustart-1, ustart, uend), utemp.getvector(ustart, uend));
7322  }
7323  if( ncc>0 )
7324  {
7325  j = n+1-i;
7326  ap::vmove(ctemp.getvector(cstart, cend), c.getrow(isub+cstart-1, cstart, cend));
7327  ap::vmove(c.getrow(isub+cstart-1, cstart, cend), c.getrow(j+cstart-1, cstart, cend));
7328  ap::vmove(c.getrow(j+cstart-1, cstart, cend), ctemp.getvector(cstart, cend));
7329  }
7330  }
7331  }
7332  return result;
7333  }
7334 
7335 
7336  template<unsigned int Precision>
7339  {
7341 
7342 
7343  if( b>=0 )
7344  {
7345  result = amp::abs<Precision>(a);
7346  }
7347  else
7348  {
7349  result = -amp::abs<Precision>(a);
7350  }
7351  return result;
7352  }
7353 
7354 
7355  template<unsigned int Precision>
7359  amp::ampf<Precision>& ssmin,
7360  amp::ampf<Precision>& ssmax)
7361  {
7367  amp::ampf<Precision> fhmn;
7368  amp::ampf<Precision> fhmx;
7371 
7372 
7373  fa = amp::abs<Precision>(f);
7374  ga = amp::abs<Precision>(g);
7375  ha = amp::abs<Precision>(h);
7376  fhmn = amp::minimum<Precision>(fa, ha);
7377  fhmx = amp::maximum<Precision>(fa, ha);
7378  if( fhmn==0 )
7379  {
7380  ssmin = 0;
7381  if( fhmx==0 )
7382  {
7383  ssmax = ga;
7384  }
7385  else
7386  {
7387  ssmax = amp::maximum<Precision>(fhmx, ga)*amp::sqrt<Precision>(1+amp::sqr<Precision>(amp::minimum<Precision>(fhmx, ga)/amp::maximum<Precision>(fhmx, ga)));
7388  }
7389  }
7390  else
7391  {
7392  if( ga<fhmx )
7393  {
7394  aas = 1+fhmn/fhmx;
7395  at = (fhmx-fhmn)/fhmx;
7396  au = amp::sqr<Precision>(ga/fhmx);
7397  c = 2/(amp::sqrt<Precision>(aas*aas+au)+amp::sqrt<Precision>(at*at+au));
7398  ssmin = fhmn*c;
7399  ssmax = fhmx/c;
7400  }
7401  else
7402  {
7403  au = fhmx/ga;
7404  if( au==0 )
7405  {
7406 
7407  //
7408  // Avoid possible harmful underflow if exponent range
7409  // asymmetric (true SSMIN may not underflow even if
7410  // AU underflows)
7411  //
7412  ssmin = fhmn*fhmx/ga;
7413  ssmax = ga;
7414  }
7415  else
7416  {
7417  aas = 1+fhmn/fhmx;
7418  at = (fhmx-fhmn)/fhmx;
7419  c = 1/(amp::sqrt<Precision>(1+amp::sqr<Precision>(aas*au))+amp::sqrt<Precision>(1+amp::sqr<Precision>(at*au)));
7420  ssmin = fhmn*c*au;
7421  ssmin = ssmin+ssmin;
7422  ssmax = ga/(c+c);
7423  }
7424  }
7425  }
7426  }
7427 
7428 
7429  template<unsigned int Precision>
7433  amp::ampf<Precision>& ssmin,
7434  amp::ampf<Precision>& ssmax,
7435  amp::ampf<Precision>& snr,
7436  amp::ampf<Precision>& csr,
7437  amp::ampf<Precision>& snl,
7438  amp::ampf<Precision>& csl)
7439  {
7440  bool gasmal;
7441  bool swp;
7442  int pmax;
7461  amp::ampf<Precision> temp;
7462  amp::ampf<Precision> tsign;
7465 
7466 
7467  ft = f;
7468  fa = amp::abs<Precision>(ft);
7469  ht = h;
7470  ha = amp::abs<Precision>(h);
7471 
7472  //
7473  // PMAX points to the maximum absolute element of matrix
7474  // PMAX = 1 if F largest in absolute values
7475  // PMAX = 2 if G largest in absolute values
7476  // PMAX = 3 if H largest in absolute values
7477  //
7478  pmax = 1;
7479  swp = ha>fa;
7480  if( swp )
7481  {
7482 
7483  //
7484  // Now FA .ge. HA
7485  //
7486  pmax = 3;
7487  temp = ft;
7488  ft = ht;
7489  ht = temp;
7490  temp = fa;
7491  fa = ha;
7492  ha = temp;
7493  }
7494  gt = g;
7495  ga = amp::abs<Precision>(gt);
7496  if( ga==0 )
7497  {
7498 
7499  //
7500  // Diagonal matrix
7501  //
7502  ssmin = ha;
7503  ssmax = fa;
7504  clt = 1;
7505  crt = 1;
7506  slt = 0;
7507  srt = 0;
7508  }
7509  else
7510  {
7511  gasmal = true;
7512  if( ga>fa )
7513  {
7514  pmax = 2;
7516  {
7517 
7518  //
7519  // Case of very large GA
7520  //
7521  gasmal = false;
7522  ssmax = ga;
7523  if( ha>1 )
7524  {
7525  v = ga/ha;
7526  ssmin = fa/v;
7527  }
7528  else
7529  {
7530  v = fa/ga;
7531  ssmin = v*ha;
7532  }
7533  clt = 1;
7534  slt = ht/gt;
7535  srt = 1;
7536  crt = ft/gt;
7537  }
7538  }
7539  if( gasmal )
7540  {
7541 
7542  //
7543  // Normal case
7544  //
7545  d = fa-ha;
7546  if( d==fa )
7547  {
7548  l = 1;
7549  }
7550  else
7551  {
7552  l = d/fa;
7553  }
7554  m = gt/ft;
7555  t = 2-l;
7556  mm = m*m;
7557  tt = t*t;
7558  s = amp::sqrt<Precision>(tt+mm);
7559  if( l==0 )
7560  {
7561  r = amp::abs<Precision>(m);
7562  }
7563  else
7564  {
7565  r = amp::sqrt<Precision>(l*l+mm);
7566  }
7567  a = amp::ampf<Precision>("0.5")*(s+r);
7568  ssmin = ha/a;
7569  ssmax = fa*a;
7570  if( mm==0 )
7571  {
7572 
7573  //
7574  // Note that M is very tiny
7575  //
7576  if( l==0 )
7577  {
7578  t = extsignbdsqr<Precision>(2, ft)*extsignbdsqr<Precision>(1, gt);
7579  }
7580  else
7581  {
7582  t = gt/extsignbdsqr<Precision>(d, ft)+m/t;
7583  }
7584  }
7585  else
7586  {
7587  t = (m/(s+t)+m/(r+l))*(1+a);
7588  }
7589  l = amp::sqrt<Precision>(t*t+4);
7590  crt = 2/l;
7591  srt = t/l;
7592  clt = (crt+srt*m)/a;
7593  v = ht/ft;
7594  slt = v*srt/a;
7595  }
7596  }
7597  if( swp )
7598  {
7599  csl = srt;
7600  snl = crt;
7601  csr = slt;
7602  snr = clt;
7603  }
7604  else
7605  {
7606  csl = clt;
7607  snl = slt;
7608  csr = crt;
7609  snr = srt;
7610  }
7611 
7612  //
7613  // Correct signs of SSMAX and SSMIN
7614  //
7615  if( pmax==1 )
7616  {
7617  tsign = extsignbdsqr<Precision>(1, csr)*extsignbdsqr<Precision>(1, csl)*extsignbdsqr<Precision>(1, f);
7618  }
7619  if( pmax==2 )
7620  {
7621  tsign = extsignbdsqr<Precision>(1, snr)*extsignbdsqr<Precision>(1, csl)*extsignbdsqr<Precision>(1, g);
7622  }
7623  if( pmax==3 )
7624  {
7625  tsign = extsignbdsqr<Precision>(1, snr)*extsignbdsqr<Precision>(1, snl)*extsignbdsqr<Precision>(1, h);
7626  }
7627  ssmax = extsignbdsqr<Precision>(ssmax, tsign);
7628  ssmin = extsignbdsqr<Precision>(ssmin, tsign*extsignbdsqr<Precision>(1, f)*extsignbdsqr<Precision>(1, h));
7629  }
7630 } // namespace
7631 
7632 /* stuff included from ./svd.h */
7633 
7634 /*************************************************************************
7635 Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
7636 
7637 Redistribution and use in source and binary forms, with or without
7638 modification, are permitted provided that the following conditions are
7639 met:
7640 
7641 - Redistributions of source code must retain the above copyright
7642  notice, this list of conditions and the following disclaimer.
7643 
7644 - Redistributions in binary form must reproduce the above copyright
7645  notice, this list of conditions and the following disclaimer listed
7646  in this license in the documentation and/or other materials
7647  provided with the distribution.
7648 
7649 - Neither the name of the copyright holders nor the names of its
7650  contributors may be used to endorse or promote products derived from
7651  this software without specific prior written permission.
7652 
7653 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7654 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7655 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7656 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7657 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7658 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7659 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7660 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7661 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7662 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
7663 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7664 *************************************************************************/
7665 
7666 /*MAKEHEADER*/
7667 
7668 /*MAKEHEADER*/
7669 
7670 /*MAKEHEADER*/
7671 
7672 /*MAKEHEADER*/
7673 
7674 /*MAKEHEADER*/
7675 
7676 /*MAKEHEADER*/
7677 
7678 /*MAKEHEADER*/
7679 
7680 /*MAKEHEADER*/
7681 
7682 /*MAKEHEADER*/
7683 
7684 namespace svd
7685 {
7686  template<unsigned int Precision>
7688  int m,
7689  int n,
7690  int uneeded,
7691  int vtneeded,
7692  int additionalmemory,
7696  template<unsigned int Precision>
7698  int m,
7699  int n,
7700  int uneeded,
7701  int vtneeded,
7702  int additionalmemory,
7706 
7707 
7708  /*************************************************************************
7709  Singular value decomposition of a rectangular matrix.
7710 
7711  The algorithm calculates the singular value decomposition of a matrix of
7712  size MxN: A = U * S * V^T
7713 
7714  The algorithm finds the singular values and, optionally, matrices U and V^T.
7715  The algorithm can find both first min(M,N) columns of matrix U and rows of
7716  matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM
7717  and NxN respectively).
7718 
7719  Take into account that the subroutine does not return matrix V but V^T.
7720 
7721  Input parameters:
7722  A - matrix to be decomposed.
7723  Array whose indexes range within [0..M-1, 0..N-1].
7724  M - number of rows in matrix A.
7725  N - number of columns in matrix A.
7726  UNeeded - 0, 1 or 2. See the description of the parameter U.
7727  VTNeeded - 0, 1 or 2. See the description of the parameter VT.
7728  AdditionalMemory -
7729  If the parameter:
7730  memory (lower requirements, lower performance).
7731  * equals 1, the algorithm uses additional
7732  memory of size min(M,N)*min(M,N) of real numbers.
7733  It often speeds up the algorithm.
7734  * equals 2, the algorithm uses additional
7735  memory of size M*min(M,N) of real numbers.
7736  It allows to get a maximum performance.
7737  The recommended value of the parameter is 2.
7738 
7739  Output parameters:
7740  W - contains singular values in descending order.
7741  U - if UNeeded=0, U isn't changed, the left singular vectors
7742  are not calculated.
7743  if Uneeded=1, U contains left singular vectors (first
7744  min(M,N) columns of matrix U). Array whose indexes range
7745  within [0..M-1, 0..Min(M,N)-1].
7746  if UNeeded=2, U contains matrix U wholly. Array whose
7747  indexes range within [0..M-1, 0..M-1].
7748  are not calculated.
7749  if VTNeeded=1, VT contains right singular vectors (first
7750  min(M,N) rows of matrix V^T). Array whose indexes range
7751  within [0..min(M,N)-1, 0..N-1].
7752  if VTNeeded=2, VT contains matrix V^T wholly. Array whose
7753  indexes range within [0..N-1, 0..N-1].
7754 
7755  -- ALGLIB --
7756  Copyright 2005 by Bochkanov Sergey
7757  *************************************************************************/
7758  template<unsigned int Precision>
7760  int m,
7761  int n,
7762  int uneeded,
7763  int vtneeded,
7764  int additionalmemory,
7768  {
7769  bool result;
7776  bool isupper;
7777  int minmn;
7778  int ncu;
7779  int nrvt;
7780  int nru;
7781  int ncvt;
7782  int i;
7783  int j;
7784  int im1;
7786 
7787 
7788  result = true;
7789  if( m==0 || n==0 )
7790  {
7791  return result;
7792  }
7793  ap::ap_error::make_assertion(uneeded>=0 && uneeded<=2);
7794  ap::ap_error::make_assertion(vtneeded>=0 && vtneeded<=2);
7795  ap::ap_error::make_assertion(additionalmemory>=0 && additionalmemory<=2);
7796 
7797  //
7798  // initialize
7799  //
7800  minmn = ap::minint(m, n);
7801  w.setbounds(1, minmn);
7802  ncu = 0;
7803  nru = 0;
7804  if( uneeded==1 )
7805  {
7806  nru = m;
7807  ncu = minmn;
7808  u.setbounds(0, nru-1, 0, ncu-1);
7809  }
7810  if( uneeded==2 )
7811  {
7812  nru = m;
7813  ncu = m;
7814  u.setbounds(0, nru-1, 0, ncu-1);
7815  }
7816  nrvt = 0;
7817  ncvt = 0;
7818  if( vtneeded==1 )
7819  {
7820  nrvt = minmn;
7821  ncvt = n;
7822  vt.setbounds(0, nrvt-1, 0, ncvt-1);
7823  }
7824  if( vtneeded==2 )
7825  {
7826  nrvt = n;
7827  ncvt = n;
7828  vt.setbounds(0, nrvt-1, 0, ncvt-1);
7829  }
7830 
7831  //
7832  // M much larger than N
7833  // Use bidiagonal reduction with QR-decomposition
7834  //
7835  if( m>amp::ampf<Precision>("1.6")*n )
7836  {
7837  if( uneeded==0 )
7838  {
7839 
7840  //
7841  // No left singular vectors to be computed
7842  //
7843  qr::rmatrixqr<Precision>(a, m, n, tau);
7844  for(i=0; i<=n-1; i++)
7845  {
7846  for(j=0; j<=i-1; j++)
7847  {
7848  a(i,j) = 0;
7849  }
7850  }
7851  bidiagonal::rmatrixbd<Precision>(a, n, n, tauq, taup);
7852  bidiagonal::rmatrixbdunpackpt<Precision>(a, n, n, taup, nrvt, vt);
7853  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, n, n, isupper, w, e);
7854  result = bdsvd::rmatrixbdsvd<Precision>(w, e, n, isupper, false, u, 0, a, 0, vt, ncvt);
7855  return result;
7856  }
7857  else
7858  {
7859 
7860  //
7861  // Left singular vectors (may be full matrix U) to be computed
7862  //
7863  qr::rmatrixqr<Precision>(a, m, n, tau);
7864  qr::rmatrixqrunpackq<Precision>(a, m, n, tau, ncu, u);
7865  for(i=0; i<=n-1; i++)
7866  {
7867  for(j=0; j<=i-1; j++)
7868  {
7869  a(i,j) = 0;
7870  }
7871  }
7872  bidiagonal::rmatrixbd<Precision>(a, n, n, tauq, taup);
7873  bidiagonal::rmatrixbdunpackpt<Precision>(a, n, n, taup, nrvt, vt);
7874  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, n, n, isupper, w, e);
7875  if( additionalmemory<1 )
7876  {
7877 
7878  //
7879  // No additional memory can be used
7880  //
7881  bidiagonal::rmatrixbdmultiplybyq<Precision>(a, n, n, tauq, u, m, n, true, false);
7882  result = bdsvd::rmatrixbdsvd<Precision>(w, e, n, isupper, false, u, m, a, 0, vt, ncvt);
7883  }
7884  else
7885  {
7886 
7887  //
7888  // Large U. Transforming intermediate matrix T2
7889  //
7890  work.setbounds(1, ap::maxint(m, n));
7891  bidiagonal::rmatrixbdunpackq<Precision>(a, n, n, tauq, n, t2);
7892  blas::copymatrix<Precision>(u, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1);
7893  blas::inplacetranspose<Precision>(t2, 0, n-1, 0, n-1, work);
7894  result = bdsvd::rmatrixbdsvd<Precision>(w, e, n, isupper, false, u, 0, t2, n, vt, ncvt);
7895  blas::matrixmatrixmultiply<Precision>(a, 0, m-1, 0, n-1, false, t2, 0, n-1, 0, n-1, true, amp::ampf<Precision>("1.0"), u, 0, m-1, 0, n-1, amp::ampf<Precision>("0.0"), work);
7896  }
7897  return result;
7898  }
7899  }
7900 
7901  //
7902  // N much larger than M
7903  // Use bidiagonal reduction with LQ-decomposition
7904  //
7905  if( n>amp::ampf<Precision>("1.6")*m )
7906  {
7907  if( vtneeded==0 )
7908  {
7909 
7910  //
7911  // No right singular vectors to be computed
7912  //
7913  lq::rmatrixlq<Precision>(a, m, n, tau);
7914  for(i=0; i<=m-1; i++)
7915  {
7916  for(j=i+1; j<=m-1; j++)
7917  {
7918  a(i,j) = 0;
7919  }
7920  }
7921  bidiagonal::rmatrixbd<Precision>(a, m, m, tauq, taup);
7922  bidiagonal::rmatrixbdunpackq<Precision>(a, m, m, tauq, ncu, u);
7923  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, m, m, isupper, w, e);
7924  work.setbounds(1, m);
7925  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7926  result = bdsvd::rmatrixbdsvd<Precision>(w, e, m, isupper, false, a, 0, u, nru, vt, 0);
7927  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7928  return result;
7929  }
7930  else
7931  {
7932 
7933  //
7934  // Right singular vectors (may be full matrix VT) to be computed
7935  //
7936  lq::rmatrixlq<Precision>(a, m, n, tau);
7937  lq::rmatrixlqunpackq<Precision>(a, m, n, tau, nrvt, vt);
7938  for(i=0; i<=m-1; i++)
7939  {
7940  for(j=i+1; j<=m-1; j++)
7941  {
7942  a(i,j) = 0;
7943  }
7944  }
7945  bidiagonal::rmatrixbd<Precision>(a, m, m, tauq, taup);
7946  bidiagonal::rmatrixbdunpackq<Precision>(a, m, m, tauq, ncu, u);
7947  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, m, m, isupper, w, e);
7948  work.setbounds(1, ap::maxint(m, n));
7949  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7950  if( additionalmemory<1 )
7951  {
7952 
7953  //
7954  // No additional memory available
7955  //
7956  bidiagonal::rmatrixbdmultiplybyp<Precision>(a, m, m, taup, vt, m, n, false, true);
7957  result = bdsvd::rmatrixbdsvd<Precision>(w, e, m, isupper, false, a, 0, u, nru, vt, n);
7958  }
7959  else
7960  {
7961 
7962  //
7963  // Large VT. Transforming intermediate matrix T2
7964  //
7965  bidiagonal::rmatrixbdunpackpt<Precision>(a, m, m, taup, m, t2);
7966  result = bdsvd::rmatrixbdsvd<Precision>(w, e, m, isupper, false, a, 0, u, nru, t2, m);
7967  blas::copymatrix<Precision>(vt, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1);
7968  blas::matrixmatrixmultiply<Precision>(t2, 0, m-1, 0, m-1, false, a, 0, m-1, 0, n-1, false, amp::ampf<Precision>("1.0"), vt, 0, m-1, 0, n-1, amp::ampf<Precision>("0.0"), work);
7969  }
7970  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7971  return result;
7972  }
7973  }
7974 
7975  //
7976  // M<=N
7977  // We can use inplace transposition of U to get rid of columnwise operations
7978  //
7979  if( m<=n )
7980  {
7981  bidiagonal::rmatrixbd<Precision>(a, m, n, tauq, taup);
7982  bidiagonal::rmatrixbdunpackq<Precision>(a, m, n, tauq, ncu, u);
7983  bidiagonal::rmatrixbdunpackpt<Precision>(a, m, n, taup, nrvt, vt);
7984  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, m, n, isupper, w, e);
7985  work.setbounds(1, m);
7986  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7987  result = bdsvd::rmatrixbdsvd<Precision>(w, e, minmn, isupper, false, a, 0, u, nru, vt, ncvt);
7988  blas::inplacetranspose<Precision>(u, 0, nru-1, 0, ncu-1, work);
7989  return result;
7990  }
7991 
7992  //
7993  // Simple bidiagonal reduction
7994  //
7995  bidiagonal::rmatrixbd<Precision>(a, m, n, tauq, taup);
7996  bidiagonal::rmatrixbdunpackq<Precision>(a, m, n, tauq, ncu, u);
7997  bidiagonal::rmatrixbdunpackpt<Precision>(a, m, n, taup, nrvt, vt);
7998  bidiagonal::rmatrixbdunpackdiagonals<Precision>(a, m, n, isupper, w, e);
7999  if( additionalmemory<2 || uneeded==0 )
8000  {
8001 
8002  //
8003  // We cant use additional memory or there is no need in such operations
8004  //
8005  result = bdsvd::rmatrixbdsvd<Precision>(w, e, minmn, isupper, false, u, nru, a, 0, vt, ncvt);
8006  }
8007  else
8008  {
8009 
8010  //
8011  // We can use additional memory
8012  //
8013  t2.setbounds(0, minmn-1, 0, m-1);
8014  blas::copyandtranspose<Precision>(u, 0, m-1, 0, minmn-1, t2, 0, minmn-1, 0, m-1);
8015  result = bdsvd::rmatrixbdsvd<Precision>(w, e, minmn, isupper, false, u, 0, t2, m, vt, ncvt);
8016  blas::copyandtranspose<Precision>(t2, 0, minmn-1, 0, m-1, u, 0, m-1, 0, minmn-1);
8017  }
8018  return result;
8019  }
8020 
8021 
8022  /*************************************************************************
8023  Obsolete 1-based subroutine.
8024  See RMatrixSVD for 0-based replacement.
8025  *************************************************************************/
8026  template<unsigned int Precision>
8028  int m,
8029  int n,
8030  int uneeded,
8031  int vtneeded,
8032  int additionalmemory,
8036  {
8037  bool result;
8044  bool isupper;
8045  int minmn;
8046  int ncu;
8047  int nrvt;
8048  int nru;
8049  int ncvt;
8050  int i;
8051  int j;
8052  int im1;
8054 
8055 
8056  result = true;
8057  if( m==0 || n==0 )
8058  {
8059  return result;
8060  }
8061  ap::ap_error::make_assertion(uneeded>=0 && uneeded<=2);
8062  ap::ap_error::make_assertion(vtneeded>=0 && vtneeded<=2);
8063  ap::ap_error::make_assertion(additionalmemory>=0 && additionalmemory<=2);
8064 
8065  //
8066  // initialize
8067  //
8068  minmn = ap::minint(m, n);
8069  w.setbounds(1, minmn);
8070  ncu = 0;
8071  nru = 0;
8072  if( uneeded==1 )
8073  {
8074  nru = m;
8075  ncu = minmn;
8076  u.setbounds(1, nru, 1, ncu);
8077  }
8078  if( uneeded==2 )
8079  {
8080  nru = m;
8081  ncu = m;
8082  u.setbounds(1, nru, 1, ncu);
8083  }
8084  nrvt = 0;
8085  ncvt = 0;
8086  if( vtneeded==1 )
8087  {
8088  nrvt = minmn;
8089  ncvt = n;
8090  vt.setbounds(1, nrvt, 1, ncvt);
8091  }
8092  if( vtneeded==2 )
8093  {
8094  nrvt = n;
8095  ncvt = n;
8096  vt.setbounds(1, nrvt, 1, ncvt);
8097  }
8098 
8099  //
8100  // M much larger than N
8101  // Use bidiagonal reduction with QR-decomposition
8102  //
8103  if( m>amp::ampf<Precision>("1.6")*n )
8104  {
8105  if( uneeded==0 )
8106  {
8107 
8108  //
8109  // No left singular vectors to be computed
8110  //
8111  qr::qrdecomposition<Precision>(a, m, n, tau);
8112  for(i=2; i<=n; i++)
8113  {
8114  for(j=1; j<=i-1; j++)
8115  {
8116  a(i,j) = 0;
8117  }
8118  }
8119  bidiagonal::tobidiagonal<Precision>(a, n, n, tauq, taup);
8120  bidiagonal::unpackptfrombidiagonal<Precision>(a, n, n, taup, nrvt, vt);
8121  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, n, n, isupper, w, e);
8122  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, n, isupper, false, u, 0, a, 0, vt, ncvt);
8123  return result;
8124  }
8125  else
8126  {
8127 
8128  //
8129  // Left singular vectors (may be full matrix U) to be computed
8130  //
8131  qr::qrdecomposition<Precision>(a, m, n, tau);
8132  qr::unpackqfromqr<Precision>(a, m, n, tau, ncu, u);
8133  for(i=2; i<=n; i++)
8134  {
8135  for(j=1; j<=i-1; j++)
8136  {
8137  a(i,j) = 0;
8138  }
8139  }
8140  bidiagonal::tobidiagonal<Precision>(a, n, n, tauq, taup);
8141  bidiagonal::unpackptfrombidiagonal<Precision>(a, n, n, taup, nrvt, vt);
8142  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, n, n, isupper, w, e);
8143  if( additionalmemory<1 )
8144  {
8145 
8146  //
8147  // No additional memory can be used
8148  //
8149  bidiagonal::multiplybyqfrombidiagonal<Precision>(a, n, n, tauq, u, m, n, true, false);
8150  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, n, isupper, false, u, m, a, 0, vt, ncvt);
8151  }
8152  else
8153  {
8154 
8155  //
8156  // Large U. Transforming intermediate matrix T2
8157  //
8158  work.setbounds(1, ap::maxint(m, n));
8159  bidiagonal::unpackqfrombidiagonal<Precision>(a, n, n, tauq, n, t2);
8160  blas::copymatrix<Precision>(u, 1, m, 1, n, a, 1, m, 1, n);
8161  blas::inplacetranspose<Precision>(t2, 1, n, 1, n, work);
8162  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, n, isupper, false, u, 0, t2, n, vt, ncvt);
8163  blas::matrixmatrixmultiply<Precision>(a, 1, m, 1, n, false, t2, 1, n, 1, n, true, amp::ampf<Precision>("1.0"), u, 1, m, 1, n, amp::ampf<Precision>("0.0"), work);
8164  }
8165  return result;
8166  }
8167  }
8168 
8169  //
8170  // N much larger than M
8171  // Use bidiagonal reduction with LQ-decomposition
8172  //
8173  if( n>amp::ampf<Precision>("1.6")*m )
8174  {
8175  if( vtneeded==0 )
8176  {
8177 
8178  //
8179  // No right singular vectors to be computed
8180  //
8181  lq::lqdecomposition<Precision>(a, m, n, tau);
8182  for(i=1; i<=m-1; i++)
8183  {
8184  for(j=i+1; j<=m; j++)
8185  {
8186  a(i,j) = 0;
8187  }
8188  }
8189  bidiagonal::tobidiagonal<Precision>(a, m, m, tauq, taup);
8190  bidiagonal::unpackqfrombidiagonal<Precision>(a, m, m, tauq, ncu, u);
8191  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, m, m, isupper, w, e);
8192  work.setbounds(1, m);
8193  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8194  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, m, isupper, false, a, 0, u, nru, vt, 0);
8195  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8196  return result;
8197  }
8198  else
8199  {
8200 
8201  //
8202  // Right singular vectors (may be full matrix VT) to be computed
8203  //
8204  lq::lqdecomposition<Precision>(a, m, n, tau);
8205  lq::unpackqfromlq<Precision>(a, m, n, tau, nrvt, vt);
8206  for(i=1; i<=m-1; i++)
8207  {
8208  for(j=i+1; j<=m; j++)
8209  {
8210  a(i,j) = 0;
8211  }
8212  }
8213  bidiagonal::tobidiagonal<Precision>(a, m, m, tauq, taup);
8214  bidiagonal::unpackqfrombidiagonal<Precision>(a, m, m, tauq, ncu, u);
8215  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, m, m, isupper, w, e);
8216  work.setbounds(1, ap::maxint(m, n));
8217  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8218  if( additionalmemory<1 )
8219  {
8220 
8221  //
8222  // No additional memory available
8223  //
8224  bidiagonal::multiplybypfrombidiagonal<Precision>(a, m, m, taup, vt, m, n, false, true);
8225  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, m, isupper, false, a, 0, u, nru, vt, n);
8226  }
8227  else
8228  {
8229 
8230  //
8231  // Large VT. Transforming intermediate matrix T2
8232  //
8233  bidiagonal::unpackptfrombidiagonal<Precision>(a, m, m, taup, m, t2);
8234  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, m, isupper, false, a, 0, u, nru, t2, m);
8235  blas::copymatrix<Precision>(vt, 1, m, 1, n, a, 1, m, 1, n);
8236  blas::matrixmatrixmultiply<Precision>(t2, 1, m, 1, m, false, a, 1, m, 1, n, false, amp::ampf<Precision>("1.0"), vt, 1, m, 1, n, amp::ampf<Precision>("0.0"), work);
8237  }
8238  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8239  return result;
8240  }
8241  }
8242 
8243  //
8244  // M<=N
8245  // We can use inplace transposition of U to get rid of columnwise operations
8246  //
8247  if( m<=n )
8248  {
8249  bidiagonal::tobidiagonal<Precision>(a, m, n, tauq, taup);
8250  bidiagonal::unpackqfrombidiagonal<Precision>(a, m, n, tauq, ncu, u);
8251  bidiagonal::unpackptfrombidiagonal<Precision>(a, m, n, taup, nrvt, vt);
8252  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, m, n, isupper, w, e);
8253  work.setbounds(1, m);
8254  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8255  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, minmn, isupper, false, a, 0, u, nru, vt, ncvt);
8256  blas::inplacetranspose<Precision>(u, 1, nru, 1, ncu, work);
8257  return result;
8258  }
8259 
8260  //
8261  // Simple bidiagonal reduction
8262  //
8263  bidiagonal::tobidiagonal<Precision>(a, m, n, tauq, taup);
8264  bidiagonal::unpackqfrombidiagonal<Precision>(a, m, n, tauq, ncu, u);
8265  bidiagonal::unpackptfrombidiagonal<Precision>(a, m, n, taup, nrvt, vt);
8266  bidiagonal::unpackdiagonalsfrombidiagonal<Precision>(a, m, n, isupper, w, e);
8267  if( additionalmemory<2 || uneeded==0 )
8268  {
8269 
8270  //
8271  // We cant use additional memory or there is no need in such operations
8272  //
8273  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, minmn, isupper, false, u, nru, a, 0, vt, ncvt);
8274  }
8275  else
8276  {
8277 
8278  //
8279  // We can use additional memory
8280  //
8281  t2.setbounds(1, minmn, 1, m);
8282  blas::copyandtranspose<Precision>(u, 1, m, 1, minmn, t2, 1, minmn, 1, m);
8283  result = bdsvd::bidiagonalsvddecomposition<Precision>(w, e, minmn, isupper, false, u, 0, t2, m, vt, ncvt);
8284  blas::copyandtranspose<Precision>(t2, 1, minmn, 1, m, u, 1, m, 1, minmn);
8285  }
8286  return result;
8287  }
8288 } // namespace
8289 
8290 #endif
8291 #endif
8292 
const ampf< Precision > halfpi()
Definition: amp.h:932
void rmatrixlqunpackq(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tau, int qrows, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: lq.h:177
ampf(unsigned short v)
Definition: svd_si.h:1122
campf(const campf &z)
Definition: svd_si.h:2112
ampf(signed char v)
Definition: svd_si.h:1123
const CanonicalForm int s
Definition: facAbsFact.cc:55
complex & operator+=(const double &v)
Definition: svd_si.h:76
const CanonicalForm int const CFList const Variable & y
Definition: facAbsFact.cc:57
void rmatrixqr(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tau)
Definition: qr.h:123
void setcontent(int iLow1, int iHigh1, int iLow2, int iHigh2, const T *pContent)
Definition: svd_si.h:912
int j
Definition: facHensel.cc:105
static const ampf getAlgoPascalMinNumber()
Definition: amp.h:582
void mu(int **points, int sizePoints)
complex()
Definition: svd_si.h:70
int getlowbound(int iBoundNum) const
Definition: svd_si.h:929
void rmatrixbdmultiplybyp(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &taup, ap::template_2d_array< amp::ampf< Precision > > &z, int zrows, int zcolumns, bool fromtheright, bool dotranspose)
Definition: bidiagonal.h:649
void tobidiagonal(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tauq, ap::template_1d_array< amp::ampf< Precision > > &taup)
Definition: bidiagonal.h:850
template_1d_array(const template_1d_array &rhs)
Definition: svd_si.h:679
void copyandtranspose(const ap::template_2d_array< amp::ampf< Precision > > &a, int is1, int is2, int js1, int js2, ap::template_2d_array< amp::ampf< Precision > > &b, int id1, int id2, int jd1, int jd2)
Definition: blas.h:351
campf(unsigned long v)
Definition: svd_si.h:2103
gmp_float exp(const gmp_float &a)
Definition: mpr_complex.cc:357
bool svddecomposition(ap::template_2d_array< amp::ampf< Precision > > a, int m, int n, int uneeded, int vtneeded, int additionalmemory, ap::template_1d_array< amp::ampf< Precision > > &w, ap::template_2d_array< amp::ampf< Precision > > &u, ap::template_2d_array< amp::ampf< Precision > > &vt)
Definition: svd.h:408
void vmoveneg(raw_vector< T > vdst, const_raw_vector< T > vsrc)
Definition: ap.h:295
double maxreal(double m1, double m2)
Definition: ap.cpp:172
void matrixmatrixmultiply(const ap::template_2d_array< amp::ampf< Precision > > &a, int ai1, int ai2, int aj1, int aj2, bool transa, const ap::template_2d_array< amp::ampf< Precision > > &b, int bi1, int bi2, int bj1, int bj2, bool transb, amp::ampf< Precision > alpha, ap::template_2d_array< amp::ampf< Precision > > &c, int ci1, int ci2, int cj1, int cj2, amp::ampf< Precision > beta, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: blas.h:505
void vsub(raw_vector< T > vdst, const_raw_vector< T > vsrc)
Definition: ap.h:533
ampf(signed int v)
Definition: svd_si.h:1119
ampf(const ampf &r)
Definition: svd_si.h:1136
void unpackqfromqr(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tau, int qcolumns, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: qr.h:354
template_2d_array< int > integer_2d_array
Definition: ap.h:977
ampf & operator*=(const T &v)
Definition: svd_si.h:1199
complex & operator*=(const complex &z)
Definition: svd_si.h:84
static const ampf getAlgoPascalEpsilon()
Definition: amp.h:565
ampf(signed long v)
Definition: svd_si.h:1117
ampf(long double v)
Definition: svd_si.h:1114
const ampf< Precision > log2(const ampf< Precision > &x)
Definition: amp.h:1014
void multiplybyqfrombidiagonal(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tauq, ap::template_2d_array< amp::ampf< Precision > > &z, int zrows, int zcolumns, bool fromtheright, bool dotranspose)
Definition: bidiagonal.h:1055
template_1d_array< complex > complex_1d_array
Definition: ap.h:975
const complex operator/(const complex &lhs, const complex &rhs)
Definition: ap.cpp:50
const ampf< Precision > acos(const ampf< Precision > &x)
Definition: amp.h:982
void generatereflection(ap::template_1d_array< amp::ampf< Precision > > &x, int n, amp::ampf< Precision > &tau)
Definition: reflections.h:112
Definition: ap.h:39
double sqr(double x)
Definition: ap.cpp:159
const complex operator-(const complex &lhs)
Definition: ap.cpp:20
void vAdd(ap::raw_vector< ampf< Precision > > vDst, ap::const_raw_vector< ampf< Precision > > vSrc)
Definition: amp.h:1379
campf(const ampf< Precision > &_x)
Definition: svd_si.h:2110
signed long signed32
Definition: amp.h:31
int GetLength() const
Definition: svd_si.h:153
ampf(mpfr_record *v)
Definition: svd_si.h:1112
ampf(const char *s)
Definition: svd_si.h:1131
#define string
Definition: libparse.cc:1250
double randomreal()
Definition: ap.cpp:133
ampf & operator/=(const T &v)
Definition: svd_si.h:1200
void setbounds(int iLow1, int iHigh1, int iLow2, int iHigh2)
Definition: svd_si.h:898
complex & operator+=(const complex &z)
Definition: svd_si.h:82
CFFListIterator iter
Definition: facAbsBiFact.cc:54
const bool operator==(const complex &lhs, const complex &rhs)
Definition: ap.cpp:11
Definition: bdsvd.h:45
campf(const ampf< Precision > &_x, const ampf< Precision > &_y)
Definition: svd_si.h:2111
gmp_float log(const gmp_float &a)
Definition: mpr_complex.cc:343
const ampf< Precision > atan2(const ampf< Precision > &y, const ampf< Precision > &x)
Definition: amp.h:998
const ampf< Precision > minimum(const ampf< Precision > &x, const ampf< Precision > &y)
Definition: amp.h:731
campf(signed int v)
Definition: svd_si.h:2104
const template_1d_array & operator=(const template_1d_array &rhs)
Definition: svd_si.h:699
g
Definition: cfModGcd.cc:4031
void WerrorS(const char *s)
Definition: feFopen.cc:24
int k
Definition: cfEzgcd.cc:92
Variable alpha
Definition: facAbsBiFact.cc:52
const double machineepsilon
Definition: svd_si.h:994
int round(double x)
Definition: ap.cpp:144
template_1d_array< double > real_1d_array
Definition: ap.h:974
int rowidxabsmax(const ap::template_2d_array< amp::ampf< Precision > > &x, int j1, int j2, int i)
Definition: blas.h:230
void rmatrixbd(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tauq, ap::template_1d_array< amp::ampf< Precision > > &taup)
Definition: bidiagonal.h:194
static void make_assertion(bool bClause)
Definition: svd_si.h:57
campf< Precision > & operator/=(campf< Precision > &lhs, const campf< Precision > &rhs)
Definition: amp.h:1200
template_1d_array< int > integer_1d_array
Definition: ap.h:973
void copymatrix(const ap::template_2d_array< amp::ampf< Precision > > &a, int is1, int is2, int js1, int js2, ap::template_2d_array< amp::ampf< Precision > > &b, int id1, int id2, int jd1, int jd2)
Definition: blas.h:288
int randominteger(int maxv)
Definition: ap.cpp:141
#define omAlloc(size)
Definition: omAllocDecl.h:210
int iceil(double x)
Definition: ap.cpp:153
ampf & operator+=(const T &v)
Definition: svd_si.h:1197
const T * getcontent() const
Definition: svd_si.h:767
mpfr_record * mpfr_record_ptr
Definition: amp.h:41
Rational abs(const Rational &a)
Definition: GMPrat.cc:436
lists getList(spectrum &spec)
Definition: ipshell.cc:3370
void unpackptfrombidiagonal(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &taup, int ptrows, ap::template_2d_array< amp::ampf< Precision > > &pt)
Definition: bidiagonal.h:1196
void unpackdiagonalsfrombidiagonal(const ap::template_2d_array< amp::ampf< Precision > > &b, int m, int n, bool &isupper, ap::template_1d_array< amp::ampf< Precision > > &d, ap::template_1d_array< amp::ampf< Precision > > &e)
Definition: bidiagonal.h:1413
ampf(signed short v)
Definition: svd_si.h:1121
template_1d_array< bool > boolean_1d_array
Definition: ap.h:976
const ampf< Precision > sinh(const ampf< Precision > &x)
Definition: amp.h:1038
T * GetData()
Definition: svd_si.h:180
int gethighbound(int iBoundNum=0) const
Definition: svd_si.h:779
CanonicalForm b
Definition: cfModGcd.cc:4044
void initialize()
int columnidxabsmax(const ap::template_2d_array< amp::ampf< Precision > > &x, int i1, int i2, int j)
Definition: blas.h:206
bool bidiagonalsvddecompositioninternal(ap::template_1d_array< amp::ampf< Precision > > &d, ap::template_1d_array< amp::ampf< Precision > > e, int n, bool isupper, bool isfractionalaccuracyrequired, ap::template_2d_array< amp::ampf< Precision > > &u, int ustart, int nru, ap::template_2d_array< amp::ampf< Precision > > &c, int cstart, int ncc, ap::template_2d_array< amp::ampf< Precision > > &vt, int vstart, int ncvt)
Definition: bdsvd.h:253
complex(const double &_x)
Definition: svd_si.h:71
campf(long double v)
Definition: svd_si.h:2099
campf(signed long v)
Definition: svd_si.h:2102
bool bidiagonalsvddecomposition(ap::template_1d_array< amp::ampf< Precision > > &d, ap::template_1d_array< amp::ampf< Precision > > e, int n, bool isupper, bool isfractionalaccuracyrequired, ap::template_2d_array< amp::ampf< Precision > > &u, int nru, ap::template_2d_array< amp::ampf< Precision > > &c, int ncc, ap::template_2d_array< amp::ampf< Precision > > &vt, int ncvt)
Definition: bdsvd.h:229
const complex operator*(const complex &lhs, const complex &rhs)
Definition: ap.cpp:41
template_2d_array< double > real_2d_array
Definition: ap.h:978
ampf(float v)
Definition: svd_si.h:1116
bool operator>=(const ampf< Precision > &op1, const ampf< Precision > &op2)
Definition: svd_si.h:1647
CanonicalForm res
Definition: facAbsFact.cc:64
int vectoridxabsmax(const ap::template_1d_array< amp::ampf< Precision > > &x, int i1, int i2)
Definition: blas.h:183
amp::ampf< Precision > extsignbdsqr(amp::ampf< Precision > a, amp::ampf< Precision > b)
Definition: bdsvd.h:1096
campf(float v)
Definition: svd_si.h:2101
ampf(unsigned int v)
Definition: svd_si.h:1120
void generaterotation(amp::ampf< Precision > f, amp::ampf< Precision > g, amp::ampf< Precision > &cs, amp::ampf< Precision > &sn, amp::ampf< Precision > &r)
Definition: rotations.h:355
BOOLEAN fa(leftv res, leftv args)
Definition: cohomo.cc:4392
void vMul(ap::raw_vector< ampf< Precision > > vDst, T2 alpha)
Definition: amp.h:1438
campf(unsigned char v)
Definition: svd_si.h:2109
template_2d_array< bool > boolean_2d_array
Definition: ap.h:980
const T * getcontent() const
Definition: svd_si.h:924
template_2d_array(const template_2d_array &rhs)
Definition: svd_si.h:829
bool wrongIdx(int i) const
Definition: svd_si.h:801
const T & operator()(int i1, int i2) const
Definition: svd_si.h:880
const T * GetData() const
Definition: svd_si.h:150
Definition: svd.h:63
void vmul(raw_vector< T > vdst, T2 alpha)
Definition: ap.h:603
ampf< Precision > y
Definition: amp.h:1125
campf(double v)
Definition: svd_si.h:2100
campf(signed char v)
Definition: svd_si.h:2108
void vadd(raw_vector< T > vdst, const_raw_vector< T > vsrc)
Definition: ap.h:413
double x
Definition: ap.h:98
#define __AMP_BINARY_OPF(type)
gmp_float sqrt(const gmp_float &a)
Definition: mpr_complex.cc:327
ampf(double v)
Definition: svd_si.h:1115
void qrdecompositionunpacked(ap::template_2d_array< amp::ampf< Precision > > a, int m, int n, ap::template_2d_array< amp::ampf< Precision > > &q, ap::template_2d_array< amp::ampf< Precision > > &r)
Definition: qr.h:420
const template_2d_array & operator=(const template_2d_array &rhs)
Definition: svd_si.h:851
campf< Precision > & operator+=(campf< Precision > &lhs, const campf< Precision > &rhs)
Definition: amp.h:1144
void T2(ideal h)
Definition: cohomo.cc:3097
int m
Definition: cfEzgcd.cc:121
bool rmatrixsvd(ap::template_2d_array< amp::ampf< Precision > > a, int m, int n, int uneeded, int vtneeded, int additionalmemory, ap::template_1d_array< amp::ampf< Precision > > &w, ap::template_2d_array< amp::ampf< Precision > > &u, ap::template_2d_array< amp::ampf< Precision > > &vt)
Definition: svd.h:140
raw_vector< T > getrow(int iRow, int iColumnStart, int iColumnEnd)
Definition: svd_si.h:947
int sign(double x)
Definition: ap.cpp:126
#define free
Definition: omAllocFunc.c:14
void tau(int **points, int sizePoints, int k)
raw_vector< T > getcolumn(int iColumn, int iRowStart, int iRowEnd)
Definition: svd_si.h:939
FILE * f
Definition: checklibs.c:9
void vMoveNeg(ap::raw_vector< ampf< Precision > > vDst, ap::const_raw_vector< ampf< Precision > > vSrc)
Definition: amp.h:1344
int i
Definition: cfEzgcd.cc:125
void vSub(ap::raw_vector< ampf< Precision > > vDst, ap::const_raw_vector< ampf< Precision > > vSrc)
Definition: amp.h:1415
int minint(int m1, int m2)
Definition: ap.cpp:167
double minreal(double m1, double m2)
Definition: ap.cpp:177
bool wrongRow(int i) const
Definition: svd_si.h:971
Definition: qr.h:45
void rmatrixlq(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tau)
Definition: lq.h:113
campf< Precision > & operator-=(campf< Precision > &lhs, const campf< Precision > &rhs)
Definition: amp.h:1156
void rmatrixbdmultiplybyq(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tauq, ap::template_2d_array< amp::ampf< Precision > > &z, int zrows, int zcolumns, bool fromtheright, bool dotranspose)
Definition: bidiagonal.h:422
ampf(const ampf< Precision2 > &r)
Definition: svd_si.h:1143
void lqdecompositionunpacked(ap::template_2d_array< amp::ampf< Precision > > a, int m, int n, ap::template_2d_array< amp::ampf< Precision > > &l, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: lq.h:408
campf(const campf< Prec2 > &z)
Definition: svd_si.h:2115
T & operator()(int i)
Definition: svd_si.h:734
ampf(const std::string &s)
Definition: svd_si.h:1130
gmp_float cos(const gmp_float &a)
Definition: mpr_complex.cc:338
const double minrealnumber
Definition: svd_si.h:996
const_raw_vector< T > getvector(int iStart, int iEnd) const
Definition: svd_si.h:793
int maxint(int m1, int m2)
Definition: ap.cpp:162
void setbounds(int iLow, int iHigh)
Definition: svd_si.h:743
int trunc(double x)
Definition: ap.cpp:147
campf< Precision > & operator*=(campf< Precision > &lhs, const campf< Precision > &rhs)
Definition: amp.h:1164
const ampf< Precision > ldexp2(const ampf< Precision > &x, mp_exp_t exponent)
Definition: amp.h:837
T vdotproduct(const_raw_vector< T > v1, const_raw_vector< T > v2)
Definition: ap.h:181
const ampf< Precision > tan(const ampf< Precision > &x)
Definition: amp.h:966
raw_vector(T *Data, int Length, int Step)
Definition: svd_si.h:178
Variable beta
Definition: facAbsFact.cc:99
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:37
template_2d_array< complex > complex_2d_array
Definition: ap.h:979
void rmatrixqrunpackq(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tau, int qcolumns, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: qr.h:193
complex & operator/=(const complex &z)
Definition: svd_si.h:85
complex & operator-=(const complex &z)
Definition: svd_si.h:83
campf(unsigned int v)
Definition: svd_si.h:2105
void svdv2x2(amp::ampf< Precision > f, amp::ampf< Precision > g, amp::ampf< Precision > h, amp::ampf< Precision > &ssmin, amp::ampf< Precision > &ssmax, amp::ampf< Precision > &snr, amp::ampf< Precision > &csr, amp::ampf< Precision > &snl, amp::ampf< Precision > &csl)
Definition: bdsvd.h:1189
const ampf< Precision > twopi()
Definition: amp.h:941
Definition: amp.h:18
void rmatrixbdunpackpt(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &taup, int ptrows, ap::template_2d_array< amp::ampf< Precision > > &pt)
Definition: bidiagonal.h:575
#define NULL
Definition: omList.c:12
complex(const double &_x, const double &_y)
Definition: svd_si.h:72
void applyreflectionfromtheright(ap::template_2d_array< amp::ampf< Precision > > &c, amp::ampf< Precision > tau, const ap::template_1d_array< amp::ampf< Precision > > &v, int m1, int m2, int n1, int n2, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: reflections.h:280
const ampf< Precision > frac(const ampf< Precision > &x)
Definition: amp.h:764
ampf & operator-=(const T &v)
Definition: svd_si.h:1198
void rmatrixbdunpackq(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tauq, int qcolumns, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: bidiagonal.h:348
const complex csqr(const complex &z)
Definition: ap.cpp:120
campf(unsigned short v)
Definition: svd_si.h:2107
void applyrotationsfromtheleft(bool isforward, int m1, int m2, int n1, int n2, const ap::template_1d_array< amp::ampf< Precision > > &c, const ap::template_1d_array< amp::ampf< Precision > > &s, ap::template_2d_array< amp::ampf< Precision > > &a, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: rotations.h:100
const_raw_vector< T > getrow(int iRow, int iColumnStart, int iColumnEnd) const
Definition: svd_si.h:963
bool wrongColumn(int j) const
Definition: svd_si.h:972
void svd2x2(amp::ampf< Precision > f, amp::ampf< Precision > g, amp::ampf< Precision > h, amp::ampf< Precision > &ssmin, amp::ampf< Precision > &ssmax)
Definition: bdsvd.h:1115
int ifloor(double x)
Definition: ap.cpp:150
void applyrotationsfromtheright(bool isforward, int m1, int m2, int n1, int n2, const ap::template_1d_array< amp::ampf< Precision > > &c, const ap::template_1d_array< amp::ampf< Precision > > &s, ap::template_2d_array< amp::ampf< Precision > > &a, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: rotations.h:238
const T & operator()(int i) const
Definition: svd_si.h:725
long m_iLinearMember
Definition: ap.h:969
ampf(unsigned char v)
Definition: svd_si.h:1124
int gethighbound(int iBoundNum) const
Definition: svd_si.h:934
const ampf< Precision > asin(const ampf< Precision > &x)
Definition: amp.h:974
const ampf< Precision > tanh(const ampf< Precision > &x)
Definition: amp.h:1054
const CanonicalForm & w
Definition: facAbsFact.cc:55
raw_vector< T > getvector(int iStart, int iEnd)
Definition: svd_si.h:784
const double maxrealnumber
Definition: svd_si.h:995
int GetStep() const
Definition: svd_si.h:156
void rmatrixqrunpackr(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_2d_array< amp::ampf< Precision > > &r)
Definition: qr.h:269
void lqdecomposition(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tau)
Definition: lq.h:288
Variable x
Definition: cfModGcd.cc:4023
signed long floor(const ampf< Precision > &x)
Definition: svd_si.h:1788
unsigned long unsigned32
Definition: amp.h:30
bool isZero(const CFArray &A)
checks if entries of A are zero
void applyreflectionfromtheleft(ap::template_2d_array< amp::ampf< Precision > > &c, amp::ampf< Precision > tau, const ap::template_1d_array< amp::ampf< Precision > > &v, int m1, int m2, int n1, int n2, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: reflections.h:207
complex & operator/=(const double &v)
Definition: svd_si.h:79
campf(signed short v)
Definition: svd_si.h:2106
complex & operator-=(const double &v)
Definition: svd_si.h:77
Definition: blas.h:38
bool operator>(const ampf< Precision > &op1, const ampf< Precision > &op2)
Definition: svd_si.h:1635
double pi()
Definition: ap.cpp:156
void inplacetranspose(ap::template_2d_array< amp::ampf< Precision > > &a, int i1, int i2, int j1, int j2, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: blas.h:318
Definition: lq.h:39
#define __AMP_BINARY_OPI(type)
Definition: svd_si.h:2262
bool rmatrixbdsvd(ap::template_1d_array< amp::ampf< Precision > > &d, ap::template_1d_array< amp::ampf< Precision > > e, int n, bool isupper, bool isfractionalaccuracyrequired, ap::template_2d_array< amp::ampf< Precision > > &u, int nru, ap::template_2d_array< amp::ampf< Precision > > &c, int ncc, ap::template_2d_array< amp::ampf< Precision > > &vt, int ncvt)
Definition: bdsvd.h:186
void vMove(ap::raw_vector< ampf< Precision > > vDst, ap::const_raw_vector< ampf< Precision > > vSrc)
Definition: amp.h:1327
const double abscomplex(const complex &z)
Definition: ap.cpp:97
std::string toString(const gfan::ZCone *const c)
Definition: bbcone.cc:27
int exponent(const CanonicalForm &f, int q)
int exponent ( const CanonicalForm & f, int q )
complex(const complex &z)
Definition: svd_si.h:73
static gmp_randstate_t * getRandState()
Definition: amp.cpp:37
const ampf< Precision > frexp2(const ampf< Precision > &x, mp_exp_t *exponent)
Definition: amp.h:818
const ampf< Precision > maximum(const ampf< Precision > &x, const ampf< Precision > &y)
Definition: amp.h:722
const_raw_vector(const T *Data, int Length, int Step)
Definition: svd_si.h:147
complex & operator*=(const double &v)
Definition: svd_si.h:78
void rmatrixbdunpackdiagonals(const ap::template_2d_array< amp::ampf< Precision > > &b, int m, int n, bool &isupper, ap::template_1d_array< amp::ampf< Precision > > &d, ap::template_1d_array< amp::ampf< Precision > > &e)
Definition: bidiagonal.h:805
Definition: amp.h:81
amp::ampf< Precision > upperhessenberg1norm(const ap::template_2d_array< amp::ampf< Precision > > &a, int i1, int i2, int j1, int j2, ap::template_1d_array< amp::ampf< Precision > > &work)
Definition: blas.h:254
static jList * T
Definition: janet.cc:30
void qrdecomposition(ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_1d_array< amp::ampf< Precision > > &tau)
Definition: qr.h:303
void setcontent(int iLow, int iHigh, const T *pContent)
Definition: svd_si.h:754
const complex operator+(const complex &lhs)
Definition: ap.cpp:17
void multiplybypfrombidiagonal(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &taup, ap::template_2d_array< amp::ampf< Precision > > &z, int zrows, int zcolumns, bool fromtheright, bool dotranspose)
Definition: bidiagonal.h:1270
Definition: ap.h:59
void rmatrixlqunpackl(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, ap::template_2d_array< amp::ampf< Precision > > &l)
Definition: lq.h:253
Rational pow(const Rational &a, int e)
Definition: GMPrat.cc:411
static Poly * h
Definition: janet.cc:971
const_raw_vector< T > getcolumn(int iColumn, int iRowStart, int iRowEnd) const
Definition: svd_si.h:955
void matrixvectormultiply(const ap::template_2d_array< amp::ampf< Precision > > &a, int i1, int i2, int j1, int j2, bool trans, const ap::template_1d_array< amp::ampf< Precision > > &x, int ix1, int ix2, amp::ampf< Precision > alpha, ap::template_1d_array< amp::ampf< Precision > > &y, int iy1, int iy2, amp::ampf< Precision > beta)
Definition: blas.h:381
gmp_float sin(const gmp_float &a)
Definition: mpr_complex.cc:333
double y
Definition: ap.h:98
const ampf< Precision > log10(const ampf< Precision > &x)
Definition: amp.h:1022
T & operator()(int i1, int i2)
Definition: svd_si.h:889
const ampf< Precision > atan(const ampf< Precision > &x)
Definition: amp.h:990
long m_iConstOffset
Definition: ap.h:969
const bool operator!=(const complex &lhs, const complex &rhs)
Definition: ap.cpp:14
int l
Definition: cfEzgcd.cc:93
return result
Definition: facAbsBiFact.cc:76
amp::ampf< Precision > vectornorm2(const ap::template_1d_array< amp::ampf< Precision > > &x, int i1, int i2)
Definition: blas.h:136
ampf(unsigned long v)
Definition: svd_si.h:1118
ampf< Precision > x
Definition: amp.h:1125
signed long ceil(const ampf< Precision > &x)
Definition: svd_si.h:1805
const complex conj(const complex &z)
Definition: ap.cpp:117
void vmove(raw_vector< T > vdst, const_raw_vector< T > vsrc)
Definition: ap.h:237
void unpackqfromlq(const ap::template_2d_array< amp::ampf< Precision > > &a, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tau, int qrows, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: lq.h:342
amp::ampf< Precision > pythag2(amp::ampf< Precision > x, amp::ampf< Precision > y)
Definition: blas.h:478
const ampf< Precision > cosh(const ampf< Precision > &x)
Definition: amp.h:1046
void unpackqfrombidiagonal(const ap::template_2d_array< amp::ampf< Precision > > &qp, int m, int n, const ap::template_1d_array< amp::ampf< Precision > > &tauq, int qcolumns, ap::template_2d_array< amp::ampf< Precision > > &q)
Definition: bidiagonal.h:981
ListNode * next
Definition: janet.h:31
int getlowbound(int iBoundNum=0) const
Definition: svd_si.h:773