ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gaussher.cpp
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Author: David Fournier
5  * Copyright (c) 2009-2012 ADMB Foundation
6  */
14 #include <fvar.hpp>
15 //static double eps=3.0e-14;
16 //static double pim=0.7511255444649427;
17 //static int maxit=50;
18 
19 void imtqlx ( const dvector& _d, const dvector& _e, const dvector& _z );
20 
25 double sign(const double x)
26 {
27  return x < 0.0 ? -1.0 : 1.0;
28 }
29 
36 void gauss_hermite (const dvector& _t,const dvector& _wts)
37 //
38 // Purpose:
39 //
40 // computes a Gauss quadrature formula with simple knots.
41 //
42 // Discussion:
43 //
44 // This routine computes all the knots and weights of a Gauss quadrature
45 // formula with a classical weight function with default values for A and B,
46 // and only simple knots.
47 //
48 // There are no moments checks and no printing is done.
49 //
50 // Use routine EIQFS to evaluate a quadrature computed by CGQFS.
51 //
52 // Licensing:
53 //
54 // This code is distributed under the GNU LGPL license.
55 //
56 // Modified:
57 //
58 // September 2010 by Derek Seiple
59 //
60 // Author:
61 //
62 // Original FORTRAN77 version by Sylvan Elhay, Jaroslav Kautsky.
63 // C++ version by John Burkardt.
64 //
65 // Reference:
66 //
67 // Sylvan Elhay, Jaroslav Kautsky,
68 // Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
69 // Interpolatory Quadrature,
70 // ACM Transactions on Mathematical Software,
71 // Volume 13, Number 4, December 1987, pages 399-415.
72 //
73 // Parameters:
74 //
75 // Output, double T[NT], the knots.
76 //
77 // Output, double WTS[NT], the weights.
78 //
79 {
80  dvector t=(dvector&) _t;
81  dvector wts=(dvector&) _wts;
82 
83  if( t.indexmax()!=wts.indexmax() )
84  {
85  cerr << "Incompatible sizes in void "
86  << "void gauss_hermite (const dvector& _t,const dvector& _wts)" << endl;
87  ad_exit(-1);
88  }
89 
90  int lb = t.indexmin();
91  int ub = t.indexmax();
92 
93  dvector aj(lb,ub);
94  dvector bj(lb,ub);
95  double zemu;
96  int i;
97 
98  // Get the Jacobi matrix and zero-th moment.
99  zemu = 1.772453850905516;
100  for ( i = lb; i <= ub; i++ )
101  {
102  aj(i) = 0.0;
103  }
104  for ( i = lb; i <= ub; i++ )
105  {
106  bj(i) = sqrt((i-lb+1)/2.0);
107  }
108 
109  // Compute the knots and weights.
110  if ( zemu <= 0.0 ) // Exit if the zero-th moment is not positive.
111  {
112  cout << "\n";
113  cout << "SGQF - Fatal error!\n";
114  cout << " ZEMU <= 0.\n";
115  exit ( 1 );
116  }
117 
118  // Set up vectors for IMTQLX.
119  for ( i = lb; i <= ub; i++ )
120  {
121  t(i) = aj(i);
122  }
123  wts(lb) = sqrt ( zemu );
124  for ( i = lb+1; i <= ub; i++ )
125  {
126  wts(i) = 0.0;
127  }
128 
129  // Diagonalize the Jacobi matrix.
130  imtqlx ( t, bj, wts );
131 
132  for ( i = lb; i <= ub; i++ )
133  {
134  wts(i) = wts(i) * wts(i);
135  }
136 
137  return;
138 }
139 
148 void gauss_legendre( double a, double b, const dvector& _t,
149  const dvector& _wts )
150 //
151 // Purpose:
152 //
153 // computes knots and weights of a Gauss-Legendre quadrature formula.
154 //
155 // Discussion:
156 //
157 // The user may specify the interval (A,B).
158 //
159 // Only simple knots are produced.
160 //
161 // Use routine EIQFS to evaluate this quadrature formula.
162 //
163 // Licensing:
164 //
165 // This code is distributed under the GNU LGPL license.
166 //
167 // Modified:
168 //
169 // September 2010 by Derek Seiple
170 //
171 // Author:
172 //
173 // Original FORTRAN77 version by Sylvan Elhay, Jaroslav Kautsky.
174 // C++ version by John Burkardt.
175 //
176 // Reference:
177 //
178 // Sylvan Elhay, Jaroslav Kautsky,
179 // Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
180 // Interpolatory Quadrature,
181 // ACM Transactions on Mathematical Software,
182 // Volume 13, Number 4, December 1987, pages 399-415.
183 //
184 // Parameters:
185 //
186 // Input, double A, B, the interval endpoints, or
187 // other parameters.
188 //
189 // Output, double T[NT], the knots.
190 //
191 // Output, double WTS[NT], the weights.
192 //
193 {
194  dvector t=(dvector&) _t;
195  dvector wts=(dvector&) _wts;
196 
197  if( t.indexmax()!=wts.indexmax() )
198  {
199  cerr << "Incompatible sizes in void "
200 "mygauss_legendre(double a, double b, const dvector& _t, const dvector& _wts)"
201  << endl;
202  ad_exit(-1);
203  }
204 
205  t.shift(0);
206  wts.shift(0);
207  int nt = t.indexmax() + 1;
208  int ub = nt-1;
209 
210  int i;
211  int k;
212  int l;
213  double al;
214  double ab;
215  double abi;
216  double abj;
217  double be;
218  double p;
219  double shft;
220  double slp;
221  double temp;
222  double tmp;
223  double zemu;
224 
225  // Compute the Gauss quadrature formula for default values of A and B.
226  dvector aj(0,ub);
227  dvector bj(0,ub);
228 
229  ab = 0.0;
230  zemu = 2.0 / ( ab + 1.0 );
231  for ( i = 0; i < nt; i++ )
232  {
233  aj[i] = 0.0;
234  }
235  for ( i = 1; i <= nt; i++ )
236  {
237  abi = i + ab * ( i % 2 );
238  abj = 2 * i + ab;
239  bj[i-1] = sqrt ( abi * abi / ( abj * abj - 1.0 ) );
240  }
241 
242  // Compute the knots and weights.
243  if ( zemu <= 0.0 ) // Exit if the zero-th moment is not positive.
244  {
245  cout << "\n";
246  cout << "Fatal error!\n";
247  cout << " ZEMU <= 0.\n";
248  exit ( 1 );
249  }
250 
251  // Set up vectors for IMTQLX.
252  for ( i = 0; i < nt; i++ )
253  {
254  t[i] = aj[i];
255  }
256  wts[0] = sqrt ( zemu );
257  for ( i = 1; i < nt; i++ )
258  {
259  wts[i] = 0.0;
260  }
261 
262  // Diagonalize the Jacobi matrix.
263  imtqlx (t, bj, wts );
264 
265  for ( i = 0; i < nt; i++ )
266  {
267  wts[i] = wts[i] * wts[i];
268  }
269 
270  // Prepare to scale the quadrature formula to other weight function with
271  // valid A and B.
272  ivector mlt(0,ub);
273  for ( i = 0; i < nt; i++ )
274  {
275  mlt[i] = 1;
276  }
277  ivector ndx(0,ub);
278  for ( i = 0; i < nt; i++ )
279  {
280  ndx[i] = i + 1;
281  }
282 
283  dvector st(0,ub);
284  dvector swts(0,ub);
285 
286  temp = 3.0e-14;
287  al = 0.0;
288  be = 0.0;
289  if ( fabs ( b - a ) <= temp )
290  {
291  cout << "\n";
292  cout << "Fatal error!\n";
293  cout << " |B - A| too small.\n";
294  exit ( 1 );
295  }
296  shft = ( a + b ) / 2.0;
297  slp = ( b - a ) / 2.0;
298 
299  p = pow ( slp, al + be + 1.0 );
300 
301  for ( k = 0; k < nt; k++ )
302  {
303  st[k] = shft + slp * t[k];
304  l = abs ( ndx[k] );
305 
306  if ( l != 0 )
307  {
308  tmp = p;
309  for ( i = l - 1; i <= l - 1 + mlt[k] - 1; i++ )
310  {
311  swts[i] = wts[i] * tmp;
312  tmp = tmp * slp;
313  }
314  }
315  }
316 
317  for(i=0;i<nt;i++)
318  {
319  t(i) = st(ub-i);
320  wts(i) = swts(ub-i);
321  }
322 
323  return;
324 }
325 
331 void gauss_legendre(const dvector& _x, const dvector& _w)
332 {
333  gauss_legendre(0,1,_x,_w);
334 }
335 
343 void normalized_gauss_hermite(const dvector& _x, const dvector& _w)
344 {
345  dvector& x=(dvector&) _x;
346  dvector& w=(dvector&) _w;
347  gauss_hermite(x,w);
348  w=elem_prod(w,exp(square(x)));
349  x*=sqrt(2.0);
350  w*=sqrt(2.0);
351 }
352 
359 void imtqlx( const dvector& _d, const dvector& _e, const dvector& _z )
360 //
361 // Purpose:
362 //
363 // IMTQLX diagonalizes a symmetric tridiagonal matrix.
364 //
365 // Discussion:
366 //
367 // This routine is a slightly modified version of the EISPACK routine to
368 // perform the implicit QL algorithm on a symmetric tridiagonal matrix.
369 //
370 // The authors thank the authors of EISPACK for permission to use this
371 // routine.
372 //
373 // It has been modified to produce the product Q' * Z, where Z is an input
374 // vector and Q is the orthogonal matrix diagonalizing the input matrix.
375 // The changes consist (essentialy) of applying the orthogonal transformations
376 // directly to Z as they are generated.
377 //
378 // Licensing:
379 //
380 // This code is distributed under the GNU LGPL license.
381 //
382 // Modified:
383 //
384 // September 2010 by Derek Seiple
385 //
386 // Author:
387 //
388 // Original FORTRAN77 version by Sylvan Elhay, Jaroslav Kautsky.
389 // C++ version by John Burkardt.
390 //
391 // Reference:
392 //
393 // Sylvan Elhay, Jaroslav Kautsky,
394 // Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
395 // Interpolatory Quadrature,
396 // ACM Transactions on Mathematical Software,
397 // Volume 13, Number 4, December 1987, pages 399-415.
398 //
399 // Roger Martin, James Wilkinson,
400 // The Implicit QL Algorithm,
401 // Numerische Mathematik,
402 // Volume 12, Number 5, December 1968, pages 377-383.
403 //
404 // Parameters:
405 //
406 // Input/output, double D(N), the diagonal entries of the matrix.
407 // On output, the information in D has been overwritten.
408 //
409 // Input/output, double E(N), the subdiagonal entries of the
410 // matrix, in entries E(1) through E(N-1). On output, the information in
411 // E has been overwritten.
412 //
413 // Input/output, double Z(N). On input, a vector. On output,
414 // the value of Q' * Z, where Q is the matrix that diagonalizes the
415 // input symmetric tridiagonal matrix.
416 //
417 {
418  dvector d=(dvector&) _d;
419  dvector e=(dvector&) _e;
420  dvector z=(dvector&) _z;
421  if (d.indexmax()!=e.indexmax() || d.indexmax()!=z.indexmax() ||
422  z.indexmax()!=e.indexmax() )
423  {
424  cerr << "Incompatible sizes in void "
425  << "imtqlx ( const dvector& _d, const dvector& _e, const dvector& _z )"
426  << endl;
427  ad_exit(-1);
428  }
429 
430  int lb = d.indexmin();
431  d.shift(0);
432  e.shift(0);
433  z.shift(0);
434  int n = d.indexmax() + 1;
435 
436  double b;
437  double c;
438  double f;
439  double g;
440  int i;
441  int ii;
442  int itn = 30;
443  int j;
444  int k;
445  int l;
446  int m;
447  int mml;
448  double p;
449  double prec;
450  double r;
451  double s;
452 
453  prec = 3.0e-14;
454 
455  if ( n == 1 )
456  {
457  return;
458  }
459 
460  e[n-1] = 0.0;
461 
462  for ( l = 1; l <= n; l++ )
463  {
464  j = 0;
465  for ( ; ; )
466  {
467  for ( m = l; m <= n; m++ )
468  {
469  if ( m == n )
470  {
471  break;
472  }
473 
474  if ( fabs ( e[m-1] ) <= prec * ( fabs ( d[m-1] ) + fabs ( d[m] ) ) )
475  {
476  break;
477  }
478  }
479  p = d[l-1];
480  if ( m == l )
481  {
482  break;
483  }
484  if ( itn <= j )
485  {
486  cout << "\n";
487  cout << "IMTQLX - Fatal error!\n";
488  cout << " Iteration limit exceeded\n";
489  exit ( 1 );
490  }
491  j = j + 1;
492  g = ( d[l] - p ) / ( 2.0 * e[l-1] );
493  r = sqrt ( g * g + 1.0 );
494  g = d[m-1] - p + e[l-1] / ( g + fabs ( r ) * sign ( g ) );
495  s = 1.0;
496  c = 1.0;
497  p = 0.0;
498  mml = m - l;
499 
500  for ( ii = 1; ii <= mml; ii++ )
501  {
502  i = m - ii;
503  f = s * e[i-1];
504  b = c * e[i-1];
505 
506  if ( fabs ( g ) <= fabs ( f ) )
507  {
508  c = g / f;
509  r = sqrt ( c * c + 1.0 );
510  e[i] = f * r;
511  s = 1.0 / r;
512  c = c * s;
513  }
514  else
515  {
516  s = f / g;
517  r = sqrt ( s * s + 1.0 );
518  e[i] = g * r;
519  c = 1.0 / r;
520  s = s * c;
521  }
522  g = d[i] - p;
523  r = ( d[i-1] - g ) * s + 2.0 * c * b;
524  p = s * r;
525  d[i] = g + p;
526  g = c * r - b;
527  f = z[i];
528  z[i] = s * z[i-1] + c * f;
529  z[i-1] = c * z[i-1] - s * f;
530  }
531  d[l-1] = d[l-1] - p;
532  e[l-1] = g;
533  e[m-1] = 0.0;
534  }
535  }
536 
537  m = n;
538 
539  // Sorting.
540  for ( ii = 2; ii <= m; ii++ )
541  {
542  i = ii - 1;
543  k = i;
544  p = d[i-1];
545 
546  for ( j = ii; j <= n; j++ )
547  {
548  if ( d[j-1] > p )
549  {
550  k = j;
551  p = d[j-1];
552  }
553  }
554 
555  if ( k != i )
556  {
557  d[k-1] = d[i-1];
558  d[i-1] = p;
559  p = z[i-1];
560  z[i-1] = z[k-1];
561  z[k-1] = p;
562  }
563  }
564 
565  d.shift(lb);
566  e.shift(lb);
567  z.shift(lb);
568  return;
569 }
d3_array elem_prod(const d3_array &a, const d3_array &b)
Returns d3_array results with computed elements product of a(i, j, k) * b(i, j, k).
Definition: d3arr2a.cpp:92
#define x
Vector of double precision numbers.
Definition: dvector.h:50
int indexmin() const
Get minimum valid index.
Definition: dvector.h:199
void gauss_legendre(double x1, double x2, const dvector &_x, const dvector &_w)
Gauss-Legendre quadature.
Definition: gaussher.cpp:148
void gauss_hermite(const dvector &_x, const dvector &_w)
Gauss-Hermite quadature.
Definition: gaussher.cpp:36
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
exitptr ad_exit
Definition: gradstrc.cpp:53
prnstream & endl(prnstream &)
Array of integers(int) with indexes from index_min to indexmax.
Definition: ivector.h:50
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
#define abs(x)
Definition: cbivnorm.cpp:186
int indexmax() const
Get maximum valid index.
Definition: dvector.h:204
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
void normalized_gauss_hermite(const dvector &_x, const dvector &_w)
Gauss-Hermite quadature.
Definition: gaussher.cpp:343
d3_array exp(const d3_array &arr3)
Returns d3_array results with computed exp from elements in arr3.
Definition: d3arr2a.cpp:28
dvector & shift(int min)
Shift valid range of subscripts.
Definition: dvector.cpp:52
#define w
void imtqlx(const dvector &_d, const dvector &_e, const dvector &_z)
Diagonalizes a symmetric tridiagonal matrix.
Definition: gaussher.cpp:359
double sign(const double x)
The sign of a number.
Definition: gaussher.cpp:25
double square(const double value)
Return square of value; constant object.
Definition: d3arr4.cpp:16
d3_array pow(const d3_array &m, int e)
Description not yet available.
Definition: d3arr6.cpp:17