Skip to content

Commit f6d6979

Browse files
author
Cristy
committed
high precision gauss jordon elimination
1 parent 2d7e67f commit f6d6979

File tree

1 file changed

+62
-25
lines changed

1 file changed

+62
-25
lines changed

magick/matrix.c

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -481,12 +481,15 @@ MagickExport MagickBooleanType GaussJordanElimination(double **matrix,
481481
{
482482
#define GaussJordanSwap(x,y) \
483483
{ \
484-
double temp = (x); \
484+
long double temp = (x); \
485485
(x)=(y); \
486486
(y)=temp; \
487487
}
488-
#define ThrowGaussJordanSwapException() \
488+
#define ThrowGaussJordanException() \
489489
{ \
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); \
490493
if (pivots != (ssize_t *) NULL) \
491494
pivots=(ssize_t *) RelinquishMagickMemory(pivots); \
492495
if (rows != (ssize_t *) NULL) \
@@ -496,81 +499,115 @@ MagickExport MagickBooleanType GaussJordanElimination(double **matrix,
496499
return(MagickFalse); \
497500
}
498501

499-
double
502+
long double
503+
**hp_matrix = (long double **) NULL,
500504
scale;
501505

502506
ssize_t
503507
column,
504-
*columns,
508+
*columns = (ssize_t *) NULL,
505509
i,
506510
j,
507-
*pivots,
511+
*pivots = (ssize_t *) NULL,
508512
row,
509-
*rows;
513+
*rows = (ssize_t *) NULL;
510514

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+
}
511530
columns=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*columns));
512531
rows=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*rows));
513532
pivots=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*pivots));
514533
if ((columns == (ssize_t *) NULL) || (rows == (ssize_t *) NULL) ||
515534
(pivots == (ssize_t *) NULL))
516-
ThrowGaussJordanSwapException();
535+
ThrowGaussJordanException();
517536
(void) memset(columns,0,rank*sizeof(*columns));
518537
(void) memset(rows,0,rank*sizeof(*rows));
519538
(void) memset(pivots,0,rank*sizeof(*pivots));
520539
for (i=0; i < (ssize_t) rank; i++)
521540
{
522-
double
541+
long double
523542
max = 0.0;
524543

525544
ssize_t
526545
k;
527546

547+
/*
548+
Partial pivoting: find the largest absolute value in the unreduced
549+
submatrix.
550+
*/
528551
column=(-1);
529552
row=(-1);
530553
for (j=0; j < (ssize_t) rank; j++)
531554
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))
534557
{
535-
max=fabs(matrix[j][k]);
558+
max=fabsl(hp_matrix[j][k]);
536559
row=j;
537560
column=k;
538561
}
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 */
541565
pivots[column]++;
542566
if (row != column)
543567
{
544568
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]);
546570
for (k=0; k < (ssize_t) number_vectors; k++)
547571
GaussJordanSwap(vectors[k][row],vectors[k][column]);
548572
}
549573
rows[i]=row;
550574
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;
555580
for (j=0; j < (ssize_t) rank; j++)
556-
matrix[column][j]*=scale;
581+
hp_matrix[column][j]*=scale;
557582
for (j=0; j < (ssize_t) number_vectors; j++)
558-
vectors[j][column]*=scale;
583+
vectors[j][column]*=(double) scale;
559584
for (j=0; j < (ssize_t) rank; j++)
560585
if (j != column)
561586
{
562-
scale=matrix[j][column];
563-
matrix[j][column]=0.0;
587+
scale=hp_matrix[j][column];
588+
hp_matrix[j][column]=0.0;
564589
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];
566591
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]);
568593
}
569594
}
570595
for (j=(ssize_t) rank-1; j >= 0; j--)
571596
if (columns[j] != rows[j])
572597
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);
574611
pivots=(ssize_t *) RelinquishMagickMemory(pivots);
575612
rows=(ssize_t *) RelinquishMagickMemory(rows);
576613
columns=(ssize_t *) RelinquishMagickMemory(columns);

0 commit comments

Comments
 (0)