lLinpackBenchmark2017.ino


1
//https://gist.githubusercontent.com/projectgus/8279947/raw/5746ada75a0442d14affa789fbff0f1a5ec5d52f/linpack_bench.ino
2
3
# include <stdlib.h>
4
# include <stdio.h>
5
# include <math.h>
6
7
int do_benchmark ( void );
8
double cpu_time ( void );
9
void daxpy ( int n, double da, double dx[], int incx, double dy[], int incy );
10
double ddot ( int n, double dx[], int incx, double dy[], int incy );
11
int dgefa ( double a[], int lda, int n, int ipvt[] );
12
void dgesl ( double a[], int lda, int n, int ipvt[], double b[], int job );
13
void dscal ( int n, double sa, double x[], int incx );
14
int idamax ( int n, double dx[], int incx );
15
double r8_abs ( double x );
16
double r8_epsilon ( void );
17
double r8_max ( double x, double y );
18
double r8_random ( int iseed[4] );
19
double *r8mat_gen ( int lda, int n );
20
21
static FILE uartout = {0} ;
22
23
static int uart_putchar (char c, FILE *stream)
24
{
25
  Serial.write(c) ;
26
  return 0 ;
27
}
28
29
void setup() {
30
  Serial.begin(9600);
31
//  fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
32
//  stdout = &uartout ;
33
}
34
35
void loop() {
36
  printf("Starting benchmark...\n");
37
  do_benchmark();
38
}
39
40
/******************************************************************************/
41
42
int do_benchmark ( void )
43
44
/******************************************************************************/
45
/*
46
  Purpose:
47
48
    MAIN is the main program for LINPACK_BENCH.
49
50
  Discussion:
51
52
    LINPACK_BENCH drives the double precision LINPACK benchmark program.
53
54
  Modified:
55
56
    25 July 2008
57
58
  Parameters:
59
60
    N is the problem size.
61
*/
62
{
63
# define N 8
64
# define LDA ( N + 1 )
65
66
  static double a[N * LDA];
67
  static double a_max;
68
  static double b[N];
69
  static double b_max;
70
  const double cray = 0.056;
71
  static double eps;
72
  int i;
73
  int info;
74
  static int ipvt[N];
75
  int j;
76
  int job;
77
  double ops;
78
  static double resid[N];
79
  double resid_max;
80
  double residn;
81
  static double rhs[N];
82
  double t1;
83
  double t2;
84
  static double time[6];
85
  double total;
86
  double x[N];
87
88
  printf ( "\n" );
89
  printf ( "LINPACK_BENCH\n" );
90
  printf ( "  C version\n" );
91
  printf ( "\n" );
92
  printf ( "  The LINPACK benchmark.\n" );
93
  printf ( "  Language: C\n" );
94
  printf ( "  Datatype: Double precision real\n" );
95
  printf ( "  Matrix order N               = %d\n", N );
96
  printf ( "  Leading matrix dimension LDA = %d\n", LDA );
97
98
  ops = ( double ) ( 2L * N * N * N ) / 3.0 + 2.0 * ( double ) ( (long)N * N );
99
100
/*
101
  Allocate space for arrays.
102
*/
103
  r8mat_gen ( LDA, N, a);
104
105
  a_max = 0.0;
106
  for ( j = 0; j < N; j++ )
107
  {
108
    for ( i = 0; i < N; i++ )
109
    {
110
      a_max = r8_max ( a_max, a[i+j*LDA] );
111
    }
112
  }
113
114
  for ( i = 0; i < N; i++ )
115
  {
116
    x[i] = 1.0;
117
  }
118
119
  for ( i = 0; i < N; i++ )
120
  {
121
    b[i] = 0.0;
122
    for ( j = 0; j < N; j++ )
123
    {
124
      b[i] = b[i] + a[i+j*LDA] * x[j];
125
    }
126
  }
127
  t1 = cpu_time ( );
128
129
  info = dgefa ( a, LDA, N, ipvt );
130
131
  if ( info != 0 )
132
  {
133
    printf ( "\n" );
134
    printf ( "LINPACK_BENCH - Fatal error!\n" );
135
    printf ( "  The matrix A is apparently singular.\n" );
136
    printf ( "  Abnormal end of execution.\n" );
137
    return 1;
138
  }
139
140
  t2 = cpu_time ( );
141
  time[0] = t2 - t1;
142
143
  t1 = cpu_time ( );
144
145
  job = 0;
146
  dgesl ( a, LDA, N, ipvt, b, job );
147
148
  t2 = cpu_time ( );
149
  time[1] = t2 - t1;
150
151
  total = time[0] + time[1];
152
153
/*
154
  Compute a residual to verify results.
155
*/
156
  r8mat_gen ( LDA, N, a );
157
158
  for ( i = 0; i < N; i++ )
159
  {
160
    x[i] = 1.0;
161
  }
162
163
  for ( i = 0; i < N; i++ )
164
  {
165
    rhs[i] = 0.0;
166
    for ( j = 0; j < N; j++ )
167
    {
168
      rhs[i] = rhs[i] + a[i+j*LDA] * x[j];
169
    }
170
  }
171
172
  for ( i = 0; i < N; i++ )
173
  {
174
    resid[i] = -rhs[i];
175
    for ( j = 0; j < N; j++ )
176
    {
177
      resid[i] = resid[i] + a[i+j*LDA] * b[j];
178
    }
179
  }
180
181
  resid_max = 0.0;
182
  for ( i = 0; i < N; i++ )
183
  {
184
    resid_max = r8_max ( resid_max, r8_abs ( resid[i] ) );
185
  }
186
187
  b_max = 0.0;
188
  for ( i = 0; i < N; i++ )
189
  {
190
    b_max = r8_max ( b_max, r8_abs ( b[i] ) );
191
  }
192
193
  eps = r8_epsilon ( );
194
195
  residn = resid_max / ( double ) N / a_max / b_max / eps;
196
197
  time[2] = total;
198
  if ( 0.0 < total )
199
  {
200
    time[3] = ops / ( 1.0E+06 * total );
201
  }
202
  else
203
  {
204
    time[3] = -1.0;
205
  }
206
  time[4] = 2.0 / time[3];
207
  time[5] = total / cray;
208
209
  printf ( "\n" );
210
  printf ( "     Norm. Resid      Resid           MACHEP         X[1]          X[N]\n" );
211
  printf ( "\n" );
212
  Serial.print("  ");
213
  Serial.print(residn, 14);
214
  Serial.print("  ");
215
  Serial.print(resid_max, 14);
216
  Serial.print("  ");
217
  Serial.print(eps, 14);
218
  Serial.print("  ");
219
  Serial.print(b[0], 14);
220
  Serial.print("  ");
221
  Serial.print(b[N-1], 14);
222
  Serial.print("  ");
223
  //printf ( "  %14f  %14f  %14e  %14f  %14f\n", residn, resid_max, eps, b[0], b[N-1] );
224
  printf ( "\n" );
225
  printf ( "      Factor     Solve      Total     MFLOPS       Unit      Cray-Ratio\n" );
226
  printf ( "\n" );
227
  for(int i =0; i<6;i++) {
228
      Serial.print("  ");
229
      Serial.print(time[i], 9);
230
  }
231
  //printf ( "  %9f  %9f  %9f  %9f  %9f  %9f\n", 
232
  //  time[0], time[1], time[2], time[3], time[4], time[5] );
233
234
/*
235
  Terminate.
236
*/
237
  printf ( "\n" );
238
  printf ( "LINPACK_BENCH\n" );
239
  printf ( "  Normal end of execution.\n" );
240
241
  printf ( "\n" );
242
243
  return 0;
244
# undef LDA
245
# undef N
246
}
247
/******************************************************************************/
248
249
double cpu_time ( void )
250
251
/******************************************************************************/
252
/*
253
  Purpose:
254
255
    CPU_TIME returns the current reading on the CPU clock.
256
257
  Discussion:
258
259
    The CPU time measurements available through this routine are often
260
    not very accurate.  In some cases, the accuracy is no better than
261
    a hundredth of a second.  
262
263
  Licensing:
264
265
    This code is distributed under the GNU LGPL license. 
266
267
  Modified:
268
269
    06 June 2005
270
271
  Author:
272
273
    John Burkardt
274
275
  Parameters:
276
277
    Output, double CPU_TIME, the current reading of the CPU clock, in seconds.
278
*/
279
{
280
  double value;
281
282
  value = ( double ) micros ( ) 
283
        / ( double ) 1000000;
284
285
  return value;
286
}
287
/******************************************************************************/
288
289
void daxpy ( int n, double da, double dx[], int incx, double dy[], int incy )
290
291
/******************************************************************************/
292
/*
293
  Purpose:
294
295
    DAXPY computes constant times a vector plus a vector.
296
297
  Discussion:
298
299
    This routine uses unrolled loops for increments equal to one.
300
301
  Modified:
302
303
    30 March 2007
304
305
  Author:
306
307
    FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart.
308
    C version by John Burkardt
309
310
  Reference:
311
312
    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
313
    LINPACK User's Guide,
314
    SIAM, 1979.
315
316
    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
317
    Basic Linear Algebra Subprograms for Fortran Usage,
318
    Algorithm 539, 
319
    ACM Transactions on Mathematical Software, 
320
    Volume 5, Number 3, September 1979, pages 308-323.
321
322
  Parameters:
323
324
    Input, int N, the number of elements in DX and DY.
325
326
    Input, double DA, the multiplier of DX.
327
328
    Input, double DX[*], the first vector.
329
330
    Input, int INCX, the increment between successive entries of DX.
331
332
    Input/output, double DY[*], the second vector.
333
    On output, DY[*] has been replaced by DY[*] + DA * DX[*].
334
335
    Input, int INCY, the increment between successive entries of DY.
336
*/
337
{
338
  int i;
339
  int ix;
340
  int iy;
341
  int m;
342
343
  if ( n <= 0 )
344
  {
345
    return;
346
  }
347
348
  if ( da == 0.0 )
349
  {
350
    return;
351
  }
352
/*
353
  Code for unequal increments or equal increments
354
  not equal to 1.
355
*/
356
  if ( incx != 1 || incy != 1 )
357
  {
358
    if ( 0 <= incx )
359
    {
360
      ix = 0;
361
    }
362
    else
363
    {
364
      ix = ( - n + 1 ) * incx;
365
    }
366
367
    if ( 0 <= incy )
368
    {
369
      iy = 0;
370
    }
371
    else
372
    {
373
      iy = ( - n + 1 ) * incy;
374
    }
375
376
    for ( i = 0; i < n; i++ )
377
    {
378
      dy[iy] = dy[iy] + da * dx[ix];
379
      ix = ix + incx;
380
      iy = iy + incy;
381
    }
382
  }
383
/*
384
  Code for both increments equal to 1.
385
*/
386
  else
387
  {
388
    m = n % 4;
389
390
    for ( i = 0; i < m; i++ )
391
    {
392
      dy[i] = dy[i] + da * dx[i];
393
    }
394
395
    for ( i = m; i < n; i = i + 4 )
396
    {
397
      dy[i  ] = dy[i  ] + da * dx[i  ];
398
      dy[i+1] = dy[i+1] + da * dx[i+1];
399
      dy[i+2] = dy[i+2] + da * dx[i+2];
400
      dy[i+3] = dy[i+3] + da * dx[i+3];
401
    }
402
  }
403
  return;
404
}
405
/******************************************************************************/
406
407
double ddot ( int n, double dx[], int incx, double dy[], int incy )
408
409
/******************************************************************************/
410
/*
411
  Purpose:
412
413
    DDOT forms the dot product of two vectors.
414
415
  Discussion:
416
417
    This routine uses unrolled loops for increments equal to one.
418
419
  Modified:
420
421
    30 March 2007
422
423
  Author:
424
425
    FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart.
426
    C version by John Burkardt
427
428
  Reference:
429
430
    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
431
    LINPACK User's Guide,
432
    SIAM, 1979.
433
434
    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
435
    Basic Linear Algebra Subprograms for Fortran Usage,
436
    Algorithm 539, 
437
    ACM Transactions on Mathematical Software, 
438
    Volume 5, Number 3, September 1979, pages 308-323.
439
440
  Parameters:
441
442
    Input, int N, the number of entries in the vectors.
443
444
    Input, double DX[*], the first vector.
445
446
    Input, int INCX, the increment between successive entries in DX.
447
448
    Input, double DY[*], the second vector.
449
450
    Input, int INCY, the increment between successive entries in DY.
451
452
    Output, double DDOT, the sum of the product of the corresponding
453
    entries of DX and DY.
454
*/
455
{
456
  double dtemp;
457
  int i;
458
  int ix;
459
  int iy;
460
  int m;
461
462
  dtemp = 0.0;
463
464
  if ( n <= 0 )
465
  {
466
    return dtemp;
467
  }
468
/*
469
  Code for unequal increments or equal increments
470
  not equal to 1.
471
*/
472
  if ( incx != 1 || incy != 1 )
473
  {
474
    if ( 0 <= incx )
475
    {
476
      ix = 0;
477
    }
478
    else
479
    {
480
      ix = ( - n + 1 ) * incx;
481
    }
482
483
    if ( 0 <= incy )
484
    {
485
      iy = 0;
486
    }
487
    else
488
    {
489
      iy = ( - n + 1 ) * incy;
490
    }
491
492
    for ( i = 0; i < n; i++ )
493
    {
494
      dtemp = dtemp + dx[ix] * dy[iy];
495
      ix = ix + incx;
496
      iy = iy + incy;
497
    }
498
  }
499
/*
500
  Code for both increments equal to 1.
501
*/
502
  else
503
  {
504
    m = n % 5;
505
506
    for ( i = 0; i < m; i++ )
507
    {
508
      dtemp = dtemp + dx[i] * dy[i];
509
    }
510
511
    for ( i = m; i < n; i = i + 5 )
512
    {
513
      dtemp = dtemp + dx[i  ] * dy[i  ] 
514
                    + dx[i+1] * dy[i+1] 
515
                    + dx[i+2] * dy[i+2] 
516
                    + dx[i+3] * dy[i+3] 
517
                    + dx[i+4] * dy[i+4];
518
    }
519
  }
520
  return dtemp;
521
}
522
/******************************************************************************/
523
524
int dgefa ( double a[], int lda, int n, int ipvt[] )
525
526
/******************************************************************************/
527
/*
528
  Purpose:
529
530
    DGEFA factors a real general matrix.
531
532
  Modified:
533
534
    16 May 2005
535
536
  Author:
537
538
    C version by John Burkardt.
539
540
  Reference:
541
542
    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
543
    LINPACK User's Guide,
544
    SIAM, (Society for Industrial and Applied Mathematics),
545
    3600 University City Science Center,
546
    Philadelphia, PA, 19104-2688.
547
    ISBN 0-89871-172-X
548
549
  Parameters:
550
551
    Input/output, double A[LDA*N].
552
    On intput, the matrix to be factored.
553
    On output, an upper triangular matrix and the multipliers used to obtain
554
    it.  The factorization can be written A=L*U, where L is a product of
555
    permutation and unit lower triangular matrices, and U is upper triangular.
556
557
    Input, int LDA, the leading dimension of A.
558
559
    Input, int N, the order of the matrix A.
560
561
    Output, int IPVT[N], the pivot indices.
562
563
    Output, int DGEFA, singularity indicator.
564
    0, normal value.
565
    K, if U(K,K) == 0.  This is not an error condition for this subroutine,
566
    but it does indicate that DGESL or DGEDI will divide by zero if called.
567
    Use RCOND in DGECO for a reliable indication of singularity.
568
*/
569
{
570
  int info;
571
  int j;
572
  int k;
573
  int l;
574
  double t;
575
/*
576
  Gaussian elimination with partial pivoting.
577
*/
578
  info = 0;
579
580
  for ( k = 1; k <= n-1; k++ )
581
  {
582
/*
583
  Find L = pivot index.
584
*/
585
    l = idamax ( n-k+1, a+(k-1)+(k-1)*lda, 1 ) + k - 1;
586
    ipvt[k-1] = l;
587
/*
588
  Zero pivot implies this column already triangularized.
589
*/
590
    if ( a[l-1+(k-1)*lda] == 0.0 )
591
    {
592
      info = k;
593
      continue;
594
    }
595
/*
596
  Interchange if necessary.
597
*/
598
    if ( l != k )
599
    {
600
      t = a[l-1+(k-1)*lda];
601
      a[l-1+(k-1)*lda] = a[k-1+(k-1)*lda];
602
      a[k-1+(k-1)*lda] = t;
603
    }
604
/*
605
  Compute multipliers.
606
*/
607
    t = -1.0 / a[k-1+(k-1)*lda];
608
609
    dscal ( n-k, t, a+k+(k-1)*lda, 1 );
610
/*
611
  Row elimination with column indexing.
612
*/
613
    for ( j = k+1; j <= n; j++ )
614
    {
615
      t = a[l-1+(j-1)*lda];
616
      if ( l != k )
617
      {
618
        a[l-1+(j-1)*lda] = a[k-1+(j-1)*lda];
619
        a[k-1+(j-1)*lda] = t;
620
      }
621
      daxpy ( n-k, t, a+k+(k-1)*lda, 1, a+k+(j-1)*lda, 1 );
622
    }
623
624
  }
625
626
  ipvt[n-1] = n;
627
628
  if ( a[n-1+(n-1)*lda] == 0.0 )
629
  {
630
    info = n;
631
  }
632
633
  return info;
634
}
635
/******************************************************************************/
636
637
void dgesl ( double a[], int lda, int n, int ipvt[], double b[], int job )
638
639
/******************************************************************************/
640
/*
641
  Purpose:
642
643
    DGESL solves a real general linear system A * X = B.
644
645
  Discussion:
646
647
    DGESL can solve either of the systems A * X = B or A' * X = B.
648
649
    The system matrix must have been factored by DGECO or DGEFA.
650
651
    A division by zero will occur if the input factor contains a
652
    zero on the diagonal.  Technically this indicates singularity
653
    but it is often caused by improper arguments or improper
654
    setting of LDA.  It will not occur if the subroutines are
655
    called correctly and if DGECO has set 0.0 < RCOND
656
    or DGEFA has set INFO == 0.
657
658
  Modified:
659
660
    16 May 2005
661
662
  Author:
663
664
    C version by John Burkardt.
665
666
  Reference:
667
668
    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
669
    LINPACK User's Guide,
670
    SIAM, (Society for Industrial and Applied Mathematics),
671
    3600 University City Science Center,
672
    Philadelphia, PA, 19104-2688.
673
    ISBN 0-89871-172-X
674
675
  Parameters:
676
677
    Input, double A[LDA*N], the output from DGECO or DGEFA.
678
679
    Input, int LDA, the leading dimension of A.
680
681
    Input, int N, the order of the matrix A.
682
683
    Input, int IPVT[N], the pivot vector from DGECO or DGEFA.
684
685
    Input/output, double B[N].
686
    On input, the right hand side vector.
687
    On output, the solution vector.
688
689
    Input, int JOB.
690
    0, solve A * X = B;
691
    nonzero, solve A' * X = B.
692
*/
693
{
694
  int k;
695
  int l;
696
  double t;
697
/*
698
  Solve A * X = B.
699
*/
700
  if ( job == 0 )
701
  {
702
    for ( k = 1; k <= n-1; k++ )
703
    {
704
      l = ipvt[k-1];
705
      t = b[l-1];
706
707
      if ( l != k )
708
      {
709
        b[l-1] = b[k-1];
710
        b[k-1] = t;
711
      }
712
713
      daxpy ( n-k, t, a+k+(k-1)*lda, 1, b+k, 1 );
714
715
    }
716
717
    for ( k = n; 1 <= k; k-- )
718
    {
719
      b[k-1] = b[k-1] / a[k-1+(k-1)*lda];
720
      t = -b[k-1];
721
      daxpy ( k-1, t, a+0+(k-1)*lda, 1, b, 1 );
722
    }
723
  }
724
/*
725
  Solve A' * X = B.
726
*/
727
  else
728
  {
729
    for ( k = 1; k <= n; k++ )
730
    {
731
      t = ddot ( k-1, a+0+(k-1)*lda, 1, b, 1 );
732
      b[k-1] = ( b[k-1] - t ) / a[k-1+(k-1)*lda];
733
    }
734
735
    for ( k = n-1; 1 <= k; k-- )
736
    {
737
      b[k-1] = b[k-1] + ddot ( n-k, a+k+(k-1)*lda, 1, b+k, 1 );
738
      l = ipvt[k-1];
739
740
      if ( l != k )
741
      {
742
        t = b[l-1];
743
        b[l-1] = b[k-1];
744
        b[k-1] = t;
745
      }
746
    }
747
  }
748
  return;
749
}
750
/******************************************************************************/
751
752
void dscal ( int n, double sa, double x[], int incx )
753
754
/******************************************************************************/
755
/*
756
  Purpose:
757
758
    DSCAL scales a vector by a constant.
759
760
  Modified:
761
762
    30 March 2007
763
764
  Author:
765
766
    FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart.
767
    C version by John Burkardt
768
769
  Reference:
770
771
    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
772
    LINPACK User's Guide,
773
    SIAM, 1979.
774
775
    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
776
    Basic Linear Algebra Subprograms for Fortran Usage,
777
    Algorithm 539,
778
    ACM Transactions on Mathematical Software,
779
    Volume 5, Number 3, September 1979, pages 308-323.
780
781
  Parameters:
782
783
    Input, int N, the number of entries in the vector.
784
785
    Input, double SA, the multiplier.
786
787
    Input/output, double X[*], the vector to be scaled.
788
789
    Input, int INCX, the increment between successive entries of X.
790
*/
791
{
792
  int i;
793
  int ix;
794
  int m;
795
796
  if ( n <= 0 )
797
  {
798
  }
799
  else if ( incx == 1 )
800
  {
801
    m = n % 5;
802
803
    for ( i = 0; i < m; i++ )
804
    {
805
      x[i] = sa * x[i];
806
    }
807
808
    for ( i = m; i < n; i = i + 5 )
809
    {
810
      x[i]   = sa * x[i];
811
      x[i+1] = sa * x[i+1];
812
      x[i+2] = sa * x[i+2];
813
      x[i+3] = sa * x[i+3];
814
      x[i+4] = sa * x[i+4];
815
    }
816
  }
817
  else
818
  {
819
    if ( 0 <= incx )
820
    {
821
      ix = 0;
822
    }
823
    else
824
    {
825
      ix = ( - n + 1 ) * incx;
826
    }
827
828
    for ( i = 0; i < n; i++ )
829
    {
830
      x[ix] = sa * x[ix];
831
      ix = ix + incx;
832
    }
833
  }
834
  return;
835
}
836
/******************************************************************************/
837
838
int idamax ( int n, double dx[], int incx )
839
840
/******************************************************************************/
841
/*
842
  Purpose:
843
844
    IDAMAX finds the index of the vector element of maximum absolute value.
845
846
  Discussion:
847
848
    WARNING: This index is a 1-based index, not a 0-based index!
849
850
  Modified:
851
852
    30 March 2007
853
854
  Author:
855
856
    FORTRAN77 original by Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart.
857
    C version by John Burkardt
858
859
  Reference:
860
861
    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
862
    LINPACK User's Guide,
863
    SIAM, 1979.
864
865
    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
866
    Basic Linear Algebra Subprograms for Fortran Usage,
867
    Algorithm 539,
868
    ACM Transactions on Mathematical Software,
869
    Volume 5, Number 3, September 1979, pages 308-323.
870
871
  Parameters:
872
873
    Input, int N, the number of entries in the vector.
874
875
    Input, double X[*], the vector to be examined.
876
877
    Input, int INCX, the increment between successive entries of SX.
878
879
    Output, int IDAMAX, the index of the element of maximum
880
    absolute value.
881
*/
882
{
883
  double dmax;
884
  int i;
885
  int ix;
886
  int value;
887
888
  value = 0;
889
890
  if ( n < 1 || incx <= 0 )
891
  {
892
    return value;
893
  }
894
895
  value = 1;
896
897
  if ( n == 1 )
898
  {
899
    return value;
900
  }
901
902
  if ( incx == 1 )
903
  {
904
    dmax = r8_abs ( dx[0] );
905
906
    for ( i = 1; i < n; i++ )
907
    {
908
      if ( dmax < r8_abs ( dx[i] ) )
909
      {
910
        value = i + 1;
911
        dmax = r8_abs ( dx[i] );
912
      }
913
    }
914
  }
915
  else
916
  {
917
    ix = 0;
918
    dmax = r8_abs ( dx[0] );
919
    ix = ix + incx;
920
921
    for ( i = 1; i < n; i++ )
922
    {
923
      if ( dmax < r8_abs ( dx[ix] ) )
924
      {
925
        value = i + 1;
926
        dmax = r8_abs ( dx[ix] );
927
      }
928
      ix = ix + incx;
929
    }
930
  }
931
932
  return value;
933
}
934
/******************************************************************************/
935
936
double r8_abs ( double x )
937
938
/******************************************************************************/
939
/*
940
  Purpose:
941
942
    R8_ABS returns the absolute value of a R8.
943
944
  Modified:
945
946
    02 April 2005
947
948
  Author:
949
950
    John Burkardt
951
952
  Parameters:
953
954
    Input, double X, the quantity whose absolute value is desired.
955
956
    Output, double R8_ABS, the absolute value of X.
957
*/
958
{
959
  double value;
960
961
  if ( 0.0 <= x )
962
  {
963
    value = x;
964
  } 
965
  else
966
  {
967
    value = -x;
968
  }
969
  return value;
970
}
971
/******************************************************************************/
972
973
double r8_epsilon ( void )
974
975
/******************************************************************************/
976
/*
977
  Purpose:
978
979
    R8_EPSILON returns the R8 round off unit.
980
981
  Discussion:
982
983
    R8_EPSILON is a number R which is a power of 2 with the property that,
984
    to the precision of the computer's arithmetic,
985
      1 < 1 + R
986
    but 
987
      1 = ( 1 + R / 2 )
988
989
  Licensing:
990
991
    This code is distributed under the GNU LGPL license. 
992
993
  Modified:
994
995
    08 May 2006
996
997
  Author:
998
999
    John Burkardt
1000
1001
  Parameters:
1002
1003
    Output, double R8_EPSILON, the double precision round-off unit.
1004
*/
1005
{
1006
  double r;
1007
1008
  r = 1.0;
1009
1010
  while ( 1.0 < ( double ) ( 1.0 + r )  )
1011
  {
1012
    r = r / 2.0;
1013
  }
1014
  r = 2.0 * r;
1015
1016
  return r;
1017
}
1018
/******************************************************************************/
1019
1020
double r8_max ( double x, double y )
1021
1022
/******************************************************************************/
1023
/*
1024
  Purpose:
1025
1026
    R8_MAX returns the maximum of two R8's.
1027
1028
  Modified:
1029
1030
    18 August 2004
1031
1032
  Author:
1033
1034
    John Burkardt
1035
1036
  Parameters:
1037
1038
    Input, double X, Y, the quantities to compare.
1039
1040
    Output, double R8_MAX, the maximum of X and Y.
1041
*/
1042
{
1043
  double value;
1044
1045
  if ( y < x )
1046
  {
1047
    value = x;
1048
  } 
1049
  else
1050
  {
1051
    value = y;
1052
  }
1053
  return value;
1054
}
1055
/******************************************************************************/
1056
1057
double r8_random ( int iseed[4] )
1058
1059
/******************************************************************************/
1060
/*
1061
  Purpose:
1062
1063
    R8_RANDOM returns a uniformly distributed random number between 0 and 1.
1064
1065
  Discussion:
1066
1067
    This routine uses a multiplicative congruential method with modulus
1068
    2**48 and multiplier 33952834046453 (see G.S.Fishman,
1069
    'Multiplicative congruential random number generators with modulus
1070
    2**b: an exhaustive analysis for b = 32 and a partial analysis for
1071
    b = 48', Math. Comp. 189, pp 331-344, 1990).
1072
1073
    48-bit integers are stored in 4 integer array elements with 12 bits
1074
    per element. Hence the routine is portable across machines with
1075
    integers of 32 bits or more.
1076
1077
  Parameters:
1078
1079
    Input/output, integer ISEED(4).
1080
    On entry, the seed of the random number generator; the array
1081
    elements must be between 0 and 4095, and ISEED(4) must be odd.
1082
    On exit, the seed is updated.
1083
1084
    Output, double R8_RANDOM, the next pseudorandom number.
1085
*/
1086
{
1087
  int ipw2 = 4096;
1088
  int it1;
1089
  int it2;
1090
  int it3;
1091
  int it4;
1092
  int m1 = 494;
1093
  int m2 = 322;
1094
  int m3 = 2508;
1095
  int m4 = 2549;
1096
  double r = 1.0 / 4096.0;
1097
  double value;
1098
/*
1099
  Multiply the seed by the multiplier modulo 2**48.
1100
*/
1101
  it4 = iseed[3] * m4;
1102
  it3 = it4 / ipw2;
1103
  it4 = it4 - ipw2 * it3;
1104
  it3 = it3 + iseed[2] * m4 + iseed[3] * m3;
1105
  it2 = it3 / ipw2;
1106
  it3 = it3 - ipw2 * it2;
1107
  it2 = it2 + iseed[1] * m4 + iseed[2] * m3 + iseed[3] * m2;
1108
  it1 = it2 / ipw2;
1109
  it2 = it2 - ipw2 * it1;
1110
  it1 = it1 + iseed[0] * m4 + iseed[1] * m3 + iseed[2] * m2 + iseed[3] * m1;
1111
  it1 = ( it1 % ipw2 );
1112
/*
1113
  Return updated seed
1114
*/
1115
  iseed[0] = it1;
1116
  iseed[1] = it2;
1117
  iseed[2] = it3;
1118
  iseed[3] = it4;
1119
/*
1120
  Convert 48-bit integer to a real number in the interval (0,1)
1121
*/
1122
  value = 
1123
      r * ( ( double ) ( it1 ) 
1124
    + r * ( ( double ) ( it2 ) 
1125
    + r * ( ( double ) ( it3 ) 
1126
    + r * ( ( double ) ( it4 ) ) ) ) );
1127
1128
  return value;
1129
}
1130
/******************************************************************************/
1131
1132
void r8mat_gen ( int lda, int n, double*a )
1133
1134
/******************************************************************************/
1135
/*
1136
  Purpose:
1137
1138
    R8MAT_GEN generates a random R8MAT.
1139
1140
  Modified:
1141
1142
    06 June 2005
1143
1144
  Parameters:
1145
1146
    Input, integer LDA, the leading dimension of the matrix.
1147
1148
    Input, integer N, the order of the matrix.
1149
1150
    Output, double R8MAT_GEN[LDA*N], the N by N matrix.
1151
*/
1152
{
1153
  int i;
1154
  int init[4] = { 1, 2, 3, 1325 };
1155
  int j;
1156
1157
  for ( j = 1; j <= n; j++ )
1158
  {
1159
    for ( i = 1; i <= n; i++ )
1160
    {
1161
      a[i-1+(j-1)*lda] = r8_random ( init ) - 0.5;
1162
    }
1163
  }
1164
}
1165
/******************************************************************************/