@@ -481,12 +481,15 @@ MagickExport MagickBooleanType GaussJordanElimination(double **matrix,
481
481
{
482
482
#define GaussJordanSwap (x ,y ) \
483
483
{ \
484
- double temp = (x); \
484
+ long double temp = (x); \
485
485
(x)=(y); \
486
486
(y)=temp; \
487
487
}
488
- #define ThrowGaussJordanSwapException () \
488
+ #define ThrowGaussJordanException () \
489
489
{ \
490
+ for (i=0; i < (ssize_t) rank; i++) \
491
+ hp_matrix[i]=(long double *) RelinquishMagickMemory(hp_matrix[i]); \
492
+ hp_matrix=(long double **) RelinquishMagickMemory(hp_matrix); \
490
493
if (pivots != (ssize_t *) NULL) \
491
494
pivots=(ssize_t *) RelinquishMagickMemory(pivots); \
492
495
if (rows != (ssize_t *) NULL) \
@@ -496,81 +499,115 @@ MagickExport MagickBooleanType GaussJordanElimination(double **matrix,
496
499
return(MagickFalse); \
497
500
}
498
501
499
- double
502
+ long double
503
+ * * hp_matrix = (long double * * ) NULL ,
500
504
scale ;
501
505
502
506
ssize_t
503
507
column ,
504
- * columns ,
508
+ * columns = ( ssize_t * ) NULL ,
505
509
i ,
506
510
j ,
507
- * pivots ,
511
+ * pivots = ( ssize_t * ) NULL ,
508
512
row ,
509
- * rows ;
513
+ * rows = ( ssize_t * ) NULL ;
510
514
515
+ /*
516
+ Allocate high precision matrix.
517
+ */
518
+ hp_matrix = (long double * * ) AcquireQuantumMemory (rank ,sizeof (* hp_matrix ));
519
+ if (hp_matrix == (long double * * ) NULL )
520
+ return (MagickFalse );
521
+ for (i = 0 ; i < (ssize_t ) rank ; i ++ )
522
+ {
523
+ hp_matrix [i ]= (long double * ) AcquireQuantumMemory (rank ,
524
+ sizeof (* hp_matrix [i ]));
525
+ if (hp_matrix [i ] == (long double * ) NULL )
526
+ ThrowGaussJordanException ();
527
+ for (j = 0 ; j < (ssize_t ) rank ; j ++ )
528
+ hp_matrix [i ][j ]= (long double )matrix [i ][j ];
529
+ }
511
530
columns = (ssize_t * ) AcquireQuantumMemory (rank ,sizeof (* columns ));
512
531
rows = (ssize_t * ) AcquireQuantumMemory (rank ,sizeof (* rows ));
513
532
pivots = (ssize_t * ) AcquireQuantumMemory (rank ,sizeof (* pivots ));
514
533
if ((columns == (ssize_t * ) NULL ) || (rows == (ssize_t * ) NULL ) ||
515
534
(pivots == (ssize_t * ) NULL ))
516
- ThrowGaussJordanSwapException ();
535
+ ThrowGaussJordanException ();
517
536
(void ) memset (columns ,0 ,rank * sizeof (* columns ));
518
537
(void ) memset (rows ,0 ,rank * sizeof (* rows ));
519
538
(void ) memset (pivots ,0 ,rank * sizeof (* pivots ));
520
539
for (i = 0 ; i < (ssize_t ) rank ; i ++ )
521
540
{
522
- double
541
+ long double
523
542
max = 0.0 ;
524
543
525
544
ssize_t
526
545
k ;
527
546
547
+ /*
548
+ Partial pivoting: find the largest absolute value in the unreduced
549
+ submatrix.
550
+ */
528
551
column = (-1 );
529
552
row = (-1 );
530
553
for (j = 0 ; j < (ssize_t ) rank ; j ++ )
531
554
if (pivots [j ] != 1 )
532
- for (k = 0 ; k < (ssize_t ) rank ; k ++ )
533
- if ((pivots [k ] == 0 ) && (fabs ( matrix [j ][k ]) > max ))
555
+ for (k = 0 ; k < (ssize_t ) rank ; k ++ )
556
+ if ((pivots [k ] == 0 ) && (fabsl ( hp_matrix [j ][k ]) > max ))
534
557
{
535
- max = fabs ( matrix [j ][k ]);
558
+ max = fabsl ( hp_matrix [j ][k ]);
536
559
row = j ;
537
560
column = k ;
538
561
}
539
- if ((column == -1 ) || (row == -1 ))
540
- ThrowGaussJordanSwapException (); /* Singular matrix */
562
+ if ((column == -1 ) || (row == -1 ) ||
563
+ ((fabsl (max ) > 0.0L ) && (fabsl (max ) <= LDBL_MIN )))
564
+ ThrowGaussJordanException (); /* Singular or nearly singular matrix */
541
565
pivots [column ]++ ;
542
566
if (row != column )
543
567
{
544
568
for (k = 0 ; k < (ssize_t ) rank ; k ++ )
545
- GaussJordanSwap (matrix [row ][k ],matrix [column ][k ]);
569
+ GaussJordanSwap (hp_matrix [row ][k ],hp_matrix [column ][k ]);
546
570
for (k = 0 ; k < (ssize_t ) number_vectors ; k ++ )
547
571
GaussJordanSwap (vectors [k ][row ],vectors [k ][column ]);
548
572
}
549
573
rows [i ]= row ;
550
574
columns [i ]= column ;
551
- if (fabs (matrix [column ][column ]) < MagickEpsilon )
552
- ThrowGaussJordanSwapException (); /* Singular matrix */
553
- scale = 1.0 /matrix [column ][column ];
554
- matrix [column ][column ]= 1.0 ;
575
+ if ((fabsl (hp_matrix [column ][column ]) > 0.0L ) &&
576
+ (fabsl (hp_matrix [column ][column ]) <= LDBL_MIN ))
577
+ ThrowGaussJordanException (); /* Singular matrix */
578
+ scale = 1.0L /hp_matrix [column ][column ];
579
+ hp_matrix [column ][column ]= 1.0 ;
555
580
for (j = 0 ; j < (ssize_t ) rank ; j ++ )
556
- matrix [column ][j ]*=scale ;
581
+ hp_matrix [column ][j ]*=scale ;
557
582
for (j = 0 ; j < (ssize_t ) number_vectors ; j ++ )
558
- vectors [j ][column ]*=scale ;
583
+ vectors [j ][column ]*=( double ) scale ;
559
584
for (j = 0 ; j < (ssize_t ) rank ; j ++ )
560
585
if (j != column )
561
586
{
562
- scale = matrix [j ][column ];
563
- matrix [j ][column ]= 0.0 ;
587
+ scale = hp_matrix [j ][column ];
588
+ hp_matrix [j ][column ]= 0.0 ;
564
589
for (k = 0 ; k < (ssize_t ) rank ; k ++ )
565
- matrix [j ][k ]-= scale * matrix [column ][k ];
590
+ hp_matrix [j ][k ]-= scale * hp_matrix [column ][k ];
566
591
for (k = 0 ; k < (ssize_t ) number_vectors ; k ++ )
567
- vectors [k ][j ]-= scale * vectors [k ][column ];
592
+ vectors [k ][j ]-= ( double )( scale * ( long double ) vectors [k ][column ]) ;
568
593
}
569
594
}
570
595
for (j = (ssize_t ) rank - 1 ; j >= 0 ; j -- )
571
596
if (columns [j ] != rows [j ])
572
597
for (i = 0 ; i < (ssize_t ) rank ; i ++ )
573
- GaussJordanSwap (matrix [i ][rows [j ]],matrix [i ][columns [j ]]);
598
+ GaussJordanSwap (hp_matrix [i ][columns [j ]],hp_matrix [i ][rows [j ]]);
599
+ /*
600
+ Copy back the result to the original matrix.
601
+ */
602
+ for (i = 0 ; i < (ssize_t ) rank ; i ++ )
603
+ for (j = 0 ; j < (ssize_t ) rank ; j ++ )
604
+ matrix [i ][j ]= (double )hp_matrix [i ][j ];
605
+ /*
606
+ Free resources.
607
+ */
608
+ for (i = 0 ; i < (ssize_t ) rank ; i ++ )
609
+ hp_matrix [i ]= (long double * ) RelinquishMagickMemory (hp_matrix [i ]);
610
+ hp_matrix = (long double * * ) RelinquishMagickMemory (hp_matrix );
574
611
pivots = (ssize_t * ) RelinquishMagickMemory (pivots );
575
612
rows = (ssize_t * ) RelinquishMagickMemory (rows );
576
613
columns = (ssize_t * ) RelinquishMagickMemory (columns );
0 commit comments