00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <ctype.h>
00051 #include <math.h>
00052 #include <float.h>
00053 #include <errno.h>
00054
00055 #include "cmatrix.h"
00056
00057 #ifndef _MATRIX_NO_PLOTTING
00058 #include "cplot.h"
00059 #endif
00060
00061
00062 #ifndef WIN32
00063 #ifdef _WIN32
00064 #define WIN32
00065 #endif
00066 #endif
00067
00068 #if defined _MSC_VER && _MSC_VER < 1400
00069 #define _CRT_SECURE_NO_DEPRECATE
00070 #endif
00071
00072 #ifndef _MSC_VER
00073 #define _CRT_SECURE_NO_DEPRECATE
00074 #endif
00075
00076 #include "kiss_fft.h"
00077
00078
00079 #ifdef MTX_DEBUG
00080 #include <time.h>
00081 #endif
00082
00083
00084 #ifndef PI
00085 #define PI (3.1415926535897932384626433832795)
00086 #endif
00087
00088 #ifndef TWOPI
00089 #define TWOPI (6.283185307179586476925286766559)
00090 #endif
00091
00092 #ifndef HALFPI
00093 #define HALFPI (1.5707963267948966192313216916398)
00094 #endif
00095
00096
00097 #define MTX_MAX_READFROMFILE_BUFFER (65536)
00098 #define MATRIX_MIN_RLE_TOLERANCE (1.0e-16)
00099 #define MTX_MAX_COMMENT_LENGTH (1024*6)
00100
00101
00102 #define MTX_ID_SIZE (8)
00103 #define MTX_ID_COMPRESSED_01 ("MTX01\n")
00104 #define MTX_ID_LEGACY_V01 ("Matrix\n")
00105 #define MTX_ID_LEGACY_V02 ("MTXV02\n")
00106
00107 #define MTX_VERSION_NR_DEFAULT (101)
00108 #define MTX_VERSION_NR_COMPRESSED_01 (102)
00109 #define MTX_VERSION_NR_LEGACY_V01 (1)
00110 #define MTX_VERSION_NR_LEGACY_V02 (2)
00111
00112 #define MTX_NK (8)
00113
00114 #define MTX_NAN (sqrt(-1.0))
00115 #define MTX_POS_INF (-log(0.0))
00116 #define MTX_NEG_INF ( log(0.0))
00117
00118
00119
00120
00121
00122
00123
00124
00125 BOOL MTX_static_global_treat_1x1_as_scalar = TRUE;
00126
00127
00128 typedef struct
00129 {
00130 char id[8];
00131 unsigned headersize;
00132 unsigned isReal;
00133 unsigned nrows;
00134 unsigned ncols;
00135 unsigned filesize;
00136 unsigned crc;
00137 char *comment;
00138 }_MTX_STRUCT_FileHeader;
00139
00140 typedef struct
00141 {
00142 unsigned length[MTX_NK];
00143 unsigned char isCompressed[MTX_NK];
00144 unsigned totalLength;
00145 }_MTX_STRUCT_CompressedColumnHeader;
00146
00147
00148
00149 typedef struct _MTX_listItemCplx
00150 {
00151 BOOL isReal;
00152 double *rowptr;
00153 stComplex *rowptr_cplx;
00154 struct _MTX_listItemCplx *next;
00155 }_MTX_STRUCT_ReadFromFileListElem;
00156
00157
00158
00159 static BOOL MTX_static_alloc( MTX *M, const unsigned nrows, const unsigned ncols, const BOOL setToZero, const BOOL isReal );
00160
00161
00162 static BOOL MTX_static_ConvertComplexTo( MTX *M, BOOL useReal );
00163
00164 static BOOL MTX_static_get_row_array_from_string( char *datastr, _MTX_STRUCT_ReadFromFileListElem *L, const unsigned ncols );
00165
00166
00167 static BOOL MTX_static_get_next_valid_data_line(
00168 FILE *in,
00169 char *linebuf,
00170 unsigned *line_length,
00171 BOOL *atEOF
00172 );
00173
00174
00175 static BOOL MTX_static_get_next_valid_data_line_from_matrix_string(
00176 const char *strMatrix,
00177 const unsigned strLength,
00178 unsigned *index,
00179 char *linebuf,
00180 unsigned *line_length,
00181 BOOL *atEndOfString
00182 );
00183
00184
00185
00186
00187 static BOOL MTX_static_extract_cplx_from_string_with_leading_digit(
00188 char *datastr,
00189 const unsigned indexS,
00190 const unsigned indexE,
00191 double *re,
00192 double *im
00193 );
00194
00195
00196 static BOOL MTX_static_extract_real_into_cplx_from_string(
00197 char *datastr,
00198 const unsigned indexS,
00199 double *re,
00200 double *im
00201 );
00202
00203
00204 static BOOL MTX_static_look_for_complex_data(
00205 char *linebuf,
00206 const unsigned line_length,
00207 BOOL *hasComplex
00208 );
00209
00210
00211
00212
00213 static BOOL MTX_static_round_value_to_integer( double *value );
00214
00215
00216 static BOOL MTX_static_round_value( double *value, const unsigned precision );
00217
00218
00219
00220 static void MTX_static_quicksort( double *a, unsigned start, unsigned end );
00221 static void MTX_static_swap_doubles( double *a, double *b );
00222 static int MTX_static_partition( double *a, unsigned start, unsigned end );
00223 static void MTX_static_quicksort_indexed( double *a, double *index, unsigned start, unsigned end );
00224 static void MTX_static_swap_doubles_indexed( double *a, double *b, double *index_a, double *index_b );
00225 static int MTX_static_partition_indexed( double *a, double *index, unsigned start, unsigned end );
00226
00227
00228
00229 static void MTX_static_quick_sqrt( const double *a_re, const double *a_im, double *re, double *im );
00230
00231
00232
00233 static void MTX_static_quick_complex_mult_ab(
00234 const double* a_re,
00235 const double* a_im,
00236 const double* b_re,
00237 const double* b_im,
00238 double *re,
00239 double *im );
00240
00241
00242 static void MTX_static_quick_complex_mult_abc(
00243 const double* a_re,
00244 const double* a_im,
00245 const double* b_re,
00246 const double* b_im,
00247 const double* c_re,
00248 const double* c_im,
00249 double *re,
00250 double *im );
00251
00252
00253
00254 static void MTX_static_quick_complex_divide(
00255 const double* a_re,
00256 const double* a_im,
00257 const double* b_re,
00258 const double* b_im,
00259 double *re,
00260 double *im );
00261
00262
00263
00264
00265 static unsigned MTX_static_CRC32(unsigned ulCRC);
00266
00267
00268
00269
00270
00271 static void MTX_static_updateCRC( unsigned char *pBytes, const unsigned nBytes, unsigned *uiCRC );
00272
00273
00274 static void MTX_static_SaveAndLoadCleanUp( FILE *fid, unsigned char **bytes, unsigned char **compressed, const unsigned nk );
00275
00276
00277 static BOOL MTX_static_ReadCompressed_LegacyVersion( MTX* M, const char *path );
00278
00279
00280
00281
00282
00283
00284 static BOOL MTX_static_Factorize( BOOL *isFullRank, const unsigned n, unsigned* index, MTX *A );
00285
00286
00287
00288 static BOOL MTX_static_SolveByGaussianElimination(
00289 const MTX *b,
00290 MTX *X,
00291 const MTX *A,
00292 unsigned *index );
00293
00294
00295 static void MTX_static_Det_cleanup( unsigned *index, double *scale, MTX *U, MTX *magMtx );
00296
00297
00298
00299
00300
00301
00302 static BOOL MTX_static_fft(
00303 const MTX *src,
00304 MTX *dst,
00305 BOOL isFwd
00306 );
00307
00308
00309
00310 static BOOL MTX_static_fft_inplace(
00311 MTX *src,
00312 BOOL isFwd
00313 );
00314
00315
00316
00317
00318
00319
00320 static double MTX_static_get_rand_value();
00321
00322
00323
00324
00325
00326
00327
00328
00329 static double MTX_static_get_randn_value();
00330
00331
00332
00333 BOOL MTX_Initialize_MTXEngine()
00334 {
00335 return TRUE;
00336 }
00337
00338 BOOL MTX_Enable1x1MatricesForTreatmentAsScalars( BOOL enable )
00339 {
00340 MTX_static_global_treat_1x1_as_scalar = enable;
00341 return TRUE;
00342 }
00343
00344 BOOL MTX_isNull( const MTX *M )
00345 {
00346 if( !M )
00347 return TRUE;
00348
00349 if( M->data == NULL && M->cplx == NULL )
00350 return TRUE;
00351
00352 return FALSE;
00353 }
00354
00355 BOOL MTX_isConformalForMultiplication( const MTX *A, const MTX *B )
00356 {
00357 if( MTX_isNull( A ) )
00358 {
00359 return FALSE;
00360 }
00361 if( MTX_isNull( B ) )
00362 {
00363 return FALSE;
00364 }
00365
00366 return( A->ncols == B->nrows );
00367 }
00368
00369 BOOL MTX_isConformalForAddition( const MTX *A, const MTX *B )
00370 {
00371 if( MTX_isNull( A ) )
00372 {
00373 return FALSE;
00374 }
00375 if( MTX_isNull( B ) )
00376 {
00377 return FALSE;
00378 }
00379
00380 return( A->nrows == B->nrows && A->ncols == B->ncols );
00381 }
00382
00383
00384 BOOL MTX_isSquare( const MTX *A )
00385 {
00386 if( MTX_isNull( A ) )
00387 {
00388 return FALSE;
00389 }
00390
00391 return( A->nrows == A->ncols );
00392 }
00393
00394 BOOL MTX_isSameSize( const MTX *A, const MTX *B )
00395 {
00396 return MTX_isConformalForAddition( A, B );
00397 }
00398
00399
00400 BOOL MTX_Init( MTX *M )
00401 {
00402 if( !M )
00403 {
00404 MTX_ERROR_MSG( "Cannot initialize NULL pointer." )
00405 return FALSE;
00406 }
00407
00408 M->ncols = 0;
00409 M->nrows = 0;
00410 M->isReal = TRUE;
00411 M->cplx = NULL;
00412 M->data = NULL;
00413 M->comment = NULL;
00414
00415 return TRUE;
00416 }
00417
00418 BOOL MTX_SetComment( MTX *M, const char *comment )
00419 {
00420 unsigned length;
00421
00422 if( !M )
00423 {
00424 MTX_ERROR_MSG( "Cannot initialize NULL pointer." );
00425 return FALSE;
00426 }
00427
00428 if( !comment )
00429 {
00430 MTX_ERROR_MSG( "if( !comment )" );
00431 return FALSE;
00432 }
00433
00434 if( M->comment )
00435 free( M->comment );
00436
00437 length = (unsigned int)strlen(comment);
00438 if( length == 0 )
00439 {
00440 MTX_ERROR_MSG( "strlen returned 0." );
00441 return FALSE;
00442 }
00443
00444 M->comment = (char*)malloc( (length+1)*sizeof(char) );
00445 if( !M->comment )
00446 {
00447
00448 MTX_ERROR_MSG( "malloc returned NULL." );
00449 return FALSE;
00450 }
00451
00452 #ifndef _CRT_SECURE_NO_DEPRECATE
00453 if( strcpy_s( M->comment, length+1, comment ) != 0 )
00454 {
00455 MTX_ERROR_MSG( "strcpy_s returned 0." );
00456 free(M->comment);
00457 M->comment = NULL;
00458 return FALSE;
00459 }
00460 #else
00461 strcpy( M->comment, comment );
00462 #endif
00463
00464 return TRUE;
00465 }
00466
00467 BOOL MTX_Free( MTX *M )
00468 {
00469 unsigned j = 0;
00470
00471 if( !M )
00472 {
00473 MTX_ERROR_MSG( "Cannot free NULL pointer." );
00474 return FALSE;
00475 }
00476
00477 if( M->isReal )
00478 {
00479 if( M->data == NULL )
00480 {
00481 if( M->comment )
00482 free( M->comment );
00483
00484 M->comment = NULL;
00485 M->nrows = 0;
00486 M->ncols = 0;
00487 return TRUE;
00488 }
00489 }
00490 else
00491 {
00492 if( M->cplx == NULL )
00493 {
00494 if( M->comment )
00495 free( M->comment );
00496
00497 M->comment = NULL;
00498 M->nrows = 0;
00499 M->ncols = 0;
00500 return TRUE;
00501 }
00502 }
00503
00504
00505 if( M->isReal )
00506 {
00507 for( j = 0; j < M->ncols; j++ )
00508 {
00509 free( M->data[j] );
00510 }
00511 }
00512 else
00513 {
00514 for( j = 0; j < M->ncols; j++ )
00515 {
00516 free( M->cplx[j] );
00517 }
00518 }
00519
00520
00521 if( M->isReal )
00522 free( M->data );
00523 else
00524 free( M->cplx );
00525
00526 M->nrows = 0;
00527 M->ncols = 0;
00528 M->isReal = TRUE;
00529 M->cplx = NULL;
00530 M->data = NULL;
00531
00532 if( M->comment )
00533 free( M->comment );
00534 M->comment = NULL;
00535 return TRUE;
00536 }
00537
00538
00539 BOOL MTX_Malloc( MTX *M, const unsigned nrows, const unsigned ncols, const BOOL isReal )
00540 {
00541 return MTX_static_alloc( M, nrows, ncols, FALSE, isReal );
00542 }
00543
00544 BOOL MTX_Calloc( MTX *M, const unsigned nrows, const unsigned ncols, const BOOL isReal )
00545 {
00546 return MTX_static_alloc( M, nrows, ncols, TRUE, isReal );
00547 }
00548
00549 BOOL MTX_static_alloc( MTX *M, const unsigned nrows, const unsigned ncols, const BOOL setToZero, const BOOL isReal )
00550 {
00551 unsigned i = 0;
00552 unsigned j = 0;
00553
00554
00555 if( nrows == 0 || ncols == 0 )
00556 {
00557 MTX_ERROR_MSG( "if( nrows == 0 || ncols == 0 )" );
00558 return FALSE;
00559 }
00560 if( !M )
00561 {
00562 MTX_ERROR_MSG( "Cannot set a NULL pointer." );
00563 return FALSE;
00564 }
00565
00566
00567 if( M->isReal == isReal )
00568 {
00569 if( M->nrows > 0 && M->ncols > 0 )
00570 {
00571 if( M->nrows == nrows && M->ncols == ncols )
00572 {
00573
00574 if( setToZero )
00575 {
00576 if( !MTX_Zero( M ) )
00577 {
00578 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
00579 return FALSE;
00580 }
00581 return TRUE;
00582 }
00583 else
00584 {
00585 return TRUE;
00586 }
00587 }
00588 else if( M->nrows == nrows && M->ncols < ncols )
00589 {
00590 if( setToZero )
00591 {
00592 if( !MTX_Zero( M ) )
00593 {
00594 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
00595 return FALSE;
00596 }
00597 }
00598 if( !MTX_AddZeroValuedColumns( M, ncols-M->ncols ) )
00599 {
00600 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
00601 return FALSE;
00602 }
00603 return TRUE;
00604 }
00605 else if( M->nrows == nrows && M->ncols > ncols )
00606 {
00607 if( MTX_RemoveColumnsAfterIndex( M, ncols-1 ) == FALSE )
00608 {
00609 MTX_ERROR_MSG( "MTX_RemoveColumnsAfterIndex returned FALSE." );
00610 return FALSE;
00611 }
00612 if( setToZero )
00613 {
00614 if( !MTX_Zero( M ) )
00615 {
00616 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
00617 return FALSE;
00618 }
00619 }
00620 return TRUE;
00621 }
00622 }
00623 }
00624
00625
00626 MTX_Free( M );
00627
00628 M->isReal = isReal;
00629 M->nrows = nrows;
00630 M->ncols = 0;
00631
00632
00633 if( isReal )
00634 {
00635 M->data = (double**)malloc( ncols*sizeof(double*) );
00636 if( !M->data )
00637 {
00638 MTX_ERROR_MSG( "malloc returned NULL." );
00639 return FALSE;
00640 }
00641 }
00642 else
00643 {
00644 M->cplx = (stComplex**)malloc( ncols*sizeof(stComplex*) );
00645 if( !M->cplx )
00646 {
00647 MTX_ERROR_MSG( "malloc returned NULL." );
00648 return FALSE;
00649 }
00650 }
00651
00652
00653
00654 if( isReal )
00655 {
00656 for( j = 0; j < ncols; j++ )
00657 {
00658 if( setToZero )
00659 M->data[j] = (double*)calloc( nrows, sizeof(double) );
00660 else
00661 M->data[j] = (double*)malloc( nrows*sizeof(double) );
00662 if( !M->data[j] )
00663 {
00664
00665 MTX_ERROR_MSG( "malloc or calloc returned NULL." );
00666 MTX_Free( M );
00667 return FALSE;
00668 }
00669 M->ncols++;
00670 }
00671 }
00672 else
00673 {
00674 for( j = 0; j < ncols; j++ )
00675 {
00676 M->cplx[j] = (stComplex*)malloc( nrows*sizeof(stComplex) );
00677 if( !M->cplx[j] )
00678 {
00679
00680 MTX_ERROR_MSG( "malloc returned NULL." );
00681 MTX_Free( M );
00682 return FALSE;
00683 }
00684 if( setToZero )
00685 {
00686 for( i = 0; i < nrows; i++ )
00687 {
00688 M->cplx[j][i].re = 0.0;
00689 M->cplx[j][i].im = 0.0;
00690 }
00691 }
00692 M->ncols++;
00693 }
00694 }
00695
00696 return TRUE;
00697 }
00698
00699
00700 BOOL MTX_SetValue( MTX *M, const unsigned row, const unsigned col, const double value )
00701 {
00702 if( MTX_isNull( M ) )
00703 {
00704 MTX_ERROR_MSG( "NULL Matrix" );
00705 return FALSE;
00706 }
00707
00708 if( row >= M->nrows )
00709 {
00710 MTX_ERROR_MSG( "if( row >= M->nrows )" );
00711 return FALSE;
00712 }
00713
00714 if( col >= M->ncols )
00715 {
00716 MTX_ERROR_MSG( "if( col >= M->ncols )" );
00717 return FALSE;
00718 }
00719
00720 if( M->isReal )
00721 {
00722 M->data[col][row] = value;
00723 }
00724 else
00725 {
00726 M->cplx[col][row].re = value;
00727 M->cplx[col][row].im = 0.0;
00728 }
00729
00730 return TRUE;
00731 }
00732
00733
00734 BOOL MTX_SetComplexValue( MTX *M, const unsigned row, const unsigned col, const double re, const double im )
00735 {
00736 if( MTX_isNull( M ) )
00737 {
00738 MTX_ERROR_MSG( "NULL Matrix" );
00739 return FALSE;
00740 }
00741
00742 if( row >= M->nrows )
00743 {
00744 MTX_ERROR_MSG( "if( row >= M->nrows )" );
00745 return FALSE;
00746 }
00747
00748 if( col >= M->ncols )
00749 {
00750 MTX_ERROR_MSG( "if( col >= M->ncols )" );
00751 return FALSE;
00752 }
00753
00754 if( M->isReal && im != 0.0 )
00755 {
00756 if( !MTX_ConvertRealToComplex( M ) )
00757 {
00758 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
00759 return FALSE;
00760 }
00761 }
00762
00763 if( M->isReal )
00764 {
00765
00766 M->data[col][row] = re;
00767 }
00768 else
00769 {
00770 M->cplx[col][row].re = re;
00771 M->cplx[col][row].im = im;
00772 }
00773
00774 return TRUE;
00775 }
00776
00777
00778
00779 BOOL MTX_Complex( MTX *M, const MTX *Re, const MTX *Im )
00780 {
00781 unsigned i = 0;
00782 unsigned j = 0;
00783
00784 if( MTX_isNull( Re ) )
00785 {
00786 MTX_ERROR_MSG( "NULL Matrix" );
00787 return FALSE;
00788 }
00789 if( MTX_isNull( Im ) )
00790 {
00791 MTX_ERROR_MSG( "NULL Matrix" );
00792 return FALSE;
00793 }
00794 if( !MTX_isSameSize( Re, Im ) )
00795 {
00796 MTX_ERROR_MSG( "MTX_isSameSize returned FALSE." );
00797 return FALSE;
00798 }
00799
00800 if( !Re->isReal )
00801 {
00802 MTX_ERROR_MSG( "if( !Re->isReal )" );
00803 return FALSE;
00804 }
00805 if( !Im->isReal )
00806 {
00807 MTX_ERROR_MSG( "if( !Im->isReal )" );
00808 return FALSE;
00809 }
00810
00811 if( M->isReal )
00812 {
00813 if( !MTX_Malloc( M, Re->nrows, Re->ncols, FALSE ) )
00814 {
00815 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
00816 return FALSE;
00817 }
00818 }
00819 else
00820 {
00821 if( !MTX_Resize( M, Re->nrows, Re->ncols, FALSE ) )
00822 {
00823 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
00824 return FALSE;
00825 }
00826 }
00827
00828 for( j = 0; j < M->ncols; j++ )
00829 {
00830 for( i = 0; i < M->nrows; i++ )
00831 {
00832 M->cplx[j][i].re = Re->data[j][i];
00833 M->cplx[j][i].im = Im->data[j][i];
00834 }
00835 }
00836 return TRUE;
00837 }
00838
00839
00840
00841
00842 BOOL MTX_SetComplexColumn( MTX *M, const unsigned col, const MTX *Re, const MTX *Im )
00843 {
00844 unsigned i = 0;
00845
00846
00847 if( M->isReal )
00848 {
00849 MTX_ERROR_MSG( "if( M->isReal )" );
00850 return FALSE;
00851 }
00852
00853 if( MTX_isNull( Re ) )
00854 {
00855 MTX_ERROR_MSG( "NULL Matrix" );
00856 return FALSE;
00857 }
00858 if( MTX_isNull( Im ) )
00859 {
00860 MTX_ERROR_MSG( "NULL Matrix" );
00861 return FALSE;
00862 }
00863 if( Re->ncols != 1 )
00864 {
00865 MTX_ERROR_MSG( "if( Re->ncols != 1 )" );
00866 return FALSE;
00867 }
00868 if( !MTX_isSameSize( Re, Im ) )
00869 {
00870 MTX_ERROR_MSG( "MTX_isSameSize returned FALSE." );
00871 return FALSE;
00872 }
00873
00874 if( !Re->isReal )
00875 {
00876 MTX_ERROR_MSG( "if( !Re->isReal )" );
00877 return FALSE;
00878 }
00879 if( !Im->isReal )
00880 {
00881 MTX_ERROR_MSG( "if( !Im->isReal )" );
00882 return FALSE;
00883 }
00884
00885
00886 if( M->nrows != Re->nrows )
00887 {
00888 MTX_ERROR_MSG( "if( M->nrows != Re->nrows )" );
00889 return FALSE;
00890 }
00891 if( col >= M->ncols )
00892 {
00893 MTX_ERROR_MSG( "if( col >= M->ncols )" );
00894 return FALSE;
00895 }
00896
00897 for( i = 0; i < M->nrows; i++ )
00898 {
00899 M->cplx[col][i].re = Re->data[0][i];
00900 M->cplx[col][i].im = Im->data[0][i];
00901 }
00902 return TRUE;
00903 }
00904
00905
00906 BOOL MTX_ConvertRealToComplex( MTX *M )
00907 {
00908 unsigned i = 0;
00909 unsigned j = 0;
00910 unsigned k = 0;
00911
00912 if( MTX_isNull( M ) )
00913 {
00914 MTX_ERROR_MSG( "NULL Matrix" );
00915 return FALSE;
00916 }
00917
00918 if( !M->isReal )
00919 return TRUE;
00920
00921
00922 M->cplx = (stComplex**)malloc( M->ncols*sizeof(stComplex*) );
00923 if( !M->cplx )
00924 {
00925 MTX_ERROR_MSG( "malloc retuned NULL." );
00926 return FALSE;
00927 }
00928
00929 for( j = 0; j < M->ncols; j++ )
00930 {
00931 M->cplx[j] = (stComplex*)malloc( sizeof(stComplex)*(M->nrows) );
00932 if( !(M->cplx[j]) )
00933 {
00934
00935 for( k = 0; k < j; k++ )
00936 {
00937 free( M->cplx[k] );
00938 }
00939
00940 free( M->cplx );
00941 M->cplx = NULL;
00942 MTX_ERROR_MSG( "malloc retuned NULL." );
00943 return FALSE;
00944 }
00945
00946 for( i = 0; i < M->nrows; i++ )
00947 {
00948 M->cplx[j][i].re = M->data[j][i];
00949 M->cplx[j][i].im = 0.0;
00950 }
00951 }
00952
00953
00954 for( j = 0; j < M->ncols; j++ )
00955 {
00956 free( M->data[j] );
00957 }
00958
00959 free( M->data );
00960 M->data = NULL;
00961 M->isReal = FALSE;
00962
00963
00964 return TRUE;
00965 }
00966
00967
00968 BOOL MTX_ConvertComplexToReal( MTX *M )
00969 {
00970 return MTX_static_ConvertComplexTo( M, TRUE );
00971 }
00972
00973 BOOL MTX_ConvertComplexToImag( MTX *M )
00974 {
00975 return MTX_static_ConvertComplexTo( M, FALSE );
00976 }
00977
00978 BOOL MTX_static_ConvertComplexTo( MTX *M, BOOL useReal )
00979 {
00980 unsigned i = 0;
00981 unsigned j = 0;
00982 unsigned k = 0;
00983
00984 if( MTX_isNull( M ) )
00985 {
00986 MTX_ERROR_MSG( "NULL Matrix" );
00987 return FALSE;
00988 }
00989
00990
00991 if( useReal )
00992 {
00993 if( M->isReal )
00994 return TRUE;
00995 }
00996
00997
00998 if( !useReal && M->isReal )
00999 {
01000 if( !MTX_Zero(M) )
01001 {
01002 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
01003 return FALSE;
01004 }
01005 return TRUE;
01006 }
01007
01008
01009 M->data = (double**)malloc( (M->ncols)*sizeof(double*) );
01010 if( !M->data )
01011 {
01012 MTX_ERROR_MSG( "if( !M->data )" );
01013 return FALSE;
01014 }
01015
01016 for( j = 0; j < M->ncols; j++ )
01017 {
01018 M->data[j] = (double*)malloc( sizeof(double)*(M->nrows) );
01019 if( !(M->data[j]) )
01020 {
01021
01022 for( k = 0; k < j; k++ )
01023 {
01024 free( M->data[k] );
01025 }
01026
01027 free( M->data );
01028 M->data = NULL;
01029 MTX_ERROR_MSG( "malloc returned NULL." );
01030 return FALSE;
01031 }
01032
01033 for( i = 0; i < M->nrows; i++ )
01034 {
01035 if( useReal )
01036 M->data[j][i] = M->cplx[j][i].re;
01037 else
01038 M->data[j][i] = M->cplx[j][i].im;
01039 }
01040 }
01041
01042
01043 for( j = 0; j < M->ncols; j++ )
01044 {
01045 free( M->cplx[j] );
01046 }
01047
01048 free( M->cplx );
01049 M->cplx = NULL;
01050 M->isReal = TRUE;
01051
01052
01053 return TRUE;
01054 }
01055
01056
01057
01058 BOOL MTX_Real( const MTX *M, MTX *Re )
01059 {
01060 unsigned i = 0;
01061 unsigned j = 0;
01062
01063 if( MTX_isNull( M ) )
01064 {
01065 MTX_ERROR_MSG( "NULL Matrix" );
01066 return FALSE;
01067 }
01068
01069 if( M->isReal )
01070 return MTX_Copy( M, Re );
01071
01072 if( !MTX_Malloc( Re, M->nrows, M->ncols, TRUE ) )
01073 {
01074 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
01075 return FALSE;
01076 }
01077
01078 for( j = 0; j < M->ncols; j++ )
01079 {
01080 for( i = 0; i < M->nrows; i++ )
01081 {
01082 Re->data[j][i] = M->cplx[j][i].re;
01083 }
01084 }
01085 return TRUE;
01086 }
01087
01088
01089 BOOL MTX_isReal( MTX *M, BOOL *isReal )
01090 {
01091 if( MTX_isNull( M ) )
01092 {
01093 *isReal = TRUE;
01094 return TRUE;
01095 }
01096
01097 if( M->isReal )
01098 {
01099 *isReal = TRUE;
01100 }
01101 else
01102 {
01103 double maxabs;
01104 MTX imagM;
01105
01106 MTX_Init(&imagM);
01107
01108 if( !MTX_Imag(M,&imagM) )
01109 {
01110 MTX_ERROR_MSG( "MTX_Imag returned FALSE." );
01111 return FALSE;
01112 }
01113
01114 if( !MTX_MaxAbs(&imagM,&maxabs) )
01115 {
01116 MTX_ERROR_MSG( "MTX_MaxAbs returned FALSE." );
01117 return FALSE;
01118 }
01119
01120 if( maxabs == 0.0 )
01121 {
01122 if( !MTX_ConvertComplexToReal(M) )
01123 {
01124 MTX_ERROR_MSG( "MTX_ConvertComplexToReal returned FALSE." );
01125 return FALSE;
01126 }
01127 *isReal = TRUE;
01128 }
01129 else
01130 {
01131 *isReal = FALSE;
01132 }
01133
01134 MTX_Free(&imagM);
01135 }
01136
01137 return TRUE;
01138 }
01139
01140 BOOL MTX_RealColumn( const MTX *M, const unsigned col, MTX *Re )
01141 {
01142 unsigned i = 0;
01143
01144 if( MTX_isNull( M ) )
01145 {
01146 MTX_ERROR_MSG( "NULL Matrix" );
01147 return FALSE;
01148 }
01149
01150 if( col >= M->ncols )
01151 {
01152 MTX_ERROR_MSG( "if( col >= M->ncols )" );
01153 return FALSE;
01154 }
01155
01156 if( M->isReal )
01157 return MTX_CopyColumn( M, col, Re );
01158
01159 if( !MTX_Malloc( Re, M->nrows, 1, TRUE ) )
01160 {
01161 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
01162 return FALSE;
01163 }
01164
01165 for( i = 0; i < M->nrows; i++ )
01166 {
01167 Re->data[0][i] = M->cplx[col][i].re;
01168 }
01169
01170 return TRUE;
01171 }
01172
01173 BOOL MTX_Imag( const MTX *M, MTX *Im )
01174 {
01175 unsigned i = 0;
01176 unsigned j = 0;
01177
01178 if( MTX_isNull( M ) )
01179 {
01180 MTX_ERROR_MSG( "NULL Matrix" );
01181 return FALSE;
01182 }
01183
01184 if( M->isReal )
01185 return MTX_Calloc( Im, M->nrows, M->ncols, TRUE );
01186
01187 if( !MTX_Malloc( Im, M->nrows, M->ncols, TRUE ) )
01188 {
01189 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
01190 return FALSE;
01191 }
01192
01193 for( j = 0; j < M->ncols; j++ )
01194 {
01195 for( i = 0; i < M->nrows; i++ )
01196 {
01197 Im->data[j][i] = M->cplx[j][i].im;
01198 }
01199 }
01200 return TRUE;
01201 }
01202
01203 BOOL MTX_ImagColumn( const MTX *M, const unsigned col, MTX *Im )
01204 {
01205 unsigned i = 0;
01206
01207 if( MTX_isNull( M ) )
01208 {
01209 MTX_ERROR_MSG( "NULL Matrix" );
01210 return FALSE;
01211 }
01212
01213 if( col >= M->ncols )
01214 {
01215 MTX_ERROR_MSG( "if( col >= M->ncols )" );
01216 return FALSE;
01217 }
01218
01219 if( M->isReal )
01220 return MTX_Calloc( Im, M->nrows, 1, TRUE );
01221
01222 if( !MTX_Malloc( Im, M->nrows, 1, TRUE ) )
01223 {
01224 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
01225 return FALSE;
01226 }
01227
01228 for( i = 0; i < M->nrows; i++ )
01229 {
01230 Im->data[0][i] = M->cplx[col][i].im;
01231 }
01232 return TRUE;
01233 }
01234
01235 BOOL MTX_Magnitude( const MTX *M, MTX *Magnitude )
01236 {
01237 unsigned i = 0;
01238 unsigned j = 0;
01239 double re;
01240 double im;
01241
01242 if( MTX_isNull( M ) )
01243 {
01244 MTX_ERROR_MSG( "NULL Matrix" );
01245 return FALSE;
01246 }
01247
01248 if( M->isReal )
01249 {
01250 if( !MTX_Copy( M, Magnitude ) )
01251 {
01252 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
01253 return FALSE;
01254 }
01255 if( !MTX_Abs( Magnitude ) )
01256 {
01257 MTX_ERROR_MSG( "MTX_Abs returned FALSE." );
01258 return FALSE;
01259 }
01260 return TRUE;
01261 }
01262
01263 if( !MTX_Malloc( Magnitude, M->nrows, M->ncols, TRUE ) )
01264 {
01265 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
01266 return FALSE;
01267 }
01268
01269 for( j = 0; j < M->ncols; j++ )
01270 {
01271 for( i = 0; i < M->nrows; i++ )
01272 {
01273 re = M->cplx[j][i].re;
01274 im = M->cplx[j][i].im;
01275 Magnitude->data[j][i] = sqrt( re*re + im*im );
01276 }
01277 }
01278 return TRUE;
01279 }
01280
01281 BOOL MTX_Phase( const MTX *M, MTX *Phase )
01282 {
01283 unsigned i = 0;
01284 unsigned j = 0;
01285
01286 if( MTX_isNull( M ) )
01287 {
01288 MTX_ERROR_MSG( "NULL Matrix" );
01289 return FALSE;
01290 }
01291
01292 if( !MTX_Calloc( Phase, M->nrows, M->ncols, TRUE ) )
01293 {
01294 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
01295 return FALSE;
01296 }
01297
01298 if( M->isReal )
01299 {
01300 for( j = 0; j < M->ncols; j++ )
01301 {
01302 for( i = 0; i < M->nrows; i++ )
01303 {
01304 if( M->data[j][i] < 0.0 )
01305 {
01306 Phase->data[j][i] = PI;
01307 }
01308 else
01309 {
01310 Phase->data[j][i] = 0.0;
01311 }
01312 }
01313 }
01314 return TRUE;
01315 }
01316
01317 for( j = 0; j < M->ncols; j++ )
01318 {
01319 for( i = 0; i < M->nrows; i++ )
01320 {
01321 Phase->data[j][i] = atan2( M->cplx[j][i].im, M->cplx[j][i].re );
01322 }
01323 }
01324 return TRUE;
01325 }
01326
01327
01328 BOOL MTX_Conjugate( MTX *M )
01329 {
01330 unsigned i=0;
01331 unsigned j=0;
01332
01333 if( MTX_isNull( M ) )
01334 {
01335 MTX_ERROR_MSG( "NULL Matrix" );
01336 return FALSE;
01337 }
01338
01339 if( M->isReal )
01340 return TRUE;
01341
01342 for( j = 0; j < M->ncols; j++ )
01343 {
01344 for( i = 0; i < M->nrows; i++ )
01345 {
01346 M->cplx[j][i].im = -M->cplx[j][i].im;
01347 }
01348 }
01349 return TRUE;
01350 }
01351
01352 BOOL MTX_RemoveColumn( MTX *M, const unsigned col )
01353 {
01354 unsigned j = 0;
01355 unsigned k = 0;
01356 double **dptr = NULL;
01357 stComplex **cptr = NULL;
01358
01359 if( MTX_isNull( M ) )
01360 {
01361 MTX_ERROR_MSG( "NULL Matrix" );
01362 return FALSE;
01363 }
01364
01365 if( col >= M->ncols )
01366 {
01367 MTX_ERROR_MSG( "if( col >= M->ncols )" );
01368 return FALSE;
01369 }
01370
01371
01372 if( M->ncols == 1 )
01373 {
01374 return MTX_Free( M );
01375 }
01376
01377
01378 if( M->isReal )
01379 {
01380 dptr = (double**)malloc( (M->ncols-1)*sizeof(double*) );
01381 if( !dptr )
01382 {
01383 MTX_ERROR_MSG( "malloc returned NULL." );
01384 return FALSE;
01385 }
01386 }
01387 else
01388 {
01389 cptr = (stComplex**)malloc( (M->ncols-1)*sizeof(stComplex*) );
01390 if( !cptr )
01391 {
01392 MTX_ERROR_MSG( "malloc returned NULL." );
01393 return FALSE;
01394 }
01395 }
01396
01397
01398
01399 k = 0;
01400 for( j = 0; j < M->ncols; j++ )
01401 {
01402 if( j != col )
01403 {
01404 if( M->isReal )
01405 dptr[k] = M->data[j];
01406 else
01407 cptr[k] = M->cplx[j];
01408 k++;
01409 }
01410 else
01411 {
01412 if( M->isReal )
01413 free( M->data[j] );
01414 else
01415 free( M->cplx[j] );
01416 }
01417 }
01418
01419
01420 if( M->isReal )
01421 {
01422 free( M->data );
01423 M->data = dptr;
01424 }
01425 else
01426 {
01427 free( M->cplx );
01428 M->cplx = cptr;
01429 }
01430 M->ncols--;
01431
01432 return TRUE;
01433 }
01434
01435 BOOL MTX_RemoveColumnsAfterIndex( MTX *dst, const unsigned col )
01436 {
01437 unsigned ncols;
01438 unsigned j = 0;
01439 double **dptr = NULL;
01440 stComplex **cptr = NULL;
01441
01442 if( MTX_isNull( dst ) )
01443 {
01444 MTX_ERROR_MSG( "NULL Matrix" );
01445 return FALSE;
01446 }
01447
01448 if( col >= dst->ncols )
01449 {
01450 MTX_ERROR_MSG( "if( col >= dst->ncols )" );
01451 return FALSE;
01452 }
01453
01454
01455 if( dst->ncols == 1 )
01456 {
01457 return MTX_Free( dst );
01458 }
01459
01460 ncols = col+1;
01461
01462
01463 if( dst->isReal )
01464 {
01465 dptr = (double**)malloc( ncols*sizeof(double*) );
01466 if( !dptr )
01467 {
01468 MTX_ERROR_MSG( "malloc returned NULL." );
01469 return FALSE;
01470 }
01471 }
01472 else
01473 {
01474 cptr = (stComplex**)malloc( ncols*sizeof(stComplex*) );
01475 if( !cptr )
01476 {
01477 MTX_ERROR_MSG( "malloc returned NULL." );
01478 return FALSE;
01479 }
01480 }
01481
01482 for( j = 0; j < dst->ncols; j++ )
01483 {
01484 if( j < ncols )
01485 {
01486 if( dst->isReal )
01487 dptr[j] = dst->data[j];
01488 else
01489 cptr[j] = dst->cplx[j];
01490 }
01491 else
01492 {
01493 if( dst->isReal )
01494 free( dst->data[j] );
01495 else
01496 free( dst->cplx[j] );
01497 }
01498 }
01499
01500
01501 if( dst->isReal )
01502 {
01503 free( dst->data );
01504 dst->data = dptr;
01505 }
01506 else
01507 {
01508 free( dst->cplx );
01509 dst->cplx = cptr;
01510 }
01511 dst->ncols = ncols;
01512
01513 return TRUE;
01514 }
01515
01516
01517 BOOL MTX_InsertColumn( MTX *dst, const MTX *src, const unsigned dst_col, const unsigned src_col )
01518 {
01519 unsigned i = 0;
01520 unsigned j = 0;
01521 unsigned k = 0;
01522 unsigned m = 0;
01523 double **dptr = NULL;
01524 stComplex **cptr = NULL;
01525
01526 if( MTX_isNull( dst ) )
01527 {
01528 MTX_ERROR_MSG( "NULL Matrix" );
01529 return FALSE;
01530 }
01531
01532 if( MTX_isNull( src ) )
01533 {
01534 MTX_ERROR_MSG( "NULL Matrix" );
01535 return FALSE;
01536 }
01537
01538 if( dst->nrows != src->nrows )
01539 {
01540 MTX_ERROR_MSG( "if( dst->nrows != src->nrows )" );
01541 return FALSE;
01542 }
01543
01544
01545 if( dst_col > dst->ncols )
01546 {
01547 MTX_ERROR_MSG( "if( dst_col > dst->ncols )" );
01548 return FALSE;
01549 }
01550
01551 if( src_col >= src->ncols )
01552 {
01553 MTX_ERROR_MSG( "if( src_col >= src->ncols )" );
01554 return FALSE;
01555 }
01556
01557 if( !src->isReal && dst->isReal )
01558 {
01559
01560 if( !MTX_ConvertRealToComplex( dst ) )
01561 {
01562 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
01563 return FALSE;
01564 }
01565 }
01566
01567
01568 if( dst->isReal )
01569 {
01570 dptr = (double**)malloc( (dst->ncols+1)*sizeof(double*) );
01571 if( !dptr )
01572 {
01573 MTX_ERROR_MSG( "malloc returned NULL." );
01574 return FALSE;
01575 }
01576 }
01577 else
01578 {
01579 cptr = (stComplex**)malloc( (dst->ncols+1)*sizeof(stComplex*) );
01580 if( !cptr )
01581 {
01582 MTX_ERROR_MSG( "malloc returned NULL." );
01583 return FALSE;
01584 }
01585 }
01586
01587
01588
01589 k = 0;
01590 for( j = 0; j <= dst->ncols; j++ )
01591 {
01592 if( j == dst_col )
01593 {
01594
01595 if( dst->isReal )
01596 dptr[k] = (double*)malloc( dst->nrows*sizeof(double) );
01597 else
01598 cptr[k] = (stComplex*)malloc( dst->nrows*sizeof(stComplex) );
01599 if( dst->isReal )
01600 {
01601 if( !dptr[k] )
01602 {
01603
01604 for( m = 0; m < k; m++ )
01605 {
01606 free( dptr[m] );
01607 }
01608
01609 MTX_ERROR_MSG( "malloc returned NULL." );
01610 free( dptr );
01611 return FALSE;
01612 }
01613 }
01614 else
01615 {
01616 if( !cptr[k] )
01617 {
01618
01619 for( m = 0; m < k; m++ )
01620 {
01621 free( cptr[m] );
01622 }
01623 MTX_ERROR_MSG( "malloc returned NULL." );
01624 free( cptr );
01625 return FALSE;
01626 }
01627 }
01628
01629
01630 for( i = 0; i < dst->nrows; i++ )
01631 {
01632 if( dst->isReal )
01633 {
01634 dptr[k][i] = src->data[src_col][i];
01635 }
01636 else
01637 {
01638 if( src->isReal )
01639 {
01640 cptr[k][i].re = src->data[src_col][i];
01641 cptr[k][i].im = 0;
01642 }
01643 else
01644 {
01645 cptr[k][i] = src->cplx[src_col][i];
01646 }
01647 }
01648 }
01649
01650
01651 if( j != dst->ncols )
01652 {
01653 k++;
01654 if( dst->isReal )
01655 dptr[k] = dst->data[j];
01656 else
01657 cptr[k] = dst->cplx[j];
01658 }
01659 }
01660 else
01661 {
01662 if( j != dst->ncols )
01663 {
01664 if( dst->isReal )
01665 dptr[k] = dst->data[j];
01666 else
01667 cptr[k] = dst->cplx[j];
01668 }
01669 }
01670 k++;
01671 }
01672
01673
01674 if( dst->isReal )
01675 {
01676 free( dst->data );
01677 dst->data = dptr;
01678 }
01679 else
01680 {
01681 free( dst->cplx );
01682 dst->cplx = cptr;
01683 }
01684 dst->ncols++;
01685
01686 return TRUE;
01687 }
01688
01689 BOOL MTX_AddColumn( MTX *dst, const MTX *src, const unsigned src_col )
01690 {
01691 return MTX_InsertColumn( dst, src, dst->ncols, src_col );
01692 }
01693
01694 BOOL MTX_Concatonate( MTX *dst, const MTX *src )
01695 {
01696 unsigned i = 0;
01697 unsigned j = 0;
01698 unsigned ncols;
01699 unsigned m = 0;
01700 double **dptr = NULL;
01701 stComplex **cptr = NULL;
01702
01703 if( dst == NULL )
01704 {
01705 MTX_ERROR_MSG( "dst is a NULL Matrix" );
01706 return FALSE;
01707 }
01708
01709 if( MTX_isNull( src ) )
01710 {
01711 MTX_ERROR_MSG( "NULL Matrix" );
01712 return FALSE;
01713 }
01714
01715 if( dst->nrows == 0 && dst->ncols == 0 )
01716 {
01717 return MTX_Copy( src, dst );
01718 }
01719 else if( dst->nrows != src->nrows )
01720 {
01721 MTX_ERROR_MSG( "if( dst->nrows != src->nrows )" );
01722 return FALSE;
01723 }
01724
01725 ncols = dst->ncols+src->ncols;
01726
01727 if( dst->isReal && !src->isReal )
01728 {
01729
01730 if( !MTX_ConvertRealToComplex( dst ) )
01731 {
01732 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
01733 return FALSE;
01734 }
01735 }
01736
01737
01738 if( dst->isReal )
01739 {
01740 dptr = (double**)malloc( ncols*sizeof(double*) );
01741 if( !dptr )
01742 {
01743 MTX_ERROR_MSG( "malloc returned NULL." );
01744 return FALSE;
01745 }
01746 }
01747 else
01748 {
01749 cptr = (stComplex**)malloc( ncols*sizeof(stComplex*) );
01750 if( !cptr )
01751 {
01752 MTX_ERROR_MSG( "malloc returned NULL." );
01753 return FALSE;
01754 }
01755 }
01756
01757 for( j = 0; j < ncols; j++ )
01758 {
01759 if( j < dst->ncols )
01760 {
01761
01762 if( dst->isReal )
01763 dptr[j] = dst->data[j];
01764 else
01765 cptr[j] = dst->cplx[j];
01766 }
01767 else
01768 {
01769
01770 if( dst->isReal )
01771 dptr[j] = (double*)malloc( dst->nrows*sizeof(double) );
01772 else
01773 cptr[j] = (stComplex*)malloc( dst->nrows*sizeof(stComplex) );
01774 if( dst->isReal )
01775 {
01776 if( !(dptr[j]) )
01777 {
01778
01779 for( m = 0; m < j; m++ )
01780 {
01781 free( dptr[m] );
01782 }
01783
01784 MTX_ERROR_MSG( "malloc returned NULL." );
01785 free( dptr );
01786 return FALSE;
01787 }
01788 }
01789 else
01790 {
01791 if( !(cptr[j]) )
01792 {
01793
01794 for( m = 0; m < j; m++ )
01795 {
01796 free( cptr[m] );
01797 }
01798 free( cptr );
01799 MTX_ERROR_MSG( "malloc returned NULL." );
01800 return FALSE;
01801 }
01802 }
01803
01804 for( i = 0; i < dst->nrows; i++ )
01805 {
01806 if( dst->isReal )
01807 {
01808 dptr[j][i] = src->data[j-dst->ncols][i];
01809 }
01810 else
01811 {
01812 if( src->isReal )
01813 {
01814 cptr[j][i].re = src->data[j-dst->ncols][i];
01815 cptr[j][i].im = 0;
01816 }
01817 else
01818 {
01819 cptr[j][i] = src->cplx[j-dst->ncols][i];
01820 }
01821 }
01822 }
01823 }
01824 }
01825
01826
01827 if( dst->isReal )
01828 {
01829 free( dst->data );
01830 dst->data = dptr;
01831 }
01832 else
01833 {
01834 free( dst->cplx );
01835 dst->cplx = cptr;
01836 }
01837 dst->ncols = ncols;
01838
01839 return TRUE;
01840 }
01841
01842
01843
01844
01845 BOOL MTX_AddZeroValuedColumns( MTX *dst, const unsigned nr_new_cols )
01846 {
01847 unsigned j = 0;
01848 unsigned ncols;
01849 unsigned m = 0;
01850 double **dptr = NULL;
01851 stComplex **cptr = NULL;
01852
01853 if( MTX_isNull( dst ) )
01854 {
01855 MTX_ERROR_MSG( "NULL Matrix" );
01856 return FALSE;
01857 }
01858
01859 ncols = dst->ncols + nr_new_cols;
01860
01861
01862 if( dst->isReal )
01863 {
01864 dptr = (double**)malloc( ncols*sizeof(double*) );
01865 if( !dptr )
01866 {
01867 MTX_ERROR_MSG( "malloc returned NULL." );
01868 return FALSE;
01869 }
01870 }
01871 else
01872 {
01873 cptr = (stComplex**)malloc( ncols*sizeof(stComplex*) );
01874 if( !cptr )
01875 {
01876 MTX_ERROR_MSG( "malloc returned NULL." );
01877 return FALSE;
01878 }
01879 }
01880
01881 for( j = 0; j < ncols; j++ )
01882 {
01883 if( j < dst->ncols )
01884 {
01885
01886 if( dst->isReal )
01887 dptr[j] = dst->data[j];
01888 else
01889 cptr[j] = dst->cplx[j];
01890 }
01891 else
01892 {
01893
01894 if( dst->isReal )
01895 {
01896 dptr[j] = (double*)calloc( dst->nrows, sizeof(double) );
01897 }
01898 else
01899 {
01900 cptr[j] = (stComplex*)calloc( dst->nrows, sizeof(stComplex) );
01901 }
01902 if( dst->isReal )
01903 {
01904 if( !(dptr[j]) )
01905 {
01906
01907 for( m = 0; m < j; m++ )
01908 {
01909 free( dptr[m] );
01910 }
01911 free( dptr );
01912
01913 MTX_ERROR_MSG( "calloc returned NULL." );
01914 return FALSE;
01915 }
01916 }
01917 else
01918 {
01919 if( !(cptr[j]) )
01920 {
01921
01922 for( m = 0; m < j; m++ )
01923 {
01924 free( cptr[m] );
01925 }
01926 free( cptr );
01927
01928 MTX_ERROR_MSG( "calloc returned NULL." );
01929 return FALSE;
01930 }
01931 }
01932
01933 }
01934 }
01935
01936
01937 if( dst->isReal )
01938 {
01939 free( dst->data );
01940 dst->data = dptr;
01941 }
01942 else
01943 {
01944 free( dst->cplx );
01945 dst->cplx = cptr;
01946 }
01947 dst->ncols = ncols;
01948
01949 return TRUE;
01950 }
01951
01952 BOOL MTX_Redim( MTX *dst, const unsigned nrows, const unsigned ncols )
01953 {
01954 unsigned j = 0;
01955 unsigned nc;
01956 unsigned nr;
01957 MTX copy;
01958 const BOOL isReal = dst->isReal;
01959
01960 MTX_Init( © );
01961
01962 if( !dst )
01963 {
01964 MTX_ERROR_MSG( "dst is a NULL pointer." );
01965 return FALSE;
01966 }
01967
01968 if( nrows == 0 || ncols == 0 )
01969 {
01970 MTX_ERROR_MSG( "if( nrows == 0 || ncols == 0 )" );
01971 return FALSE;
01972 }
01973
01974
01975 if( dst->ncols == 0 && dst->nrows == 0 )
01976 return MTX_Calloc( dst, nrows, ncols, dst->isReal );
01977
01978
01979
01980 if( dst->nrows == nrows && dst->ncols == ncols )
01981 return TRUE;
01982
01983
01984 if( dst->nrows == nrows )
01985 {
01986 if( ncols < dst->ncols )
01987 {
01988 if( MTX_RemoveColumnsAfterIndex( dst, ncols-1 ) == FALSE )
01989 {
01990 MTX_ERROR_MSG( "MTX_RemoveColumnsAfterIndex returned FALSE." );
01991 return FALSE;
01992 }
01993
01994 return TRUE;
01995 }
01996 else
01997 {
01998
01999 if( !MTX_AddZeroValuedColumns( dst, ncols-dst->ncols ) )
02000 {
02001 MTX_ERROR_MSG( "MTX_AddZeroValuedColumns returned FALSE." );
02002 return FALSE;
02003 }
02004 return TRUE;
02005 }
02006 }
02007
02008
02009 if( !MTX_Malloc( ©, dst->nrows, dst->ncols, isReal ) )
02010 {
02011 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
02012 return FALSE;
02013 }
02014 if( !MTX_Copy( dst, © ) )
02015 {
02016 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
02017 MTX_Free( © );
02018 return FALSE;
02019 }
02020
02021
02022 MTX_Free( dst );
02023
02024 if( !MTX_Calloc( dst, nrows, ncols, isReal ) )
02025 {
02026 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
02027 MTX_Free( © );
02028 return FALSE;
02029 }
02030
02031
02032 if( dst->ncols < copy.ncols )
02033 nc = dst->ncols;
02034 else
02035 nc = copy.ncols;
02036
02037 if( dst->nrows < copy.nrows )
02038 nr = dst->nrows;
02039 else
02040 nr = copy.nrows;
02041
02042 if( isReal )
02043 {
02044 for( j = 0; j < nc; j++ )
02045 {
02046 memcpy( dst->data[j], copy.data[j], sizeof(double)*nr );
02047 }
02048 }
02049 else
02050 {
02051 for( j = 0; j < nc; j++ )
02052 {
02053 memcpy( dst->cplx[j], copy.cplx[j], sizeof(stComplex)*nr );
02054 }
02055 }
02056 MTX_Free( © );
02057 return TRUE;
02058 }
02059
02060 BOOL MTX_Resize( MTX *dst, const unsigned nrows, const unsigned ncols, const BOOL isReal )
02061 {
02062 if( !dst )
02063 {
02064 MTX_ERROR_MSG( "dst is a NULL pointer." );
02065 return FALSE;
02066 }
02067
02068 if( nrows == 0 || ncols == 0 )
02069 {
02070 MTX_ERROR_MSG( "if( nrows == 0 || ncols == 0 )" );
02071 return FALSE;
02072 }
02073
02074
02075
02076 if( !MTX_Calloc( dst, nrows, ncols, isReal ) )
02077 {
02078 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
02079 return FALSE;
02080 }
02081
02082 return TRUE;
02083 }
02084
02085 BOOL MTX_Copy( const MTX *src, MTX *dst )
02086 {
02087 unsigned j = 0;
02088
02089 if( MTX_isNull( src ) )
02090 {
02091 MTX_ERROR_MSG( "NULL Matrix" );
02092 return FALSE;
02093 }
02094 if( !dst )
02095 {
02096 MTX_ERROR_MSG( "dst is a NULL pointer." );
02097 return FALSE;
02098 }
02099
02100
02101 if( dst->isReal != src->isReal )
02102 {
02103 if( !MTX_Resize( dst, src->nrows, src->ncols, src->isReal ) )
02104 {
02105 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02106 return FALSE;
02107 }
02108 }
02109
02110 if( !MTX_isSameSize( src, dst ) )
02111 {
02112 if( !MTX_Resize( dst, src->nrows, src->ncols, src->isReal ) )
02113 {
02114 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02115 return FALSE;
02116 }
02117 }
02118
02119
02120 if( src->isReal )
02121 {
02122 for( j = 0; j < dst->ncols; j++ )
02123 {
02124 memcpy( dst->data[j], src->data[j], sizeof(double)*(dst->nrows) );
02125 }
02126 }
02127 else
02128 {
02129 for( j = 0; j < dst->ncols; j++ )
02130 {
02131 memcpy( dst->cplx[j], src->cplx[j], sizeof(stComplex)*(dst->nrows) );
02132 }
02133 }
02134
02135 return TRUE;
02136 }
02137
02138 BOOL MTX_CopyIntoColumnWiseVector( const MTX *src, MTX *dst )
02139 {
02140 unsigned j = 0;
02141
02142 if( MTX_isNull( src ) )
02143 {
02144 MTX_ERROR_MSG( "NULL Matrix" );
02145 return FALSE;
02146 }
02147 if( !dst )
02148 {
02149 MTX_ERROR_MSG( "dst is a NULL pointer." );
02150 return FALSE;
02151 }
02152
02153
02154 if( dst->isReal != src->isReal )
02155 {
02156 if( !MTX_Resize( dst, src->nrows*src->ncols, 1, src->isReal ) )
02157 {
02158 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02159 return FALSE;
02160 }
02161 }
02162
02163 if( dst->nrows != src->nrows*src->ncols )
02164 {
02165 if( !MTX_Resize( dst, src->nrows*src->ncols, 1, src->isReal ) )
02166 {
02167 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02168 return FALSE;
02169 }
02170 }
02171
02172 if( src->isReal )
02173 {
02174 for( j = 0; j < src->ncols; j++ )
02175 {
02176 memcpy( &(dst->data[0][j*src->nrows]), src->data[j], sizeof(double)*src->nrows );
02177 }
02178 }
02179 else
02180 {
02181 for( j = 0; j < src->ncols; j++ )
02182 {
02183 memcpy( &(dst->cplx[0][j*src->nrows]), src->cplx[j], sizeof(stComplex)*src->nrows );
02184 }
02185 }
02186
02187 return TRUE;
02188 }
02189
02190
02191 BOOL MTX_SetFromStaticMatrix( MTX *dst, const double mat[], const unsigned nrows, const unsigned ncols )
02192 {
02193 unsigned i = 0;
02194 unsigned j = 0;
02195
02196 if( !dst )
02197 {
02198 MTX_ERROR_MSG( "dst is a NULL pointer." );
02199 return FALSE;
02200 }
02201
02202 if( !mat )
02203 {
02204 MTX_ERROR_MSG( "mat is a NULL pointer." );
02205 return FALSE;
02206 }
02207
02208 if( dst->nrows != nrows || dst->ncols != ncols )
02209 {
02210 if( !MTX_Resize( dst, nrows, ncols, TRUE ) )
02211 {
02212 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02213 return FALSE;
02214 }
02215 }
02216
02217 for( j = 0; j < ncols; j++ )
02218 for( i = 0; i < nrows; i++ )
02219 dst->data[j][i] = mat[i*ncols + j];
02220
02221 return TRUE;
02222 }
02223
02224 BOOL MTX_CopyColumn( const MTX *src, const unsigned col, MTX *dst )
02225 {
02226 if( MTX_isNull( src ) )
02227 {
02228 MTX_ERROR_MSG( "NULL Matrix" );
02229 return FALSE;
02230 }
02231 if( !dst )
02232 {
02233 MTX_ERROR_MSG( "dst is a NULL pointer." );
02234 return FALSE;
02235 }
02236 if( col >= src->ncols )
02237 {
02238 MTX_ERROR_MSG( "if( col >= src->ncols )" );
02239 return FALSE;
02240 }
02241
02242 if( src->isReal != dst->isReal )
02243 {
02244 if( !MTX_Malloc( dst, src->nrows, 1, src->isReal ) )
02245 {
02246 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02247 return FALSE;
02248 }
02249 }
02250 else if( dst->nrows != src->nrows || dst->ncols != 1 )
02251 {
02252 if( !MTX_Malloc( dst, src->nrows, 1, src->isReal ) )
02253 {
02254 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02255 return FALSE;
02256 }
02257 }
02258
02259 if( src->isReal )
02260 {
02261 memcpy( dst->data[0], src->data[col], sizeof(double)*(dst->nrows) );
02262 }
02263 else
02264 {
02265 memcpy( dst->cplx[0], src->cplx[col], sizeof(stComplex)*(dst->nrows) );
02266 }
02267
02268 return TRUE;
02269 }
02270
02271 BOOL MTX_CopyRow( const MTX *src, const unsigned row, MTX *dst )
02272 {
02273 unsigned i = 0;
02274
02275 if( MTX_isNull( src ) )
02276 {
02277 MTX_ERROR_MSG( "NULL Matrix" );
02278 return FALSE;
02279 }
02280 if( !dst )
02281 {
02282 MTX_ERROR_MSG( "dst is a NULL pointer." );
02283 return FALSE;
02284 }
02285 if( row >= src->nrows )
02286 {
02287 MTX_ERROR_MSG( "if( row >= src->nrows )" );
02288 return FALSE;
02289 }
02290
02291 if( dst->nrows != 1 || dst->ncols != src->ncols )
02292 {
02293 if( !MTX_Resize( dst, 1, src->ncols, src->isReal ) )
02294 {
02295 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02296 return FALSE;
02297 }
02298 }
02299
02300 for( i = 0; i < dst->ncols; i++ )
02301 {
02302 if( src->isReal )
02303 dst->data[i][0] = src->data[i][row];
02304 else
02305 dst->cplx[i][0] = src->cplx[i][row];
02306 }
02307
02308 return TRUE;
02309 }
02310
02311 BOOL MTX_CopyRowIntoAColumnMatrix( const MTX *src, const unsigned row, MTX *dst )
02312 {
02313 unsigned i = 0;
02314
02315 if( MTX_isNull( src ) )
02316 {
02317 MTX_ERROR_MSG( "NULL Matrix" );
02318 return FALSE;
02319 }
02320 if( !dst )
02321 {
02322 MTX_ERROR_MSG( "dst is a NULL pointer." );
02323 return FALSE;
02324 }
02325 if( row >= src->nrows )
02326 {
02327 MTX_ERROR_MSG( "if( row >= src->nrows )" );
02328 return FALSE;
02329 }
02330
02331 if( dst->nrows != src->ncols || dst->ncols != 1 )
02332 {
02333 if( !MTX_Resize( dst, src->ncols, 1, src->isReal ) )
02334 {
02335 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02336 return FALSE;
02337 }
02338 }
02339
02340 for( i = 0; i < dst->nrows; i++ )
02341 {
02342 if( src->isReal )
02343 dst->data[0][i] = src->data[i][row];
02344 else
02345 dst->cplx[0][i] = src->cplx[i][row];
02346 }
02347
02348 return TRUE;
02349 }
02350
02351 BOOL MTX_InsertSubMatrix( MTX *dst, const MTX *src, const unsigned dst_row, const unsigned dst_col )
02352 {
02353 unsigned i = 0;
02354 unsigned j = 0;
02355
02356 if( !dst )
02357 {
02358 MTX_ERROR_MSG( "dst is a NULL pointer." );
02359 return FALSE;
02360 }
02361
02362 if( MTX_isNull( src ) )
02363 {
02364 MTX_ERROR_MSG( "NULL Matrix" );
02365 return FALSE;
02366 }
02367
02368
02369 if( dst_row + src->nrows > dst->nrows )
02370 {
02371 MTX_ERROR_MSG( "if( dst_row + src->nrows > dst->nrows )" );
02372 return FALSE;
02373 }
02374 if( dst_col + src->ncols > dst->ncols )
02375 {
02376 MTX_ERROR_MSG( "if( dst_col + src->ncols > dst->ncols )" );
02377 return FALSE;
02378 }
02379
02380 if( !src->isReal && dst->isReal )
02381 {
02382
02383 if( !MTX_ConvertRealToComplex( dst ) )
02384 {
02385 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
02386 return FALSE;
02387 }
02388 }
02389
02390
02391 if( dst->isReal )
02392 {
02393 for( j = 0; j < src->ncols; j++ )
02394 {
02395 memcpy( &(dst->data[dst_col+j][dst_row]), src->data[j], sizeof(double)*src->nrows );
02396 }
02397 }
02398 else
02399 {
02400 if( src->isReal )
02401 {
02402 for( j = 0; j < src->ncols; j++ )
02403 {
02404 for( i = 0; i < src->nrows; i++ )
02405 {
02406 dst->cplx[dst_col+j][dst_row+i].re = src->data[j][i];
02407 dst->cplx[dst_col+j][dst_row+i].im = 0.0;
02408 }
02409 }
02410 }
02411 else
02412 {
02413 for( j = 0; j < src->ncols; j++ )
02414 {
02415 memcpy( &(dst->cplx[dst_col+j][dst_row]), src->cplx[j], sizeof(stComplex)*src->nrows );
02416 }
02417 }
02418 }
02419 return TRUE;
02420 }
02421
02422 BOOL MTX_ExtractSubMatrix(
02423 const MTX* src,
02424 MTX* dst,
02425 const unsigned from_row,
02426 const unsigned from_col,
02427 const unsigned to_row,
02428 const unsigned to_col
02429 )
02430 {
02431 unsigned i;
02432 unsigned j;
02433 unsigned k;
02434 unsigned m;
02435
02436 if( src == NULL )
02437 {
02438 MTX_ERROR_MSG( "NULL source matrix" );
02439 return FALSE;
02440 }
02441 if( dst == NULL )
02442 {
02443 MTX_ERROR_MSG( "NULL destination matrix" );
02444 return FALSE;
02445 }
02446 if( MTX_isNull( src ) )
02447 {
02448 MTX_ERROR_MSG( "NULL source matrix" );
02449 return FALSE;
02450 }
02451
02452 if( to_row - from_row < 0 )
02453 {
02454 MTX_ERROR_MSG( "The destination matrix has invalid dimension. to_row - from_row < 0" );
02455 return FALSE;
02456 }
02457 if( to_col - from_col < 0 )
02458 {
02459 MTX_ERROR_MSG( "The destination matrix has invalid dimension. to_col - from_col < 0" );
02460 return FALSE;
02461 }
02462
02463 if( from_row >= src->nrows )
02464 {
02465 MTX_ERROR_MSG( "from_row > number of source rows" );
02466 return FALSE;
02467 }
02468 if( from_col >= src->ncols )
02469 {
02470 MTX_ERROR_MSG( "from_col > number of source columns" );
02471 return FALSE;
02472 }
02473 if( to_row >= src->nrows )
02474 {
02475 MTX_ERROR_MSG( "to_row > number of source rows" );
02476 return FALSE;
02477 }
02478 if( to_col >= src->ncols )
02479 {
02480 MTX_ERROR_MSG( "to_col > number of source columns" );
02481 return FALSE;
02482 }
02483
02484 if( !MTX_Malloc( dst, to_row-from_row+1, to_col-from_col+1, src->isReal ) )
02485 {
02486 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
02487 return FALSE;
02488 }
02489
02490 m = 0;
02491 for( j = from_col; j <= to_col; j++ )
02492 {
02493 k = 0;
02494 for( i = from_row; i <= to_row; i++ )
02495 {
02496 if( src->isReal )
02497 {
02498 dst->data[m][k] = src->data[j][i];
02499 }
02500 else
02501 {
02502 dst->cplx[m][k].re = src->cplx[j][i].re;
02503 dst->cplx[m][k].im = src->cplx[j][i].im;
02504 }
02505 k++;
02506 }
02507 m++;
02508 }
02509
02510 return TRUE;
02511 }
02512
02513 BOOL MTX_Zero( MTX *dst )
02514 {
02515 unsigned j = 0;
02516
02517 if( MTX_isNull( dst ) )
02518 {
02519 MTX_ERROR_MSG( "NULL Matrix" );
02520 return FALSE;
02521 }
02522
02523 for( j = 0; j < dst->ncols; j++ )
02524 {
02525 if( dst->isReal )
02526 {
02527 memset( dst->data[j], 0, sizeof(double)*dst->nrows );
02528 }
02529 else
02530 {
02531 memset( dst->cplx[j], 0, sizeof(stComplex)*dst->nrows );
02532 }
02533 }
02534 return TRUE;
02535 }
02536
02537 BOOL MTX_ZeroColumn( MTX *dst, const unsigned col )
02538 {
02539 if( MTX_isNull( dst ) )
02540 {
02541 MTX_ERROR_MSG( "NULL Matrix" );
02542 return FALSE;
02543 }
02544
02545 if( col >= dst->ncols )
02546 {
02547 MTX_ERROR_MSG( "if( col >= dst->ncols )" );
02548 return FALSE;
02549 }
02550
02551 if( dst->isReal )
02552 {
02553 memset( dst->data[col], 0, sizeof(double)*dst->nrows );
02554 }
02555 else
02556 {
02557 memset( dst->cplx[col], 0, sizeof(stComplex)*dst->nrows );
02558 }
02559
02560 return TRUE;
02561 }
02562
02563 BOOL MTX_ZeroRow( MTX *dst, const unsigned row )
02564 {
02565 return MTX_FillRow( dst, row, 0.0 );
02566 }
02567
02568 BOOL MTX_Fill( MTX *dst, const double value )
02569 {
02570 unsigned i = 0;
02571 unsigned j = 0;
02572
02573 if( MTX_isNull( dst ) )
02574 {
02575 MTX_ERROR_MSG( "NULL Matrix" );
02576 return FALSE;
02577 }
02578
02579
02580 if( dst->isReal )
02581 {
02582 j = 0;
02583 for( i = 0; i < dst->nrows; i++ )
02584 {
02585 dst->data[j][i] = value;
02586 }
02587 for( j = 1; j < dst->ncols; j++ )
02588 {
02589 memcpy( dst->data[j], dst->data[j-1], sizeof(double)*dst->nrows );
02590 }
02591 }
02592 else
02593 {
02594 j = 0;
02595 for( i = 0; i < dst->nrows; i++ )
02596 {
02597 dst->cplx[j][i].re = value;
02598 dst->cplx[j][i].im = 0.0;
02599 }
02600 for( j = 1; j < dst->ncols; j++ )
02601 {
02602 memcpy( dst->cplx[j], dst->cplx[j-1], sizeof(stComplex)*dst->nrows );
02603 }
02604 }
02605
02606 return TRUE;
02607 }
02608
02609 BOOL MTX_FillComplex( MTX *dst, const double re, const double im )
02610 {
02611 unsigned i = 0;
02612 unsigned j = 0;
02613
02614 if( MTX_isNull( dst ) )
02615 {
02616 MTX_ERROR_MSG( "NULL Matrix" );
02617 return FALSE;
02618 }
02619
02620 if( dst->isReal )
02621 {
02622 if( !MTX_ConvertRealToComplex( dst ) )
02623 {
02624 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
02625 return FALSE;
02626 }
02627 }
02628
02629 for( j = 0; j < dst->ncols; j++ )
02630 {
02631 if( j == 0 )
02632 {
02633 for( i = 0; i < dst->nrows; i++ )
02634 {
02635 dst->cplx[j][i].re = re;
02636 dst->cplx[j][i].im = im;
02637 }
02638 }
02639 else
02640 {
02641 memcpy( dst->cplx[j], dst->cplx[j-1], sizeof(stComplex)*dst->nrows );
02642 }
02643 }
02644 return TRUE;
02645 }
02646
02647 BOOL MTX_FillColumn( MTX *dst, const unsigned col, const double value )
02648 {
02649 unsigned i = 0;
02650
02651 if( MTX_isNull( dst ) )
02652 {
02653 MTX_ERROR_MSG( "NULL Matrix" );
02654 return FALSE;
02655 }
02656
02657 if( col >= dst->ncols )
02658 {
02659 MTX_ERROR_MSG( "if( col >= dst->ncols )" );
02660 return FALSE;
02661 }
02662
02663 if( dst->isReal )
02664 {
02665 for( i = 0; i < dst->nrows; i++ )
02666 {
02667 dst->data[col][i] = value;
02668 }
02669 }
02670 else
02671 {
02672 for( i = 0; i < dst->nrows; i++ )
02673 {
02674 dst->cplx[col][i].re = value;
02675 dst->cplx[col][i].im = 0;
02676 }
02677 }
02678
02679 return TRUE;
02680 }
02681
02682 BOOL MTX_FillColumnComplex( MTX *dst, const unsigned col, const double re, const double im )
02683 {
02684 unsigned i = 0;
02685
02686 if( MTX_isNull( dst ) )
02687 {
02688 MTX_ERROR_MSG( "NULL Matrix" );
02689 return FALSE;
02690 }
02691
02692 if( col >= dst->ncols )
02693 {
02694 MTX_ERROR_MSG( "if( col >= dst->ncols )" );
02695 return FALSE;
02696 }
02697
02698 if( dst->isReal )
02699 {
02700 if( !MTX_ConvertRealToComplex( dst ) )
02701 {
02702 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
02703 return FALSE;
02704 }
02705 }
02706
02707 for( i = 0; i < dst->nrows; i++ )
02708 {
02709 dst->cplx[col][i].re = re;
02710 dst->cplx[col][i].im = im;
02711 }
02712
02713 return TRUE;
02714 }
02715
02716 BOOL MTX_FillRow( MTX *dst, const unsigned row, const double value )
02717 {
02718 unsigned j = 0;
02719
02720 if( MTX_isNull( dst ) )
02721 {
02722 MTX_ERROR_MSG( "NULL Matrix" );
02723 return FALSE;
02724 }
02725
02726 if( row >= dst->nrows )
02727 {
02728 MTX_ERROR_MSG( "if( row >= dst->nrows )" );
02729 return FALSE;
02730 }
02731
02732 for( j = 0; j < dst->ncols; j++ )
02733 {
02734 if( dst->isReal )
02735 {
02736 dst->data[j][row] = value;
02737 }
02738 else
02739 {
02740 dst->cplx[j][row].re = value;
02741 dst->cplx[j][row].im = value;
02742 }
02743 }
02744
02745 return TRUE;
02746 }
02747
02748 BOOL MTX_FillRowComplex( MTX *dst, const unsigned row, const double re, const double im )
02749 {
02750 unsigned j = 0;
02751
02752 if( MTX_isNull( dst ) )
02753 {
02754 MTX_ERROR_MSG( "NULL Matrix" );
02755 return FALSE;
02756 }
02757
02758 if( row >= dst->nrows )
02759 {
02760 MTX_ERROR_MSG( "if( row >= dst->nrows )" );
02761 return FALSE;
02762 }
02763
02764 if( dst->isReal )
02765 {
02766 if( !MTX_ConvertRealToComplex( dst ) )
02767 {
02768 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
02769 return FALSE;
02770 }
02771 }
02772
02773 for( j = 0; j < dst->ncols; j++ )
02774 {
02775 dst->cplx[j][row].re = re;
02776 dst->cplx[j][row].im = im;
02777 }
02778
02779 return TRUE;
02780 }
02781
02782
02783
02784 BOOL MTX_Identity( MTX *dst )
02785 {
02786 unsigned j = 0;
02787
02788 if( MTX_isNull( dst ) )
02789 {
02790 MTX_ERROR_MSG( "NULL Matrix" );
02791 return FALSE;
02792 }
02793
02794 if( !MTX_isSquare( dst ) )
02795 {
02796 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
02797 return FALSE;
02798 }
02799
02800 if( !dst->isReal )
02801 {
02802 if( !MTX_Calloc( dst, dst->nrows, dst->ncols, TRUE ) )
02803 {
02804 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
02805 return FALSE;
02806 }
02807 }
02808 else
02809 {
02810 if( !MTX_Zero( dst ) )
02811 {
02812 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
02813 return FALSE;
02814 }
02815 }
02816
02817 for( j = 0; j < dst->ncols; j++ )
02818 {
02819 dst->data[j][j] = 1.0;
02820 }
02821 return TRUE;
02822 }
02823
02824 BOOL MTX_ForceSymmetric( MTX *M )
02825 {
02826 unsigned i = 0;
02827 unsigned j = 0;
02828 double tmp = 0.0;
02829 stComplex cplxval;
02830
02831 if( MTX_isNull( M ) )
02832 {
02833 MTX_ERROR_MSG( "NULL Matrix" );
02834 return FALSE;
02835 }
02836 if( !MTX_isSquare( M ) )
02837 {
02838 MTX_ERROR_MSG( "The matrix is not square.");
02839 return FALSE;
02840 }
02841
02842 for( j = 0; j < M->ncols; j++ )
02843 {
02844 for( i = 0; i < M->nrows; i++ )
02845 {
02846 if( i == j )
02847 break;
02848
02849 if( M->isReal )
02850 {
02851 tmp = M->data[j][i] + M->data[i][j];
02852 tmp /= 2.0;
02853 M->data[j][i] = tmp;
02854 M->data[i][j] = tmp;
02855 }
02856 else
02857 {
02858 cplxval.re = M->cplx[j][i].re + M->cplx[i][j].re;
02859 cplxval.im = M->cplx[j][i].im + M->cplx[i][j].im;
02860 cplxval.re /= 2.0;
02861 cplxval.im /= 2.0;
02862
02863 M->cplx[j][i].re = cplxval.re;
02864 M->cplx[j][i].im = cplxval.im;
02865 M->cplx[i][j].re = cplxval.re;
02866 M->cplx[i][j].im = cplxval.im;
02867 }
02868 }
02869 }
02870 return TRUE;
02871 }
02872
02873
02874 BOOL MTX_Transpose( const MTX *src, MTX *dst )
02875 {
02876 unsigned i = 0;
02877 unsigned j = 0;
02878
02879 if( !dst )
02880 {
02881 MTX_ERROR_MSG( "dst is a NULL pointer." );
02882 return FALSE;
02883 }
02884
02885 if( MTX_isNull( src ) )
02886 {
02887 MTX_ERROR_MSG( "NULL Matrix" );
02888 return FALSE;
02889 }
02890
02891
02892 if( dst == src )
02893 {
02894 return MTX_TransposeInplace( dst );
02895 }
02896
02897
02898 if( !src->isReal && dst->isReal )
02899 {
02900 MTX_Free( dst );
02901
02902 if( !MTX_Malloc( dst, src->ncols, src->nrows, src->isReal ) )
02903 {
02904 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
02905 return FALSE;
02906 }
02907 }
02908 else if( src->isReal && !dst->isReal )
02909 {
02910 MTX_Free( dst );
02911
02912 if( !MTX_Malloc( dst, src->ncols, src->nrows, src->isReal ) )
02913 {
02914 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
02915 return FALSE;
02916 }
02917 }
02918
02919
02920
02921 if( dst->nrows != src->ncols || dst->ncols != src->nrows )
02922 {
02923 if( !MTX_Resize( dst, src->ncols, src->nrows, src->isReal ) )
02924 {
02925 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
02926 return FALSE;
02927 }
02928 }
02929
02930 if( dst->isReal )
02931 {
02932 for( j = 0; j < src->ncols; j++ )
02933 {
02934 for( i = 0; i < src->nrows; i++ )
02935 {
02936 dst->data[i][j] = src->data[j][i];
02937 }
02938 }
02939 }
02940 else
02941 {
02942 for( j = 0; j < src->ncols; j++ )
02943 {
02944 for( i = 0; i < src->nrows; i++ )
02945 {
02946 dst->cplx[i][j].re = src->cplx[j][i].re;
02947 dst->cplx[i][j].im = src->cplx[j][i].im;
02948 }
02949 }
02950 }
02951 return TRUE;
02952 }
02953
02954 BOOL MTX_TransposeInplace( MTX *M )
02955 {
02956 unsigned i = 0;
02957 unsigned j = 0;
02958 double tmp = 0.0;
02959 stComplex cplxval;
02960
02961 if( MTX_isNull( M ) )
02962 {
02963 MTX_ERROR_MSG( "NULL Matrix" );
02964 return FALSE;
02965 }
02966
02967
02968 if( MTX_isSquare( M ) )
02969 {
02970 for( j = 0; j < M->ncols; j++ )
02971 {
02972 for( i = 0; i < M->nrows; i++ )
02973 {
02974 if( i == j )
02975 break;
02976
02977 if( M->isReal )
02978 {
02979 tmp = M->data[j][i];
02980 M->data[j][i] = M->data[i][j];
02981 M->data[i][j] = tmp;
02982 }
02983 else
02984 {
02985 cplxval.re = M->cplx[j][i].re;
02986 cplxval.im = M->cplx[j][i].im;
02987 M->cplx[j][i].re = M->cplx[i][j].re;
02988 M->cplx[j][i].im = M->cplx[i][j].im;
02989 M->cplx[i][j].re = cplxval.re;
02990 M->cplx[i][j].im = cplxval.im;
02991 }
02992 }
02993 }
02994 }
02995 else
02996 {
02997 MTX copy;
02998 MTX_Init( © );
02999
03000 if( !MTX_Malloc( ©, M->nrows, M->ncols, M->isReal ) )
03001 {
03002 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
03003 return FALSE;
03004 }
03005 if( !MTX_Copy( M, © ) )
03006 {
03007 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
03008 return FALSE;
03009 }
03010
03011
03012 if( !MTX_Resize( M, copy.ncols, copy.nrows, copy.isReal ) )
03013 {
03014 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
03015 return FALSE;
03016 }
03017
03018 for( j = 0; j < copy.ncols; j++ )
03019 {
03020 for( i = 0; i < copy.nrows; i++ )
03021 {
03022 if( M->isReal )
03023 {
03024 M->data[i][j] = copy.data[j][i];
03025 }
03026 else
03027 {
03028 M->cplx[i][j].re = copy.cplx[j][i].re;
03029 M->cplx[i][j].im = copy.cplx[j][i].im;
03030 }
03031 }
03032 }
03033
03034 MTX_Free( © );
03035 }
03036 return TRUE;
03037 }
03038
03039
03040
03041
03042
03043
03044 BOOL MTX_Round( MTX *M, const unsigned precision )
03045 {
03046 unsigned i = 0;
03047 unsigned j = 0;
03048
03049 if( MTX_isNull( M ) )
03050 {
03051 MTX_ERROR_MSG( "NULL Matrix" );
03052 return FALSE;
03053 }
03054
03055 if( precision > 32 )
03056 return TRUE;
03057
03058 if( precision == 0 )
03059 {
03060 if( M->isReal )
03061 {
03062 for( j = 0; j < M->ncols; j++ )
03063 {
03064 for( i = 0; i < M->nrows; i++ )
03065 {
03066 MTX_static_round_value_to_integer( &(M->data[j][i]) );
03067 }
03068 }
03069 }
03070 else
03071 {
03072 for( j = 0; j < M->ncols; j++ )
03073 {
03074 for( i = 0; i < M->nrows; i++ )
03075 {
03076 MTX_static_round_value_to_integer( &(M->cplx[j][i].re) );
03077 MTX_static_round_value_to_integer( &(M->cplx[j][i].im) );
03078 }
03079 }
03080 }
03081 }
03082 else
03083 {
03084 if( M->isReal )
03085 {
03086 for( j = 0; j < M->ncols; j++ )
03087 {
03088 for( i = 0; i < M->nrows; i++ )
03089 {
03090 MTX_static_round_value( &(M->data[j][i]), precision );
03091 }
03092 }
03093 }
03094 else
03095 {
03096 for( j = 0; j < M->ncols; j++ )
03097 {
03098 for( i = 0; i < M->nrows; i++ )
03099 {
03100 MTX_static_round_value( &(M->cplx[j][i].re), precision );
03101 MTX_static_round_value( &(M->cplx[j][i].im), precision );
03102 }
03103 }
03104 }
03105 }
03106 return TRUE;
03107 }
03108
03109 BOOL MTX_static_round_value_to_integer( double *value )
03110 {
03111 if( *value < 0 )
03112 *value = ceil( *value - 0.5 );
03113 else
03114 *value = floor( *value + 0.5 );
03115 return TRUE;
03116 }
03117
03118 BOOL MTX_static_round_value( double *value, const unsigned precision )
03119 {
03120 double pow10;
03121
03122 pow10 = pow( 10.0, (double)(precision) );
03123
03124 *value *= pow10;
03125 if( *value < 0 )
03126 *value = ceil( *value - 0.5 );
03127 else
03128 *value = floor( *value + 0.5 );
03129 *value /= pow10;
03130
03131 return TRUE;
03132 }
03133
03134 BOOL MTX_Floor( MTX *M )
03135 {
03136 unsigned i = 0;
03137 unsigned j = 0;
03138
03139 if( MTX_isNull( M ) )
03140 {
03141 MTX_ERROR_MSG( "NULL Matrix" );
03142 return FALSE;
03143 }
03144
03145 if( M->isReal )
03146 {
03147 for( j = 0; j < M->ncols; j++ )
03148 {
03149 for( i = 0; i < M->nrows; i++ )
03150 {
03151 M->data[j][i] = floor(M->data[j][i]);
03152 }
03153 }
03154 }
03155 else
03156 {
03157 for( j = 0; j < M->ncols; j++ )
03158 {
03159 for( i = 0; i < M->nrows; i++ )
03160 {
03161 M->cplx[j][i].re = floor(M->cplx[j][i].re);
03162 M->cplx[j][i].im = floor(M->cplx[j][i].im);
03163 }
03164 }
03165 }
03166
03167 return TRUE;
03168 }
03169
03170 BOOL MTX_Ceil( MTX *M )
03171 {
03172 unsigned i = 0;
03173 unsigned j = 0;
03174
03175 if( MTX_isNull( M ) )
03176 {
03177 MTX_ERROR_MSG( "NULL Matrix" );
03178 return FALSE;
03179 }
03180
03181 if( M->isReal )
03182 {
03183 for( j = 0; j < M->ncols; j++ )
03184 {
03185 for( i = 0; i < M->nrows; i++ )
03186 {
03187 M->data[j][i] = ceil(M->data[j][i]);
03188 }
03189 }
03190 }
03191 else
03192 {
03193 for( j = 0; j < M->ncols; j++ )
03194 {
03195 for( i = 0; i < M->nrows; i++ )
03196 {
03197 M->cplx[j][i].re = ceil(M->cplx[j][i].re);
03198 M->cplx[j][i].im = ceil(M->cplx[j][i].im);
03199 }
03200 }
03201 }
03202
03203 return TRUE;
03204 }
03205
03206 BOOL MTX_Fix( MTX *M )
03207 {
03208 unsigned i = 0;
03209 unsigned j = 0;
03210
03211 if( MTX_isNull( M ) )
03212 {
03213 MTX_ERROR_MSG( "NULL Matrix" );
03214 return FALSE;
03215 }
03216
03217 if( M->isReal )
03218 {
03219 for( j = 0; j < M->ncols; j++ )
03220 {
03221 for( i = 0; i < M->nrows; i++ )
03222 {
03223 if( M->data[j][i] < 0 )
03224 M->data[j][i] = ceil(M->data[j][i]);
03225 else
03226 M->data[j][i] = floor(M->data[j][i]);
03227 }
03228 }
03229 }
03230 else
03231 {
03232 for( j = 0; j < M->ncols; j++ )
03233 {
03234 for( i = 0; i < M->nrows; i++ )
03235 {
03236 if( M->cplx[j][i].re < 0 )
03237 M->cplx[j][i].re = ceil(M->cplx[j][i].re);
03238 else
03239 M->cplx[j][i].re = floor(M->cplx[j][i].re);
03240
03241 if( M->cplx[j][i].im < 0 )
03242 M->cplx[j][i].im = ceil(M->cplx[j][i].im);
03243 else
03244 M->cplx[j][i].im = floor(M->cplx[j][i].im);
03245 }
03246 }
03247 }
03248 return TRUE;
03249 }
03250
03251
03252 BOOL MTX_OneMinus( const MTX* src, MTX *dst )
03253 {
03254 if( MTX_isNull( src ) )
03255 {
03256 MTX_ERROR_MSG( "NULL Matrix" );
03257 return FALSE;
03258 }
03259 if( dst == NULL )
03260 {
03261 MTX_ERROR_MSG( "if( dst == NULL )" );
03262 return FALSE;
03263 }
03264
03265 if( !(dst->isReal == src->isReal &&
03266 dst->nrows == src->nrows &&
03267 dst->ncols == src->ncols ) )
03268 {
03269 if( !MTX_Malloc( dst, src->nrows, src->ncols, src->isReal ) )
03270 {
03271 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
03272 return FALSE;
03273 }
03274 }
03275 if( !MTX_Fill( dst, 1.0 ) )
03276 {
03277 MTX_ERROR_MSG( "MTX_Fill returned FALSE." );
03278 return FALSE;
03279 }
03280 if( !MTX_Subtract_Inplace( dst, src ) )
03281 {
03282 MTX_ERROR_MSG( "MTX_Subtract_Inplace returned FALSE." );
03283 return FALSE;
03284 }
03285 return TRUE;
03286 }
03287
03288
03289 BOOL MTX_DetermineFileDelimiter(
03290 const char *path,
03291 char *delimiter,
03292 BOOL *hasComment,
03293 char **comment
03294 )
03295 {
03296 unsigned i = 0;
03297 unsigned line_length = 0;
03298 char line[MTX_MAX_READFROMFILE_BUFFER];
03299 char *linebuf;
03300 FILE *in;
03301 BOOL atEOF = FALSE;
03302
03303 *hasComment = FALSE;
03304
03305
03306 #ifndef _CRT_SECURE_NO_DEPRECATE
03307 if( fopen_s( &in, path, "r" ) != 0 )
03308 {
03309 MTX_ERROR_MSG( "fopen_s returned failure." );
03310 return FALSE;
03311 }
03312 #else
03313 in = fopen( path, "r" );
03314 #endif
03315 if( !in )
03316 {
03317 #ifndef _CRT_SECURE_NO_DEPRECATE
03318 if( sprintf_s( line, MTX_MAX_READFROMFILE_BUFFER, "Unable to open %s.", path ) > 0 )
03319 MTX_ERROR_MSG( line );
03320 #else
03321 if( sprintf( line, "Unable to open %s.", path ) > 0 )
03322 MTX_ERROR_MSG( line );
03323 #endif
03324 return FALSE;
03325 }
03326
03327
03328 if( !MTX_static_get_next_valid_data_line( in, line, &line_length, &atEOF ) )
03329 {
03330 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
03331 return FALSE;
03332 }
03333 if( atEOF )
03334 {
03335 MTX_ERROR_MSG( "Unexpected end of file." );
03336 return FALSE;
03337 }
03338
03339
03340 if( strcmp( line, MTX_ID_COMPRESSED_01 ) == 0 )
03341 {
03342 *delimiter = 'b';
03343 fclose( in );
03344 return TRUE;
03345 }
03346
03347
03348 if( strcmp( line, MTX_ID_LEGACY_V01 ) == 0 )
03349 {
03350 *delimiter = 'b';
03351 fclose( in );
03352 return TRUE;
03353 }
03354
03355
03356 if( strcmp( line, MTX_ID_LEGACY_V02 ) == 0 )
03357 {
03358 *delimiter = 'b';
03359 fclose( in );
03360 return TRUE;
03361 }
03362
03363
03364 linebuf = (char *)line;
03365 for( i = 0; i < line_length; i++ )
03366 {
03367 if( isalpha( line[i] ) )
03368 {
03369 if( line[i] == 'e' || line[i] == 'E' || line[i] == '-' || line[i] == '+' || line[i] == '.' || line[i] == 'i' || line[i] == 'j' )
03370 continue;
03371
03372
03373 *hasComment = TRUE;
03374
03375
03376 (*comment) = (char*)malloc( (line_length+1)*sizeof(char) );
03377 if( !(*comment) )
03378 {
03379
03380 fclose(in);
03381 MTX_ERROR_MSG( "malloc returned NULL." );
03382 return FALSE;
03383 }
03384 #ifndef _CRT_SECURE_NO_DEPRECATE
03385 if( strcpy_s( *comment, line_length+1, line ) != 0 )
03386 {
03387 MTX_ERROR_MSG( "strcpy_s returned failure." );
03388 return FALSE;
03389 }
03390 #else
03391 strcpy( *comment, line );
03392
03393 #endif
03394
03395 if( !MTX_static_get_next_valid_data_line( in, line, &line_length, &atEOF ) )
03396 {
03397 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
03398 return FALSE;
03399 }
03400 if( atEOF )
03401 {
03402 MTX_ERROR_MSG( "Unexpected end of file." );
03403 return FALSE;
03404 }
03405
03406 linebuf = (char *)line;
03407 break;
03408 }
03409 }
03410 fclose( in );
03411
03412
03413 *delimiter = 'w';
03414
03415 if( strstr( linebuf, "," ) ) { *delimiter = ','; return TRUE; }
03416 if( strstr( linebuf, ":" ) ) { *delimiter = ':'; return TRUE; }
03417 if( strstr( linebuf, ";" ) ) { *delimiter = ';'; return TRUE; }
03418 if( strstr( linebuf, "|" ) ) { *delimiter = '|'; return TRUE; }
03419 if( strstr( linebuf, "`" ) ) { *delimiter = '`'; return TRUE; }
03420 if( strstr( linebuf, "~" ) ) { *delimiter = '~'; return TRUE; }
03421 if( strstr( linebuf, "!" ) ) { *delimiter = '!'; return TRUE; }
03422 if( strstr( linebuf, "@" ) ) { *delimiter = '@'; return TRUE; }
03423 if( strstr( linebuf, "#" ) ) { *delimiter = '#'; return TRUE; }
03424 if( strstr( linebuf, "$" ) ) { *delimiter = '$'; return TRUE; }
03425 if( strstr( linebuf, "%%" ) ) { *delimiter = '%'; return TRUE; }
03426 if( strstr( linebuf, "^" ) ) { *delimiter = '^'; return TRUE; }
03427 if( strstr( linebuf, "&" ) ) { *delimiter = '&'; return TRUE; }
03428 if( strstr( linebuf, "*" ) ) { *delimiter = '*'; return TRUE; }
03429 if( strstr( linebuf, "(" ) ) { *delimiter = '('; return TRUE; }
03430 if( strstr( linebuf, ")" ) ) { *delimiter = ')'; return TRUE; }
03431 if( strstr( linebuf, "_" ) ) { *delimiter = '_'; return TRUE; }
03432 if( strstr( linebuf, "=" ) ) { *delimiter = '='; return TRUE; }
03433 if( strstr( linebuf, "{" ) ) { *delimiter = '{'; return TRUE; }
03434 if( strstr( linebuf, "}" ) ) { *delimiter = '}'; return TRUE; }
03435 if( strstr( linebuf, "[" ) ) { *delimiter = '['; return TRUE; }
03436 if( strstr( linebuf, "]" ) ) { *delimiter = ']'; return TRUE; }
03437 if( strstr( linebuf, "\\" ) ) { *delimiter = '\\'; return TRUE; }
03438 if( strstr( linebuf, "\'" ) ) { *delimiter = '\''; return TRUE; }
03439 if( strstr( linebuf, "<" ) ) { *delimiter = '<'; return TRUE; }
03440 if( strstr( linebuf, "<" ) ) { *delimiter = '<'; return TRUE; }
03441 if( strstr( linebuf, ">" ) ) { *delimiter = '>'; return TRUE; }
03442 if( strstr( linebuf, "?" ) ) { *delimiter = '?'; return TRUE; }
03443 if( strstr( linebuf, "/" ) ) { *delimiter = '/'; return TRUE; }
03444
03445 return TRUE;
03446 }
03447
03448
03449 BOOL MTX_DetermineFileSize( const char *path, unsigned *size )
03450 {
03451 FILE* in;
03452 unsigned fstart;
03453 unsigned fend;
03454 char msg[512];
03455
03456 *size = 0;
03457
03458
03459 if( !path )
03460 {
03461 MTX_ERROR_MSG( "path is NULL." );
03462 return FALSE;
03463 }
03464
03465
03466 #ifndef _CRT_SECURE_NO_DEPRECATE
03467 if( fopen_s( &in, path, "r" ) != 0 )
03468 {
03469 MTX_ERROR_MSG( "fopen_s returned failure." );
03470 return FALSE;
03471 }
03472 #else
03473 in = fopen( path, "r" );
03474 #endif
03475 if( !in )
03476 {
03477 #ifndef _CRT_SECURE_NO_DEPRECATE
03478 if( sprintf_s( msg, 512, "Unable to open %s", path ) > 0 )
03479 MTX_ERROR_MSG( msg );
03480 #else
03481 if( sprintf( msg, "Unable to open %s", path ) > 0 )
03482 MTX_ERROR_MSG( msg );
03483 #endif
03484 return FALSE;
03485 }
03486
03487 fstart = ftell( in );
03488 fseek( in, 0, SEEK_END );
03489 fend = ftell( in );
03490
03491 *size = fend - fstart;
03492 fclose(in);
03493
03494 return TRUE;
03495 }
03496
03497
03498 BOOL MTX_DetermineNumberOfColumnsInDataString( const char *datastr, unsigned *ncols )
03499 {
03500 unsigned i = 0;
03501 unsigned line_length;
03502 char c;
03503 BOOL wasLastCharData = FALSE;
03504 double dtmp;
03505 int rv;
03506
03507 if( !datastr )
03508 {
03509 MTX_ERROR_MSG( "datastr is NULL." );
03510 return FALSE;
03511 }
03512
03513 line_length = (unsigned int)strlen(datastr);
03514 if( line_length == 0 )
03515 {
03516 MTX_ERROR_MSG( "if( line_length == 0 )" );
03517 return FALSE;
03518 }
03519
03520
03521 *ncols = 0;
03522
03523
03524 for( i = 0; i < line_length; i++ )
03525 {
03526 if( isspace(datastr[i]) )
03527 continue;
03528 else
03529 break;
03530 }
03531 if( i == line_length )
03532 {
03533
03534 MTX_ERROR_MSG( "if( i == line_length ) - no data in the string." );
03535 return FALSE;
03536 }
03537
03538
03539 for( ; i < line_length; i++ )
03540 {
03541 c = datastr[i];
03542 if( isdigit(c) || c == '.' || c == '-' || c == '+' )
03543 {
03544 if( !wasLastCharData )
03545 {
03546
03547 #ifndef _CRT_SECURE_NO_DEPRECATE
03548 rv = sscanf_s( &(datastr[i]), "%lf", &dtmp );
03549 #else
03550 rv = sscanf( &(datastr[i]), "%lf", &dtmp );
03551 #endif
03552 if( rv == 0 || rv == EOF )
03553 {
03554
03555 (*ncols) = 0;
03556 MTX_ERROR_MSG( "Invalid element found." );
03557 return FALSE;
03558 }
03559 (*ncols)++;
03560 }
03561 wasLastCharData = TRUE;
03562 }
03563 else if( c == 'e' || c == 'E' )
03564 {
03565 if( !wasLastCharData )
03566 {
03567
03568
03569 (*ncols) = 0;
03570 MTX_ERROR_MSG( "Exponent cannot be a leading character." );
03571 return FALSE;
03572 }
03573 continue;
03574 }
03575 else
03576 {
03577 wasLastCharData = FALSE;
03578 }
03579 }
03580
03581 return TRUE;
03582 }
03583
03584
03585
03586
03587 BOOL MTX_DetermineNumberOfColumnsInDataStringCplx( const char *datastr, const char delimiter, unsigned *ncols )
03588 {
03589 unsigned i = 0;
03590 unsigned line_length;
03591 char c;
03592
03593 BOOL isElementOnlyReal;
03594 BOOL isElementOnlyComplex;
03595 BOOL isComplexMix;
03596
03597 if( !datastr )
03598 {
03599 MTX_ERROR_MSG( "datastr is NULL." );
03600 return FALSE;
03601 }
03602
03603 line_length = (unsigned int)strlen(datastr);
03604 if( line_length == 0 )
03605 {
03606 MTX_ERROR_MSG( "if( line_length == 0 )" );
03607 return FALSE;
03608 }
03609
03610
03611 *ncols = 0;
03612
03613
03614 for( i = 0; i < line_length; i++ )
03615 {
03616 if( isspace(datastr[i]) )
03617 continue;
03618 else
03619 break;
03620 }
03621 if( i == line_length )
03622 {
03623
03624 MTX_ERROR_MSG( "if( i == line_length ) - No data in the string." );
03625 return FALSE;
03626 }
03627
03628 isElementOnlyComplex = FALSE;
03629 isElementOnlyReal = FALSE;
03630 isComplexMix = FALSE;
03631
03632 for( ; i < line_length; i++ )
03633 {
03634 c = datastr[i];
03635
03636
03637 if( isdigit(c) )
03638 {
03639 i++;
03640
03641
03642 for( ; i < line_length; i++ )
03643 {
03644 c = datastr[i];
03645 if( c == 'i' || c == 'j' )
03646 {
03647
03648 isComplexMix = TRUE;
03649 break;
03650 }
03651 else if( delimiter == 'w' )
03652 {
03653 if( isspace(c) )
03654 {
03655
03656 isElementOnlyReal = TRUE;
03657 break;
03658 }
03659 }
03660 else if( c == delimiter )
03661 {
03662
03663 isElementOnlyReal = TRUE;
03664 break;
03665 }
03666
03667 }
03668
03669 (*ncols)++;
03670 isComplexMix = FALSE;
03671 isElementOnlyReal = FALSE;
03672 }
03673 else
03674 {
03675 if( c == 'i' || c == 'j' )
03676 {
03677 isElementOnlyComplex = TRUE;
03678 (*ncols)++;
03679 isElementOnlyComplex = FALSE;
03680 }
03681 }
03682 }
03683
03684 return TRUE;
03685 }
03686
03687
03688
03689 BOOL MTX_static_extract_cplx_from_string_with_leading_digit(
03690 char *datastr,
03691 const unsigned indexS,
03692 const unsigned indexE,
03693 double *re,
03694 double *im
03695 )
03696 {
03697 unsigned i = 0;
03698 int rv;
03699 unsigned len = indexE - indexS + 1;
03700 char str[128];
03701
03702 for( i = 0; i < len && i < 128; i++ )
03703 {
03704 str[i] = datastr[indexS+i];
03705 if( i != 0 )
03706 {
03707 if( (str[i-1] == '+' || str[i-1] == '-') && (str[i] == 'i' || str[i] == 'j') )
03708 {
03709 str[i] = '1';
03710 }
03711 }
03712 }
03713 str[i] = '\0';
03714
03715
03716 #ifndef _CRT_SECURE_NO_DEPRECATE
03717 rv = sscanf_s( str, "%lf%lf", re, im );
03718 #else
03719 rv = sscanf( str, "%lf%lf", re, im );
03720 #endif
03721 if( rv == 2 )
03722 {
03723 return TRUE;
03724 }
03725 else if( rv == 1 )
03726 {
03727 *im = *re;
03728 *re = 0;
03729 return TRUE;
03730 }
03731 else
03732 {
03733 #ifndef _CRT_SECURE_NO_DEPRECATE
03734 MTX_ERROR_MSG( "sscanf_s returned failure." );
03735 #else
03736 MTX_ERROR_MSG( "sscanf returned failure." );
03737 #endif
03738 return FALSE;
03739 }
03740 }
03741
03742
03743 BOOL MTX_static_extract_real_into_cplx_from_string(
03744 char *datastr,
03745 const unsigned indexS,
03746 double *re,
03747 double *im
03748 )
03749 {
03750 int rv;
03751
03752
03753 #ifndef _CRT_SECURE_NO_DEPRECATE
03754 rv = sscanf_s( &(datastr[indexS]), "%lf", re );
03755 #else
03756 rv = sscanf( &(datastr[indexS]), "%lf", re );
03757 #endif
03758 if( rv == 1 )
03759 {
03760 *im = 0;
03761 return TRUE;
03762 }
03763 else
03764 {
03765 #ifndef _CRT_SECURE_NO_DEPRECATE
03766 MTX_ERROR_MSG( "sscanf_s returned failure." );
03767 #else
03768 MTX_ERROR_MSG( "sscanf returned failure." );
03769 #endif
03770 return FALSE;
03771 }
03772 }
03773
03774
03775
03776
03777 BOOL MTX_static_get_row_array_from_string_cplx( char *datastr, const char delimiter, _MTX_STRUCT_ReadFromFileListElem *L, const unsigned ncols )
03778 {
03779 unsigned i = 0;
03780 int j = 0;
03781 unsigned line_length;
03782 char c;
03783
03784 unsigned indexS;
03785 unsigned indexE;
03786
03787 BOOL isElementOnlyReal;
03788 BOOL isElementOnlyComplex;
03789 BOOL isComplexMix;
03790
03791 unsigned n = 0;
03792
03793 if( !datastr )
03794 {
03795 MTX_ERROR_MSG( "datastr is NULL." );
03796 return FALSE;
03797 }
03798
03799 line_length = (unsigned int)strlen(datastr);
03800 if( line_length == 0 )
03801 {
03802 MTX_ERROR_MSG( "if( line_length == 0 )" );
03803 return FALSE;
03804 }
03805
03806
03807 for( i = 0; i < line_length; i++ )
03808 {
03809 if( isspace(datastr[i]) )
03810 continue;
03811 else
03812 break;
03813 }
03814 if( i == line_length )
03815 {
03816
03817 MTX_ERROR_MSG( "if( i == line_length ) - No data in the string." );
03818 return FALSE;
03819 }
03820
03821 isElementOnlyComplex = FALSE;
03822 isElementOnlyReal = FALSE;
03823 isComplexMix = FALSE;
03824
03825 for( ; i < line_length; i++ )
03826 {
03827 c = datastr[i];
03828
03829
03830 if( isdigit(c) || ((c == '+' || c == '-') && isdigit(datastr[i+1]) ) )
03831 {
03832 indexS = i;
03833 i++;
03834
03835
03836 for( ; i <= line_length; i++ )
03837 {
03838 c = datastr[i];
03839 if( c == 'i' || c == 'j' )
03840 {
03841
03842 indexE = i;
03843 isComplexMix = TRUE;
03844
03845
03846 if( n < ncols )
03847 {
03848 if( !MTX_static_extract_cplx_from_string_with_leading_digit(
03849 datastr,
03850 indexS,
03851 indexE,
03852 &(L->rowptr_cplx[n].re),
03853 &(L->rowptr_cplx[n].im) ) )
03854 {
03855 MTX_ERROR_MSG( "MTX_static_extract_cplx_from_string_with_leading_digit returned FALSE." );
03856 return FALSE;
03857 }
03858 }
03859
03860 break;
03861 }
03862 else if( delimiter == 'w' )
03863 {
03864 if( isspace(c) || c == 0 )
03865 {
03866
03867 isElementOnlyReal = TRUE;
03868
03869
03870 if( n < ncols )
03871 {
03872 if( !MTX_static_extract_real_into_cplx_from_string(
03873 datastr,
03874 indexS,
03875 &(L->rowptr_cplx[n].re),
03876 &(L->rowptr_cplx[n].im) ) )
03877 {
03878 MTX_ERROR_MSG( "MTX_static_extract_real_into_cplx_from_string returned FALSE." );
03879 return FALSE;
03880 }
03881 }
03882 break;
03883 }
03884 }
03885 else if( c == delimiter || c == 0 )
03886 {
03887
03888 isElementOnlyReal = TRUE;
03889
03890
03891 if( n < ncols )
03892 {
03893
03894 if( !MTX_static_extract_real_into_cplx_from_string(
03895 datastr,
03896 indexS,
03897 &(L->rowptr_cplx[n].re),
03898 &(L->rowptr_cplx[n].im) ) )
03899 {
03900 MTX_ERROR_MSG( "MTX_static_extract_real_into_cplx_from_string returned FALSE." );
03901 return FALSE;
03902 }
03903 }
03904 break;
03905 }
03906
03907 }
03908
03909 n++;
03910 if( n > ncols )
03911 break;
03912 isComplexMix = FALSE;
03913 isElementOnlyReal = FALSE;
03914 }
03915 else
03916 {
03917 if( c == 'i' || c == 'j' )
03918 {
03919 isElementOnlyComplex = TRUE;
03920
03921
03922 if( n < ncols )
03923 {
03924
03925 L->rowptr_cplx[n].re = 0;
03926 L->rowptr_cplx[n].im = 1.0;
03927 j = i-1;
03928 while( j >= 0 )
03929 {
03930 c = datastr[j];
03931 if( c == '-' )
03932 {
03933 L->rowptr_cplx[n].im = -1.0;
03934 break;
03935 }
03936 else if( c == '+' )
03937 {
03938 break;
03939 }
03940 else if( c == 'i' || c == 'j' )
03941 {
03942 break;
03943 }
03944 else if( isdigit(c) )
03945 {
03946 break;
03947 }
03948 j--;
03949 }
03950 }
03951 n++;
03952 if( n > ncols )
03953 break;
03954 isElementOnlyComplex = FALSE;
03955 }
03956 }
03957 }
03958
03959 if( n != ncols )
03960 {
03961 MTX_ERROR_MSG( "if( n != ncols )" );
03962 return FALSE;
03963 }
03964 else
03965 {
03966 return TRUE;
03967 }
03968 }
03969
03970
03971 BOOL MTX_static_get_row_array_from_string( char *datastr, _MTX_STRUCT_ReadFromFileListElem *L, const unsigned ncols )
03972 {
03973 unsigned i = 0;
03974 unsigned n;
03975 unsigned line_length;
03976 char c;
03977 BOOL wasLastCharData = FALSE;
03978 int rv;
03979
03980 if( !datastr )
03981 {
03982 MTX_ERROR_MSG( "datastr is NULL." );
03983 return FALSE;
03984 }
03985
03986 if( !L )
03987 {
03988 MTX_ERROR_MSG( "L is NULL." );
03989 return FALSE;
03990 }
03991
03992 if( !L->rowptr )
03993 {
03994 MTX_ERROR_MSG( "L->rowptr is NULL." );
03995 return FALSE;
03996 }
03997
03998 line_length = (unsigned int)strlen(datastr);
03999 if( line_length == 0 )
04000 {
04001 MTX_ERROR_MSG( "if( line_length == 0 )" );
04002 return FALSE;
04003 }
04004
04005
04006 for( i = 0; i < line_length; i++ )
04007 {
04008 if( isspace(datastr[i]) )
04009 continue;
04010 else
04011 break;
04012 }
04013 if( i == line_length )
04014 {
04015
04016 MTX_ERROR_MSG( "if( i == line_length ) - No data in the string." );
04017 return FALSE;
04018 }
04019
04020
04021 n = 0;
04022 for( ; i < line_length; i++ )
04023 {
04024 c = datastr[i];
04025 if( isdigit(c) || c == '.' || c == '-' || c == '+' )
04026 {
04027 if( !wasLastCharData )
04028 {
04029
04030 #ifndef _CRT_SECURE_NO_DEPRECATE
04031 rv = sscanf_s( &(datastr[i]), "%lf", &(L->rowptr[n]) );
04032 #else
04033 rv = sscanf( &(datastr[i]), "%lf", &(L->rowptr[n]) );
04034 #endif
04035 if( rv == 0 || rv == EOF )
04036 {
04037
04038 MTX_ERROR_MSG( "Invalid element found." );
04039 return FALSE;
04040 }
04041 n++;
04042 if( n == ncols )
04043 break;
04044 }
04045 wasLastCharData = TRUE;
04046 }
04047 else if( c == 'e' || c == 'E' )
04048 {
04049 if( !wasLastCharData )
04050 {
04051
04052
04053 MTX_ERROR_MSG( "Invalid element found. Exponent cannot be leading character." );
04054 return FALSE;
04055 }
04056 continue;
04057 }
04058 else
04059 {
04060 wasLastCharData = FALSE;
04061 }
04062 }
04063
04064 if( n != ncols )
04065 {
04066
04067 MTX_ERROR_MSG( "if( n != ncols ) - The number of columns do not match." );
04068 return FALSE;
04069 }
04070
04071 return TRUE;
04072 }
04073
04074
04075 BOOL MTX_static_get_next_valid_data_line(
04076 FILE *in,
04077 char *linebuf,
04078 unsigned *line_length,
04079 BOOL *atEOF
04080 )
04081 {
04082 unsigned i = 0;
04083 i = 0;
04084 *line_length = 0;
04085 while( i == *line_length )
04086 {
04087 if( fgets( linebuf, MTX_MAX_READFROMFILE_BUFFER, in ) == NULL )
04088 {
04089 *atEOF = TRUE;
04090 if( feof(in) )
04091 {
04092
04093 fclose(in);
04094 return TRUE;
04095 }
04096 else if( ferror(in) != 0 )
04097 {
04098
04099 fclose(in);
04100 MTX_ERROR_MSG( "Error reading in the data." );
04101 return FALSE;
04102 }
04103 else
04104 {
04105
04106 fclose(in);
04107 MTX_ERROR_MSG( "Error reading in the data." );
04108 return FALSE;
04109 }
04110 }
04111
04112 *line_length = (unsigned int)strlen(linebuf);
04113 for( i = 0; i < *line_length; i++ )
04114 {
04115 if( !isspace(linebuf[i]) )
04116 break;
04117 }
04118 }
04119
04120
04121 if( *line_length < MTX_MAX_READFROMFILE_BUFFER-2 )
04122 {
04123 linebuf[*line_length] = '\0';
04124 linebuf[(*line_length)+1] = '\0';
04125 }
04126
04127 return TRUE;
04128 }
04129
04130
04131
04132 BOOL MTX_static_get_next_valid_data_line_from_matrix_string(
04133 const char *strMatrix,
04134 const unsigned strLength,
04135 unsigned *index,
04136 char *linebuf,
04137 unsigned *line_length,
04138 BOOL *atEndOfString
04139 )
04140 {
04141 unsigned i = 0;
04142 unsigned j = 0;
04143 *line_length = 0;
04144 *atEndOfString = FALSE;
04145
04146
04147 if( strMatrix == NULL )
04148 {
04149 MTX_ERROR_MSG( "strMatrix is NULL." );
04150 return FALSE;
04151 }
04152 if( index == NULL )
04153 {
04154 MTX_ERROR_MSG( "index is NULL." );
04155 return FALSE;
04156 }
04157 if( *index == strLength )
04158 {
04159 *atEndOfString = TRUE;
04160 return TRUE;
04161 }
04162 if( *index > strLength )
04163 {
04164 MTX_ERROR_MSG( "if( *index > strLength )" );
04165 return FALSE;
04166 }
04167
04168 while( i == *line_length )
04169 {
04170 *line_length = 0;
04171 for( j = *index; j < strLength; j++ )
04172 {
04173 linebuf[j-(*index)] = strMatrix[j];
04174 *line_length = *line_length + 1;
04175 if( strMatrix[j] == '\n' )
04176 break;
04177 }
04178 linebuf[*line_length] = '\0';
04179
04180 if( *line_length == 0 )
04181 {
04182 *atEndOfString = TRUE;
04183 *index = strLength;
04184 break;
04185 }
04186
04187 for( i = 0; i < *line_length; i++ )
04188 {
04189 if( !isspace(linebuf[i]) )
04190 break;
04191 }
04192 *index += *line_length;
04193 }
04194
04195
04196 if( *line_length < MTX_MAX_READFROMFILE_BUFFER-2 )
04197 {
04198 linebuf[*line_length] = '\0';
04199 linebuf[(*line_length)+1] = '\0';
04200 }
04201
04202 return TRUE;
04203 }
04204
04205 BOOL MTX_static_look_for_complex_data(
04206 char *linebuf,
04207 const unsigned line_length,
04208 BOOL *hasComplex
04209 )
04210 {
04211 unsigned i;
04212
04213 *hasComplex = FALSE;
04214 if( linebuf == NULL )
04215 {
04216 MTX_ERROR_MSG( "linebuf is NULL." );
04217 return FALSE;
04218 }
04219
04220 for( i = 0; i < line_length; i++ )
04221 {
04222 if( linebuf[i] == 'i' || linebuf[i] == 'j' )
04223 {
04224 *hasComplex = TRUE;
04225 break;
04226 }
04227 }
04228 return TRUE;
04229 }
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239 BOOL MTX_ReadFromFileRealOnly( MTX *M, const char *path )
04240 {
04241 unsigned i = 0;
04242 FILE *in = NULL;
04243 char delimiter = 0;
04244 char linebuf[MTX_MAX_READFROMFILE_BUFFER];
04245 unsigned ncols = 0;
04246 unsigned nrows = 0;
04247 unsigned fsize = 0;
04248 unsigned line_length = 0;
04249 BOOL hasCommentLine = FALSE;
04250 BOOL errorInReadingDataFile = FALSE;
04251 BOOL errorInTranspose = FALSE;
04252 BOOL atEOF = FALSE;
04253 MTX RowMatrix;
04254
04255
04256 _MTX_STRUCT_ReadFromFileListElem *L = NULL;
04257 _MTX_STRUCT_ReadFromFileListElem *nL = NULL;
04258 _MTX_STRUCT_ReadFromFileListElem head;
04259 head.next = NULL;
04260 head.rowptr = NULL;
04261
04262 if( M == NULL )
04263 {
04264 MTX_ERROR_MSG( "M is NULL." );
04265 return FALSE;
04266 }
04267
04268
04269 if( !path )
04270 {
04271 MTX_ERROR_MSG( "path is NULL." );
04272 return FALSE;
04273 }
04274
04275
04276 #ifndef _CRT_SECURE_NO_DEPRECATE
04277 if( fopen_s( &in, path, "r" ) != 0 )
04278 {
04279 MTX_ERROR_MSG( "fopen_s returned failure." );
04280 return FALSE;
04281 }
04282 #else
04283 in = fopen( path, "r" );
04284 #endif
04285 if( !in )
04286 {
04287 #ifndef _CRT_SECURE_NO_DEPRECATE
04288 if( sprintf_s( linebuf, MTX_MAX_READFROMFILE_BUFFER, "Unable to open %s.", path ) > 0 )
04289 MTX_ERROR_MSG( linebuf );
04290 #else
04291 if( sprintf( linebuf, "Unable to open %s.", path ) > 0 )
04292 MTX_ERROR_MSG( linebuf );
04293 #endif
04294 return FALSE;
04295 }
04296 fclose(in);
04297
04298 MTX_Init( &RowMatrix );
04299
04300
04301 if( MTX_DetermineFileDelimiter( path, &delimiter, &hasCommentLine, &(M->comment) ) == FALSE )
04302 {
04303 MTX_ERROR_MSG( "MTX_DetermineFileDelimiter returned FALSE." );
04304 return FALSE;
04305 }
04306
04307
04308 if( delimiter == 'b' )
04309 {
04310 if( MTX_ReadCompressed( M, path ) )
04311 {
04312 return TRUE;
04313 }
04314 else
04315 {
04316 MTX_ERROR_MSG( "MTX_ReadCompressed returned FALSE." );
04317 return FALSE;
04318 }
04319 }
04320
04321
04322 if( MTX_DetermineFileSize( path, &fsize ) == FALSE )
04323 {
04324 MTX_ERROR_MSG( "MTX_DetermineFileSize returned FALSE." );
04325 return FALSE;
04326 }
04327
04328
04329 #ifndef _CRT_SECURE_NO_DEPRECATE
04330 if( fopen_s( &in, path, "r" ) != 0 )
04331 {
04332 MTX_ERROR_MSG( "fopen_s returned failure." );
04333 return FALSE;
04334 }
04335 #else
04336 in = fopen( path, "r" );
04337 #endif
04338 if( !in )
04339 {
04340 #ifndef _CRT_SECURE_NO_DEPRECATE
04341 if( sprintf_s( linebuf, MTX_MAX_READFROMFILE_BUFFER, "Unable to open %s.", path ) > 0 )
04342 MTX_ERROR_MSG( linebuf );
04343 #else
04344 if( sprintf( linebuf, "Unable to open %s.", path ) > 0 )
04345 MTX_ERROR_MSG( linebuf );
04346 #endif
04347 return FALSE;
04348 }
04349
04350
04351 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04352 {
04353 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
04354 return FALSE;
04355 }
04356 if( atEOF )
04357 {
04358 MTX_ERROR_MSG( "Unexpected end of file." );
04359 return FALSE;
04360 }
04361
04362 if( hasCommentLine )
04363 {
04364 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04365 {
04366 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
04367 return FALSE;
04368 }
04369 if( atEOF )
04370 {
04371 MTX_ERROR_MSG( "Unexpected end of file." );
04372 return FALSE;
04373 }
04374 }
04375
04376
04377 if( MTX_DetermineNumberOfColumnsInDataString( linebuf, &ncols ) == FALSE )
04378 {
04379 MTX_ERROR_MSG( "MTX_DetermineNumberOfColumnsInDataString returned FALSE." );
04380 return FALSE;
04381 }
04382
04383
04384
04385
04386
04387 nrows = 0;
04388 head.rowptr = (double*)malloc( ncols*sizeof(double) );
04389
04390 if( MTX_static_get_row_array_from_string( linebuf, &head, ncols ) == FALSE )
04391 {
04392
04393 free( head.rowptr );
04394 MTX_ERROR_MSG( "MTX_static_get_row_array_from_string returned FALSE." );
04395 return FALSE;
04396 }
04397 nrows++;
04398 nL = &head;
04399
04400 while(1)
04401 {
04402
04403 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04404 {
04405 errorInReadingDataFile = TRUE;
04406 break;
04407 }
04408 if( atEOF )
04409 {
04410 break;
04411 }
04412
04413
04414 L = nL;
04415
04416
04417 nL = (_MTX_STRUCT_ReadFromFileListElem*)malloc( sizeof( _MTX_STRUCT_ReadFromFileListElem ) );
04418 if( !nL )
04419 {
04420
04421
04422 errorInReadingDataFile = TRUE;
04423
04424 free( head.rowptr );
04425 MTX_ERROR_MSG( "if( !nL )" );
04426 return FALSE;
04427 }
04428
04429 nL->rowptr = NULL;
04430 nL->next = NULL;
04431
04432 nL->rowptr = (double*)malloc( ncols*sizeof(double) );
04433 if( !nL->rowptr )
04434 {
04435
04436
04437 errorInReadingDataFile = TRUE;
04438 break;
04439 }
04440
04441
04442
04443 L->next = nL;
04444
04445
04446 if( MTX_static_get_row_array_from_string( linebuf, nL, ncols ) == FALSE )
04447 {
04448
04449 errorInReadingDataFile = TRUE;
04450 break;
04451 }
04452 nrows++;
04453 }
04454
04455 if( errorInReadingDataFile )
04456 {
04457
04458 L = head.next;
04459 while( L!=NULL )
04460 {
04461 nL = L->next;
04462 free( L->rowptr );
04463 free(L);
04464 L = nL;
04465 }
04466 free( head.rowptr );
04467
04468 MTX_ERROR_MSG( "if( errorInReadingDataFile )" );
04469 return FALSE;
04470 }
04471
04472
04473
04474
04475 RowMatrix.data = (double**)malloc( nrows*sizeof(double*) );
04476 if( !RowMatrix.data )
04477 {
04478 MTX_ERROR_MSG( "malloc returned NULL." );
04479 return FALSE;
04480 }
04481
04482
04483 RowMatrix.ncols = nrows;
04484 RowMatrix.nrows = ncols;
04485
04486 L = &head;
04487 for( i = 0; i < nrows; i++ )
04488 {
04489 if( L == NULL )
04490 {
04491
04492 free(RowMatrix.data);
04493 RowMatrix.data = NULL;
04494 MTX_ERROR_MSG( "if( L == NULL )" );
04495 return FALSE;
04496 }
04497 RowMatrix.data[i] = L->rowptr;
04498 L = L->next;
04499 }
04500
04501
04502
04503
04504 if( !MTX_Transpose( &RowMatrix, M ) )
04505 {
04506 errorInTranspose = TRUE;
04507 }
04508
04509
04510 L = head.next;
04511 while( L!=NULL )
04512 {
04513 nL = L->next;
04514 free( L->rowptr );
04515 free(L);
04516 L = nL;
04517 }
04518
04519 free( head.rowptr );
04520
04521
04522 free( RowMatrix.data );
04523
04524 if( errorInTranspose )
04525 {
04526 MTX_ERROR_MSG( "if( errorInTranspose )" );
04527 return FALSE;
04528 }
04529 else
04530 {
04531 return TRUE;
04532 }
04533 }
04534
04535
04536
04537
04538
04539
04540 BOOL MTX_ReadFromFile( MTX *M, const char *path )
04541 {
04542 unsigned i;
04543 FILE *in = NULL;
04544 char delimiter = 0;
04545 char linebuf[MTX_MAX_READFROMFILE_BUFFER];
04546 unsigned ncols = 0;
04547 unsigned nrows = 0;
04548 unsigned fsize = 0;
04549 unsigned line_length = 0;
04550 BOOL hasCommentLine = FALSE;
04551 BOOL errorInReadingDataFile = FALSE;
04552 BOOL errorInTranspose = FALSE;
04553 BOOL atEOF = FALSE;
04554 BOOL isReal = TRUE;
04555 BOOL complexDetected = FALSE;
04556 BOOL needToConvertRealToComplex = FALSE;
04557 MTX RowMatrix;
04558 char *commentLine = NULL;
04559
04560
04561 _MTX_STRUCT_ReadFromFileListElem *L = NULL;
04562 _MTX_STRUCT_ReadFromFileListElem *nL = NULL;
04563 _MTX_STRUCT_ReadFromFileListElem head;
04564 head.next = NULL;
04565 head.rowptr = NULL;
04566
04567
04568 if( !path )
04569 {
04570 MTX_ERROR_MSG( "path is NULL." );
04571 return FALSE;
04572 }
04573
04574
04575 #ifndef _CRT_SECURE_NO_DEPRECATE
04576 if( fopen_s( &in, path, "r" ) != 0 )
04577 {
04578 MTX_ERROR_MSG( "fopen_s returned failure." );
04579 return FALSE;
04580 }
04581 #else
04582 in = fopen( path, "r" );
04583 #endif
04584 if( !in )
04585 {
04586 #ifndef _CRT_SECURE_NO_DEPRECATE
04587 if( sprintf_s( linebuf, MTX_MAX_READFROMFILE_BUFFER, "Unable to open %s.", path ) > 0 )
04588 MTX_ERROR_MSG( linebuf );
04589 #else
04590 if( sprintf( linebuf, "Unable to open %s.", path ) > 0 )
04591 MTX_ERROR_MSG( linebuf );
04592 #endif
04593 return FALSE;
04594 }
04595 fclose(in);
04596
04597
04598 MTX_Init( &RowMatrix );
04599
04600
04601 if( MTX_DetermineFileDelimiter( path, &delimiter, &hasCommentLine, &commentLine ) == FALSE )
04602 {
04603 MTX_ERROR_MSG( "MTX_DetermineFileDelimiter returned FALSE." );
04604 return FALSE;
04605 }
04606
04607
04608 if( delimiter == 'b' )
04609 {
04610
04611 if( MTX_ReadCompressed( M, path ) )
04612 {
04613 return TRUE;
04614 }
04615 else
04616 {
04617 MTX_ERROR_MSG( "MTX_ReadCompressed returned FALSE." );
04618 return FALSE;
04619 }
04620 }
04621
04622
04623 if( MTX_DetermineFileSize( path, &fsize ) == FALSE )
04624 {
04625 MTX_ERROR_MSG( "MTX_DetermineFileSize returned FALSE." );
04626 return FALSE;
04627 }
04628
04629
04630 #ifndef _CRT_SECURE_NO_DEPRECATE
04631 if( fopen_s( &in, path, "r" ) != 0 )
04632 {
04633 MTX_ERROR_MSG( "fopen_s returned failure." );
04634 return FALSE;
04635 }
04636 #else
04637 in = fopen( path, "r" );
04638 #endif
04639 if( !in )
04640 {
04641 #ifndef _CRT_SECURE_NO_DEPRECATE
04642 if( sprintf_s( linebuf, MTX_MAX_READFROMFILE_BUFFER, "Unable to open %s.", path ) > 0 )
04643 MTX_ERROR_MSG( linebuf );
04644 #else
04645 if( sprintf( linebuf, "Unable to open %s.", path ) > 0 )
04646 MTX_ERROR_MSG( linebuf );
04647 #endif
04648 return FALSE;
04649 }
04650
04651
04652 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04653 {
04654 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
04655 return FALSE;
04656 }
04657 if( atEOF )
04658 {
04659 MTX_ERROR_MSG( "Unexpected end of file." );
04660 return FALSE;
04661 }
04662
04663 if( hasCommentLine )
04664 {
04665 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04666 {
04667 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line returned FALSE." );
04668 return FALSE;
04669 }
04670 if( atEOF )
04671 {
04672 MTX_ERROR_MSG( "Unexpected end of file." );
04673 return FALSE;
04674 }
04675 }
04676
04677
04678 if( !MTX_static_look_for_complex_data( linebuf, line_length, &complexDetected ) )
04679 {
04680 MTX_ERROR_MSG( "MTX_static_look_for_complex_data returned FALSE." );
04681 return FALSE;
04682 }
04683 if( complexDetected )
04684 {
04685 needToConvertRealToComplex = FALSE;
04686 isReal = FALSE;
04687
04688 }
04689
04690
04691 if( isReal )
04692 {
04693 if( !MTX_DetermineNumberOfColumnsInDataString( linebuf, &ncols ) )
04694 {
04695 MTX_ERROR_MSG( "MTX_DetermineNumberOfColumnsInDataString returned FALSE." );
04696 return FALSE;
04697 }
04698 }
04699 else
04700 {
04701 if( !MTX_DetermineNumberOfColumnsInDataStringCplx( linebuf, delimiter, &ncols ) )
04702 {
04703 MTX_ERROR_MSG( "MTX_DetermineNumberOfColumnsInDataStringCplx returned FALSE." );
04704 return FALSE;
04705 }
04706 }
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718 nrows = 0;
04719 if( isReal )
04720 {
04721 head.isReal = TRUE;
04722 head.rowptr = (double*)malloc( ncols*sizeof(double) );
04723
04724
04725 if( !MTX_static_get_row_array_from_string( linebuf, &head, ncols ) )
04726 {
04727
04728 free( head.rowptr );
04729 MTX_ERROR_MSG( "MTX_static_get_row_array_from_string returned false." );
04730 return FALSE;
04731 }
04732 }
04733 else
04734 {
04735 head.isReal = FALSE;
04736 head.rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
04737
04738
04739 if( MTX_static_get_row_array_from_string_cplx( linebuf, delimiter, &head, ncols ) == FALSE )
04740 {
04741
04742 free( head.rowptr_cplx );
04743 MTX_ERROR_MSG( "MTX_static_get_row_array_from_string_cplx returned false." );
04744 return FALSE;
04745 }
04746 }
04747 nrows++;
04748 nL = &head;
04749
04750 while(1)
04751 {
04752
04753 if( !MTX_static_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
04754 {
04755 errorInReadingDataFile = TRUE;
04756 break;
04757 }
04758 if( atEOF )
04759 {
04760 break;
04761 }
04762
04763
04764 if( isReal )
04765 {
04766 if( !MTX_static_look_for_complex_data( linebuf, line_length, &complexDetected ) )
04767 {
04768 MTX_ERROR_MSG( "MTX_static_look_for_complex_data returned FALSE." );
04769 return FALSE;
04770 }
04771
04772 if( complexDetected )
04773 {
04774 isReal = FALSE;
04775 needToConvertRealToComplex = TRUE;
04776 }
04777 }
04778
04779
04780 L = nL;
04781
04782
04783 nL = (_MTX_STRUCT_ReadFromFileListElem*)malloc( sizeof( _MTX_STRUCT_ReadFromFileListElem ) );
04784 if( !nL )
04785 {
04786
04787
04788 errorInReadingDataFile = TRUE;
04789 MTX_ERROR_MSG( "if( !nL )" );
04790 return FALSE;
04791 }
04792
04793
04794 nL->isReal = isReal;
04795 nL->rowptr = NULL;
04796 nL->rowptr_cplx = NULL;
04797 nL->next = NULL;
04798
04799
04800 if( isReal )
04801 {
04802 nL->rowptr = (double*)malloc( ncols*sizeof(double) );
04803 if( !nL->rowptr )
04804 {
04805
04806
04807 errorInReadingDataFile = TRUE;
04808 break;
04809 }
04810 }
04811 else
04812 {
04813 nL->rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
04814 if( !nL->rowptr_cplx )
04815 {
04816
04817
04818 errorInReadingDataFile = TRUE;
04819 break;
04820 }
04821 }
04822
04823
04824
04825 L->next = nL;
04826
04827 if( isReal )
04828 {
04829
04830 if( MTX_static_get_row_array_from_string( linebuf, nL, ncols ) == FALSE )
04831 {
04832
04833 errorInReadingDataFile = TRUE;
04834 break;
04835 }
04836 }
04837 else
04838 {
04839
04840 if( MTX_static_get_row_array_from_string_cplx( linebuf, delimiter, nL, ncols ) == FALSE )
04841 {
04842
04843 errorInReadingDataFile = TRUE;
04844 break;
04845 }
04846 }
04847 nrows++;
04848 }
04849
04850 if( errorInReadingDataFile )
04851 {
04852
04853 L = head.next;
04854 while( L!=NULL )
04855 {
04856 nL = L->next;
04857 if( L->isReal )
04858 {
04859 free( L->rowptr );
04860 }
04861 else
04862 {
04863 free( L->rowptr_cplx );
04864 }
04865 free(L);
04866 L = nL;
04867 }
04868 if( head.isReal )
04869 {
04870 free( head.rowptr );
04871 }
04872 else
04873 {
04874 free( head.rowptr_cplx );
04875 }
04876
04877 MTX_ERROR_MSG( "if( errorInReadingDataFile )" );
04878 return FALSE;
04879 }
04880
04881
04882
04883 if( needToConvertRealToComplex )
04884 {
04885 L = &head;
04886
04887
04888 while( L->isReal )
04889 {
04890 L->rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
04891 if( !L->rowptr_cplx )
04892 {
04893
04894
04895 errorInReadingDataFile = TRUE;
04896 break;
04897 }
04898
04899
04900 for( i = 0; i < ncols; i++ )
04901 {
04902 L->rowptr_cplx[i].re = L->rowptr[i];
04903 L->rowptr_cplx[i].im = 0.0;
04904 }
04905
04906
04907 if( L->isReal )
04908 {
04909 free( L->rowptr );
04910 }
04911 L->rowptr = NULL;
04912
04913
04914 L = L->next;
04915
04916
04917 if( L == NULL )
04918 break;
04919 }
04920 }
04921
04922
04923
04924
04925
04926
04927
04928 if( isReal )
04929 {
04930 RowMatrix.isReal = TRUE;
04931 RowMatrix.data = (double**)malloc( nrows*sizeof(double*) );
04932 if( !RowMatrix.data )
04933 {
04934 MTX_ERROR_MSG( "malloc returned NULL." );
04935 return FALSE;
04936 }
04937 }
04938 else
04939 {
04940 RowMatrix.isReal = FALSE;
04941 RowMatrix.cplx = (stComplex**)malloc( nrows*sizeof(stComplex*) );
04942 if( !RowMatrix.cplx )
04943 {
04944 MTX_ERROR_MSG( "malloc returned NULL." );
04945 return FALSE;
04946 }
04947 }
04948
04949 RowMatrix.ncols = nrows;
04950 RowMatrix.nrows = ncols;
04951
04952 L = &head;
04953 for( i = 0; i < nrows; i++ )
04954 {
04955 if( L == NULL )
04956 {
04957
04958 MTX_ERROR_MSG( "if( L == NULL ) - This should never happen." );
04959 return FALSE;
04960 }
04961 if( isReal )
04962 {
04963 RowMatrix.data[i] = L->rowptr;
04964 }
04965 else
04966 {
04967 RowMatrix.cplx[i] = L->rowptr_cplx;
04968 }
04969 L = L->next;
04970 }
04971
04972
04973
04974
04975 if( !MTX_Transpose( &RowMatrix, M ) )
04976 {
04977 errorInTranspose = TRUE;
04978 }
04979
04980 if( commentLine != NULL )
04981 {
04982
04983 M->comment = commentLine;
04984 }
04985
04986
04987 L = head.next;
04988 while( L!=NULL )
04989 {
04990 nL = L->next;
04991 if( isReal )
04992 {
04993 free( L->rowptr );
04994 }
04995 else
04996 {
04997 free( L->rowptr_cplx );
04998 }
04999 free(L);
05000 L = nL;
05001 }
05002
05003 if( isReal )
05004 {
05005 free( head.rowptr );
05006 }
05007 else
05008 {
05009 free( head.rowptr_cplx );
05010 }
05011
05012
05013 if( isReal )
05014 {
05015 free( RowMatrix.data );
05016 }
05017 else
05018 {
05019 free( RowMatrix.cplx );
05020 }
05021
05022 if( errorInTranspose )
05023 {
05024 MTX_ERROR_MSG( "if( errorInTranspose )" );
05025 return FALSE;
05026 }
05027 else
05028 {
05029 return TRUE;
05030 }
05031 }
05032
05033
05034
05035
05036
05037
05038 BOOL MTX_SetFromMatrixString( MTX *M, const char *strMatrix )
05039 {
05040 unsigned i;
05041 const char delimiter = 'w';
05042 char strMatrixCopy[MTX_MAX_READFROMFILE_BUFFER];
05043 char linebuf[MTX_MAX_READFROMFILE_BUFFER];
05044 unsigned ncols = 0;
05045 unsigned nrows = 0;
05046 unsigned line_length = 0;
05047 unsigned strMatrixLength = 0;
05048 unsigned strMatrixIndex = 0;
05049 BOOL errorInReadingData = FALSE;
05050 BOOL errorInTranspose = FALSE;
05051 BOOL atEndOfString = FALSE;
05052 BOOL isReal = TRUE;
05053 BOOL complexDetected = FALSE;
05054 BOOL needToConvertRealToComplex = FALSE;
05055 MTX RowMatrix;
05056
05057
05058 _MTX_STRUCT_ReadFromFileListElem *L = NULL;
05059 _MTX_STRUCT_ReadFromFileListElem *nL = NULL;
05060 _MTX_STRUCT_ReadFromFileListElem head;
05061 head.next = NULL;
05062 head.rowptr = NULL;
05063
05064
05065 if( strMatrix == NULL )
05066 {
05067 MTX_ERROR_MSG( "strMatrix is NULL." );
05068 return FALSE;
05069 }
05070
05071 strMatrixLength = (unsigned int)strlen( strMatrix );
05072 if( strMatrixLength == 0 )
05073 {
05074 MTX_ERROR_MSG( "if( strMatrixLength == 0 )" );
05075 return FALSE;
05076 }
05077
05078
05079 if( strMatrixLength+1 > MTX_MAX_READFROMFILE_BUFFER )
05080 {
05081 MTX_ERROR_MSG( "if( strMatrixLength+1 > MTX_MAX_READFROMFILE_BUFFER )" );
05082 return FALSE;
05083 }
05084
05085
05086 MTX_Init( &RowMatrix );
05087
05088
05089 #ifndef _CRT_SECURE_NO_DEPRECATE
05090 if( strncpy_s( strMatrixCopy, MTX_MAX_READFROMFILE_BUFFER, strMatrix, strMatrixLength ) != 0 )
05091 {
05092 MTX_ERROR_MSG( "strncpy_s returned failure." );
05093 return FALSE;
05094 }
05095 #else
05096 strncpy( strMatrixCopy, strMatrix, strMatrixLength );
05097 #endif
05098 strMatrixCopy[strMatrixLength] = '\0';
05099
05100
05101
05102 for( i = 0; i < strMatrixLength; i++ )
05103 {
05104 if( strMatrixCopy[i] == ',' )
05105 {
05106 strMatrixCopy[i] = ' ';
05107 }
05108 else if( strMatrixCopy[i] == ';' )
05109 {
05110 strMatrixCopy[i] = '\n';
05111 }
05112 else if( strMatrixCopy[i] == '[' )
05113 {
05114 strMatrixCopy[i] = ' ';
05115 }
05116 else if( strMatrixCopy[i] == ']' )
05117 {
05118 strMatrixCopy[i] = ' ';
05119 }
05120 }
05121
05122
05123 if( !MTX_static_get_next_valid_data_line_from_matrix_string(
05124 strMatrixCopy,
05125 strMatrixLength,
05126 &strMatrixIndex,
05127 linebuf,
05128 &line_length,
05129 &atEndOfString ) )
05130 {
05131 MTX_ERROR_MSG( "MTX_static_get_next_valid_data_line_from_matrix_string returned FALSE." );
05132 return FALSE;
05133 }
05134 if( atEndOfString )
05135 {
05136 MTX_ERROR_MSG( "Unexpected end of string." );
05137 return FALSE;
05138 }
05139
05140
05141 if( !MTX_static_look_for_complex_data( linebuf, line_length, &complexDetected ) )
05142 {
05143 MTX_ERROR_MSG( "MTX_static_look_for_complex_data returned FALSE." );
05144 return FALSE;
05145 }
05146 if( complexDetected )
05147 {
05148 needToConvertRealToComplex = FALSE;
05149 isReal = FALSE;
05150
05151 }
05152
05153
05154 if( isReal )
05155 {
05156 if( !MTX_DetermineNumberOfColumnsInDataString( linebuf, &ncols ) )
05157 {
05158 MTX_ERROR_MSG( "MTX_DetermineNumberOfColumnsInDataString returned FALSE." );
05159 return FALSE;
05160 }
05161 }
05162 else
05163 {
05164 if( !MTX_DetermineNumberOfColumnsInDataStringCplx( linebuf, delimiter, &ncols ) )
05165 {
05166 MTX_ERROR_MSG( "MTX_DetermineNumberOfColumnsInDataStringCplx returned FALSE." );
05167 return FALSE;
05168 }
05169 }
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180 nrows = 0;
05181 if( isReal )
05182 {
05183 head.isReal = TRUE;
05184 head.rowptr = (double*)malloc( ncols*sizeof(double) );
05185
05186
05187 if( !MTX_static_get_row_array_from_string( linebuf, &head, ncols ) )
05188 {
05189
05190 free( head.rowptr );
05191 MTX_ERROR_MSG( "malloc returned NULL." );
05192 return FALSE;
05193 }
05194 }
05195 else
05196 {
05197 head.isReal = FALSE;
05198 head.rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
05199
05200
05201 if( MTX_static_get_row_array_from_string_cplx( linebuf, delimiter, &head, ncols ) == FALSE )
05202 {
05203
05204 free( head.rowptr_cplx );
05205 MTX_ERROR_MSG( "malloc returned NULL." );
05206 return FALSE;
05207 }
05208 }
05209 nrows++;
05210 nL = &head;
05211
05212 while(1)
05213 {
05214
05215 if( !MTX_static_get_next_valid_data_line_from_matrix_string(
05216 strMatrixCopy,
05217 strMatrixLength,
05218 &strMatrixIndex,
05219 linebuf,
05220 &line_length,
05221 &atEndOfString ) )
05222 {
05223 errorInReadingData = TRUE;
05224 break;
05225 }
05226 if( atEndOfString )
05227 {
05228 break;
05229 }
05230
05231
05232 if( isReal )
05233 {
05234 if( !MTX_static_look_for_complex_data( linebuf, line_length, &complexDetected ) )
05235 {
05236 MTX_ERROR_MSG( "MTX_static_look_for_complex_data returned FALSE." );
05237 return FALSE;
05238 }
05239
05240 if( complexDetected )
05241 {
05242 isReal = FALSE;
05243 needToConvertRealToComplex = TRUE;
05244 }
05245 }
05246
05247
05248 L = nL;
05249
05250
05251 nL = (_MTX_STRUCT_ReadFromFileListElem*)malloc( sizeof( _MTX_STRUCT_ReadFromFileListElem ) );
05252 if( !nL )
05253 {
05254
05255
05256 errorInReadingData = TRUE;
05257 break;
05258 }
05259
05260
05261 nL->isReal = isReal;
05262 nL->rowptr = NULL;
05263 nL->rowptr_cplx = NULL;
05264 nL->next = NULL;
05265
05266
05267 if( isReal )
05268 {
05269 nL->rowptr = (double*)malloc( ncols*sizeof(double) );
05270 if( !nL->rowptr )
05271 {
05272
05273
05274 errorInReadingData = TRUE;
05275 break;
05276 }
05277 }
05278 else
05279 {
05280 nL->rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
05281 if( !nL->rowptr_cplx )
05282 {
05283
05284
05285 errorInReadingData = TRUE;
05286 break;
05287 }
05288 }
05289
05290
05291
05292 L->next = nL;
05293
05294 if( isReal )
05295 {
05296
05297 if( MTX_static_get_row_array_from_string( linebuf, nL, ncols ) == FALSE )
05298 {
05299
05300 errorInReadingData = TRUE;
05301 break;
05302 }
05303 }
05304 else
05305 {
05306
05307 if( MTX_static_get_row_array_from_string_cplx( linebuf, delimiter, nL, ncols ) == FALSE )
05308 {
05309
05310 errorInReadingData = TRUE;
05311 break;
05312 }
05313 }
05314 nrows++;
05315 }
05316
05317 if( errorInReadingData )
05318 {
05319
05320 L = head.next;
05321 while( L!=NULL )
05322 {
05323 nL = L->next;
05324 if( L->isReal )
05325 {
05326 free( L->rowptr );
05327 }
05328 else
05329 {
05330 free( L->rowptr_cplx );
05331 }
05332 free(L);
05333 L = nL;
05334 }
05335 if( head.isReal )
05336 {
05337 free( head.rowptr );
05338 }
05339 else
05340 {
05341 free( head.rowptr_cplx );
05342 }
05343 MTX_ERROR_MSG( "if( errorInReadingData )" );
05344 return FALSE;
05345 }
05346
05347
05348
05349 if( needToConvertRealToComplex )
05350 {
05351 L = &head;
05352
05353
05354 while( L->isReal )
05355 {
05356 L->rowptr_cplx = (stComplex*)malloc( ncols*sizeof(stComplex) );
05357 if( !L->rowptr_cplx )
05358 {
05359
05360
05361 errorInReadingData = TRUE;
05362 break;
05363 }
05364
05365
05366 for( i = 0; i < ncols; i++ )
05367 {
05368 L->rowptr_cplx[i].re = L->rowptr[i];
05369 L->rowptr_cplx[i].im = 0.0;
05370 }
05371
05372
05373 if( L->isReal )
05374 {
05375 free( L->rowptr );
05376 }
05377 L->rowptr = NULL;
05378
05379
05380 L = L->next;
05381
05382
05383 if( L == NULL )
05384 break;
05385 }
05386 }
05387
05388
05389
05390
05391
05392
05393
05394 if( isReal )
05395 {
05396 RowMatrix.isReal = TRUE;
05397 RowMatrix.data = (double**)malloc( nrows*sizeof(double*) );
05398 if( !RowMatrix.data )
05399 {
05400 MTX_ERROR_MSG( "malloc returned FALSE." );
05401 return FALSE;
05402 }
05403 }
05404 else
05405 {
05406 RowMatrix.isReal = FALSE;
05407 RowMatrix.cplx = (stComplex**)malloc( nrows*sizeof(stComplex*) );
05408 if( !RowMatrix.cplx )
05409 {
05410 MTX_ERROR_MSG( "malloc returned FALSE." );
05411 return FALSE;
05412 }
05413 }
05414
05415 RowMatrix.ncols = nrows;
05416 RowMatrix.nrows = ncols;
05417
05418 L = &head;
05419 for( i = 0; i < nrows; i++ )
05420 {
05421 if( L == NULL )
05422 {
05423
05424 MTX_ERROR_MSG( "if( L == NULL ) - this should never happen." );
05425 return FALSE;
05426 }
05427 if( isReal )
05428 {
05429 RowMatrix.data[i] = L->rowptr;
05430 }
05431 else
05432 {
05433 RowMatrix.cplx[i] = L->rowptr_cplx;
05434 }
05435 L = L->next;
05436 }
05437
05438
05439
05440
05441
05442 if( !MTX_Transpose( &RowMatrix, M ) )
05443 {
05444 errorInTranspose = TRUE;
05445 }
05446
05447
05448 L = head.next;
05449 while( L!=NULL )
05450 {
05451 nL = L->next;
05452 if( isReal )
05453 {
05454 free( L->rowptr );
05455 }
05456 else
05457 {
05458 free( L->rowptr_cplx );
05459 }
05460 free(L);
05461 L = nL;
05462 }
05463
05464 if( isReal )
05465 {
05466 free( head.rowptr );
05467 }
05468 else
05469 {
05470 free( head.rowptr_cplx );
05471 }
05472
05473
05474 if( isReal )
05475 {
05476 free( RowMatrix.data );
05477 }
05478 else
05479 {
05480 free( RowMatrix.cplx );
05481 }
05482
05483 if( errorInTranspose )
05484 {
05485 MTX_ERROR_MSG( "if( errorInTranspose )" );
05486 return FALSE;
05487 }
05488 else
05489 {
05490 return TRUE;
05491 }
05492 }
05493
05494
05495
05496
05497
05498 BOOL MTX_ValueToString(
05499 const double value,
05500 const unsigned width,
05501 const unsigned precision,
05502 const BOOL isReal,
05503 const BOOL alignLeft,
05504 char *ValueBuffer,
05505 const unsigned ValueBufferSize
05506 )
05507 {
05508 char format[16];
05509 char valbuf[512];
05510 #ifdef _CRT_SECURE_NO_DEPRECATE
05511 char tmpbuf[1024];
05512 #endif
05513 char* strptr;
05514
05515 if( width == 0 )
05516 {
05517 MTX_ERROR_MSG( "if( width == 0 )" );
05518 return FALSE;
05519 }
05520
05521 valbuf[0] = '\0';
05522
05523 #ifndef _CRT_SECURE_NO_DEPRECATE
05524
05525 if( precision == 0 )
05526 {
05527 if( isReal )
05528 {
05529 if( value < 0 )
05530 {
05531 if( sprintf_s( valbuf, 512, "%d", (int)(-floor( -value + 0.5 )) ) < 0 )
05532 {
05533 MTX_ERROR_MSG( "sprintf_s returned failure." );
05534 return FALSE;
05535 }
05536 }
05537 else
05538 {
05539 if( sprintf_s( valbuf, 512, " %d", (int)(floor( value + 0.5 )) ) < 0 )
05540 {
05541 MTX_ERROR_MSG( "sprintf_s returned failure." );
05542 return FALSE;
05543 }
05544 }
05545 }
05546 else
05547 {
05548 if( value < 0 )
05549 {
05550 if( sprintf_s( valbuf, 512, "%+di", (int)(-floor( -value + 0.5 )) ) < 0 )
05551 {
05552 MTX_ERROR_MSG( "sprintf_s returned failure." );
05553 return FALSE;
05554 }
05555 }
05556 else
05557 {
05558 if( sprintf_s( valbuf, 512, "%+di", (int)(floor( value + 0.5 )) ) < 0 )
05559 {
05560 MTX_ERROR_MSG( "sprintf_s returned failure." );
05561 return FALSE;
05562 }
05563 }
05564 }
05565 }
05566 else
05567 {
05568 if( isReal )
05569 {
05570 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
05571 {
05572 MTX_ERROR_MSG( "sprintf_s returned failure." );
05573 return FALSE;
05574 }
05575 if( sprintf_s( valbuf, 512, format, value ) < 0 )
05576 {
05577 MTX_ERROR_MSG( "sprintf_s returned failure." );
05578 return FALSE;
05579 }
05580 }
05581 else
05582 {
05583 if( sprintf_s( format, 16, "%%+.%dgi", precision ) < 0 )
05584 {
05585 MTX_ERROR_MSG( "sprintf_s returned failure." );
05586 return FALSE;
05587 }
05588 if( sprintf_s( valbuf, 512, format, value ) < 0 )
05589 {
05590 MTX_ERROR_MSG( "sprintf_s returned failure." );
05591 return FALSE;
05592 }
05593 }
05594 }
05595
05596 if( alignLeft )
05597 {
05598 if( sprintf_s( format, 16, "%%-%ds", width ) < 0 )
05599 {
05600 MTX_ERROR_MSG( "sprintf_s returned failure." );
05601 return FALSE;
05602 }
05603 }
05604 else
05605 {
05606 if( sprintf_s( format, 16, "%%%ds", width ) < 0 )
05607 {
05608 MTX_ERROR_MSG( "sprintf_s returned failure." );
05609 return FALSE;
05610 }
05611 }
05612
05613 if( sprintf_s( ValueBuffer, ValueBufferSize, format, valbuf ) < 0 )
05614 {
05615 MTX_ERROR_MSG( "sprintf_s returned failure." );
05616 return FALSE;
05617 }
05618
05619 #else
05620
05621 if( precision == 0 )
05622 {
05623 if( isReal )
05624 {
05625 if( value < 0 )
05626 {
05627 if( sprintf( valbuf, "%d", (int)(-floor( -value + 0.5 )) ) < 0 )
05628 {
05629 MTX_ERROR_MSG( "sprintf returned failure." );
05630 return FALSE;
05631 }
05632 }
05633 else
05634 {
05635 if( sprintf( valbuf, " %d", (int)(floor( value + 0.5 )) ) < 0 )
05636 {
05637 MTX_ERROR_MSG( "sprintf returned failure." );
05638 return FALSE;
05639 }
05640 }
05641 }
05642 else
05643 {
05644 if( value < 0 )
05645 {
05646 if( sprintf( valbuf, "%+di", (int)(-floor( -value + 0.5 )) ) < 0 )
05647 {
05648 MTX_ERROR_MSG( "sprintf returned failure." );
05649 return FALSE;
05650 }
05651 }
05652 else
05653 {
05654 if( sprintf( valbuf, "%+di", (int)(floor( value + 0.5 )) ) < 0 )
05655 {
05656 MTX_ERROR_MSG( "sprintf returned failure." );
05657 return FALSE;
05658 }
05659 }
05660 }
05661 }
05662 else
05663 {
05664 if( isReal )
05665 {
05666 if( sprintf( format, "%% .%dg", precision ) < 0 )
05667 {
05668 MTX_ERROR_MSG( "sprintf returned failure." );
05669 return FALSE;
05670 }
05671 if( sprintf( valbuf, format, value ) < 0 )
05672 {
05673 MTX_ERROR_MSG( "sprintf returned failure." );
05674 return FALSE;
05675 }
05676 }
05677 else
05678 {
05679 if( sprintf( format, "%%+.%dgi", precision ) < 0 )
05680 {
05681 MTX_ERROR_MSG( "sprintf returned failure." );
05682 return FALSE;
05683 }
05684 if( sprintf( valbuf, format, value ) < 0 )
05685 {
05686 MTX_ERROR_MSG( "sprintf returned failure." );
05687 return FALSE;
05688 }
05689 }
05690 }
05691
05692 if( alignLeft )
05693 {
05694 if( sprintf( format, "%%-%ds", width ) < 0 )
05695 {
05696 MTX_ERROR_MSG( "sprintf returned failure." );
05697 return FALSE;
05698 }
05699 }
05700 else
05701 {
05702 if( sprintf( format, "%%%ds", width ) < 0 )
05703 {
05704 MTX_ERROR_MSG( "sprintf returned failure." );
05705 return FALSE;
05706 }
05707 }
05708
05709 if( sprintf( tmpbuf, format, valbuf ) < 0 )
05710 {
05711 MTX_ERROR_MSG( "sprintf returned failure." );
05712 return FALSE;
05713 }
05714 if( strlen(tmpbuf) >= ValueBufferSize )
05715 {
05716 MTX_ERROR_MSG( "ValueBufferSize not sufficient." );
05717 return FALSE;
05718 }
05719 strcpy( ValueBuffer, tmpbuf );
05720
05721 #endif
05722
05723
05724 strptr = strstr( ValueBuffer, "-0" );
05725 if( strptr != NULL )
05726 {
05727 if( strptr[2] == '\0' || strptr[2] == ' ' )
05728 strptr[0] = ' ';
05729 }
05730
05731 return TRUE;
05732 }
05733
05734
05735 BOOL MTX_Print( const MTX *M, const char *path, const unsigned width, const unsigned precision, const BOOL append )
05736 {
05737 unsigned i = 0;
05738 unsigned j = 0;
05739 unsigned k = 0;
05740 char ValueBuffer[512];
05741 FILE* out;
05742
05743 if( MTX_isNull( M ) )
05744 {
05745 MTX_ERROR_MSG( "NULL Matrix" );
05746 return FALSE;
05747 }
05748
05749 if( M->ncols == 0 || M->nrows == 0 )
05750 {
05751 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
05752 return FALSE;
05753 }
05754
05755 if( precision > 200 )
05756 {
05757 MTX_ERROR_MSG( "if( precision > 200 )" );
05758 return FALSE;
05759 }
05760
05761 if( width > 511 )
05762 {
05763 MTX_ERROR_MSG( "if( width > 511 )" );
05764 return FALSE;
05765 }
05766
05767 ValueBuffer[0] = '\0';
05768
05769 if( append )
05770 {
05771 #ifndef _CRT_SECURE_NO_DEPRECATE
05772 if( fopen_s( &out, path, "at+" ) != 0 )
05773 {
05774 MTX_ERROR_MSG( "fopen_s returned failure." );
05775 return FALSE;
05776 }
05777 #else
05778 out = fopen( path, "at+" );
05779 #endif
05780 }
05781 else
05782 {
05783 #ifndef _CRT_SECURE_NO_DEPRECATE
05784 if( fopen_s( &out, path, "w" ) != 0 )
05785 {
05786 MTX_ERROR_MSG( "fopen_s returned failure." );
05787 return FALSE;
05788 }
05789 #else
05790 out = fopen( path, "w" );
05791 #endif
05792 }
05793 if( !out )
05794 {
05795 #ifndef _CRT_SECURE_NO_DEPRECATE
05796 if( sprintf_s( ValueBuffer, 512, "Unable to open %s.", path ) > 0 )
05797 MTX_ERROR_MSG( ValueBuffer );
05798 #else
05799 if( sprintf( ValueBuffer, "Unable to open %s.", path ) > 0 )
05800 MTX_ERROR_MSG( ValueBuffer );
05801 #endif
05802 return FALSE;
05803 }
05804
05805 if( M->isReal )
05806 {
05807 for( i = 0; i < M->nrows; i++ )
05808 {
05809 for( j = 0; j < M->ncols; j++ )
05810 {
05811 MTX_ValueToString( M->data[j][i], width, precision, TRUE, TRUE, ValueBuffer, 512 );
05812 fprintf( out, ValueBuffer );
05813 }
05814 fprintf( out, "\n" );
05815 }
05816 }
05817 else
05818 {
05819 for( i = 0; i < M->nrows; i++ )
05820 {
05821 for( j = 0; j < M->ncols; j++ )
05822 {
05823 if( M->cplx[j][i].im == 0 )
05824 {
05825
05826 MTX_ValueToString( M->cplx[j][i].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
05827 fprintf( out, ValueBuffer );
05828 for( k = 0; k < width; k++ )
05829 fprintf( out, " " );
05830 }
05831 else
05832 {
05833
05834 MTX_ValueToString( M->cplx[j][i].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
05835 fprintf( out, ValueBuffer );
05836 MTX_ValueToString( M->cplx[j][i].im, width, precision, FALSE, TRUE, ValueBuffer, 512 );
05837 fprintf( out, ValueBuffer );
05838 }
05839 }
05840 fprintf( out, "\n" );
05841 }
05842 }
05843 fclose(out);
05844
05845 return TRUE;
05846 }
05847
05848 BOOL MTX_Print_ToBuffer( const MTX *M, char *buffer, const unsigned maxlength, const unsigned width, const unsigned precision )
05849 {
05850 unsigned i = 0;
05851 unsigned j = 0;
05852 unsigned k = 0;
05853 unsigned scount = 0;
05854 unsigned dcount = 0;
05855 BOOL endOfBuffer = FALSE;
05856 char ValueBuffer[512];
05857
05858 if( MTX_isNull( M ) )
05859 {
05860 MTX_ERROR_MSG( "NULL Matrix" );
05861 return FALSE;
05862 }
05863
05864 if( M->ncols == 0 || M->nrows == 0 )
05865 {
05866 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
05867 return FALSE;
05868 }
05869
05870 if( buffer == NULL )
05871 {
05872 MTX_ERROR_MSG( "buffer is NULL." );
05873 return FALSE;
05874 }
05875
05876 if( maxlength == 0 )
05877 {
05878 MTX_ERROR_MSG( "if( maxlength == 0 )" );
05879 return FALSE;
05880 }
05881
05882 if( precision > 200 )
05883 {
05884 MTX_ERROR_MSG( "if( precision > 200 )" );
05885 return FALSE;
05886 }
05887
05888 if( width > 511 )
05889 {
05890 MTX_ERROR_MSG( "if( width > 511 )" );
05891 return FALSE;
05892 }
05893
05894 ValueBuffer[0] = '\0';
05895
05896 for( i = 0; i < M->nrows; i++ )
05897 {
05898 for( j = 0; j < M->ncols; j++ )
05899 {
05900 if( M->isReal )
05901 {
05902 MTX_ValueToString( M->data[j][i], width, precision, TRUE, TRUE, ValueBuffer, 512 );
05903 if( scount + width >= maxlength )
05904 {
05905 endOfBuffer = TRUE;
05906 break;
05907 }
05908 #ifndef _CRT_SECURE_NO_DEPRECATE
05909 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
05910 if( dcount < 0 )
05911 {
05912 MTX_ERROR_MSG( "sprintf_s returned failure." );
05913 return FALSE;
05914 }
05915 scount += dcount;
05916 #else
05917 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
05918 if( dcount < 0 )
05919 {
05920 MTX_ERROR_MSG( "sprintf returned failure." );
05921 return FALSE;
05922 }
05923 scount += dcount;
05924 #endif
05925 }
05926 else
05927 {
05928 if( M->cplx[j][i].im == 0 )
05929 {
05930
05931 MTX_ValueToString( M->cplx[j][i].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
05932 if( scount + width >= maxlength )
05933 {
05934 endOfBuffer = TRUE;
05935 break;
05936 }
05937 #ifndef _CRT_SECURE_NO_DEPRECATE
05938 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
05939 if( dcount < 0 )
05940 {
05941 MTX_ERROR_MSG( "sprintf_s returned failure." );
05942 return FALSE;
05943 }
05944 scount += dcount;
05945
05946 for( k = 0; k < width; k++ )
05947 {
05948 dcount = sprintf_s( buffer+scount, maxlength-scount, " " );
05949 if( dcount < 0 )
05950 {
05951 MTX_ERROR_MSG( "sprintf_s returned failure." );
05952 return FALSE;
05953 }
05954 scount += dcount;
05955 }
05956 #else
05957 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
05958 if( dcount < 0 )
05959 {
05960 MTX_ERROR_MSG( "sprintf returned failure." );
05961 return FALSE;
05962 }
05963 scount += dcount;
05964
05965 for( k = 0; k < width; k++ )
05966 {
05967 dcount = sprintf( buffer+scount, " " );
05968 if( dcount < 0 )
05969 {
05970 MTX_ERROR_MSG( "sprintf returned failure." );
05971 return FALSE;
05972 }
05973 scount += dcount;
05974 }
05975 #endif
05976 }
05977 else
05978 {
05979
05980 MTX_ValueToString( M->cplx[j][i].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
05981 if( scount + width >= maxlength )
05982 {
05983 endOfBuffer = TRUE;
05984 break;
05985 }
05986
05987 #ifndef _CRT_SECURE_NO_DEPRECATE
05988 dcount = sprintf_s( buffer+scount, maxlength - scount, "%s", ValueBuffer );
05989 if( dcount < 0 )
05990 {
05991 MTX_ERROR_MSG( "sprintf_s returned failure." );
05992 return FALSE;
05993 }
05994 scount += dcount;
05995 #else
05996 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
05997 if( dcount < 0 )
05998 {
05999 MTX_ERROR_MSG( "sprintf returned failure." );
06000 return FALSE;
06001 }
06002 scount += dcount;
06003 #endif
06004
06005 MTX_ValueToString( M->cplx[j][i].im, width, precision, FALSE, TRUE, ValueBuffer, 512 );
06006 if( scount + width >= maxlength )
06007 {
06008 endOfBuffer = TRUE;
06009 break;
06010 }
06011
06012 #ifndef _CRT_SECURE_NO_DEPRECATE
06013 dcount = sprintf_s( buffer+scount, maxlength - scount, "%s", ValueBuffer );
06014 if( dcount < 0 )
06015 {
06016 MTX_ERROR_MSG( "sprintf_s returned failure." );
06017 return FALSE;
06018 }
06019 scount += dcount;
06020 #else
06021 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
06022 if( dcount < 0 )
06023 {
06024 MTX_ERROR_MSG( "sprintf returned failure." );
06025 return FALSE;
06026 }
06027 scount += dcount;
06028 #endif
06029 }
06030 }
06031 }
06032 if( endOfBuffer )
06033 break;
06034 if( scount + 2 >= maxlength )
06035 break;
06036
06037 #ifndef _CRT_SECURE_NO_DEPRECATE
06038 dcount = sprintf_s( buffer+scount, maxlength - scount, "\n" );
06039 if( dcount < 0 )
06040 {
06041 MTX_ERROR_MSG( "sprintf returned failure." );
06042 return FALSE;
06043 }
06044 scount += dcount;
06045 #else
06046 dcount = sprintf( buffer+scount, "\n" );
06047 if( dcount < 0 )
06048 {
06049 MTX_ERROR_MSG( "sprintf returned failure." );
06050 return FALSE;
06051 }
06052 scount += dcount;
06053 #endif
06054 }
06055
06056 return TRUE;
06057 }
06058
06059
06060
06061
06062
06063 BOOL MTX_PrintAutoWidth( const MTX *M, const char *path, const unsigned precision, const BOOL append )
06064 {
06065 unsigned i = 0;
06066 unsigned j = 0;
06067 unsigned k = 0;
06068 unsigned n = 0;
06069 unsigned maxwidth = 0;
06070 unsigned maxwidth_im = 0;
06071 unsigned length = 0;
06072 unsigned *maxColumnWidth;
06073 char format[16];
06074 char ValueBuffer[512];
06075 FILE* out;
06076
06077 if( MTX_isNull( M ) )
06078 {
06079 MTX_ERROR_MSG( "NULL Matrix" );
06080 return FALSE;
06081 }
06082
06083 if( M->ncols == 0 || M->nrows == 0 )
06084 {
06085 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
06086 return FALSE;
06087 }
06088
06089 if( precision > 200 )
06090 {
06091 MTX_ERROR_MSG( "if( precision > 200 )" );
06092 return FALSE;
06093 }
06094
06095 ValueBuffer[0] = '\0';
06096
06097 if( append )
06098 {
06099 #ifndef _CRT_SECURE_NO_DEPRECATE
06100 if( fopen_s( &out, path, "at+" ) != 0 )
06101 {
06102 MTX_ERROR_MSG( "fopen_s failed to open the file." );
06103 return FALSE;
06104 }
06105 #else
06106 out = fopen( path, "at+" );
06107 #endif
06108 }
06109 else
06110 {
06111 #ifndef _CRT_SECURE_NO_DEPRECATE
06112 if( fopen_s( &out, path, "w" ) != 0 )
06113 {
06114 MTX_ERROR_MSG( "fopen_s failed to open the file." );
06115 return FALSE;
06116 }
06117 #else
06118 out = fopen( path, "w" );
06119 #endif
06120 }
06121 if( !out )
06122 {
06123 #ifndef _CRT_SECURE_NO_DEPRECATE
06124 if( sprintf_s( ValueBuffer, 512, "Unable to open %s.", path ) > 0 )
06125 MTX_ERROR_MSG( ValueBuffer );
06126 #else
06127 if( sprintf( ValueBuffer, "Unable to open %s.", path ) > 0 )
06128 MTX_ERROR_MSG( ValueBuffer );
06129 #endif
06130 return FALSE;
06131 }
06132
06133 if( M->isReal )
06134 n = M->ncols;
06135 else
06136 n = M->ncols*2;
06137
06138 maxColumnWidth = (unsigned*)malloc( sizeof(unsigned)*n );
06139 if( !maxColumnWidth )
06140 {
06141 fclose(out);
06142 MTX_ERROR_MSG( "malloc returned NULL." );
06143 return FALSE;
06144 }
06145
06146 if( M->isReal )
06147 {
06148 for( j = 0; j < M->ncols; j++ )
06149 {
06150
06151 maxwidth = 0;
06152 for( i = 0; i < M->nrows; i++ )
06153 {
06154 #ifndef _CRT_SECURE_NO_DEPRECATE
06155 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06156 {
06157 MTX_ERROR_MSG( "sprintf_s returned failure." );
06158 return FALSE;
06159 }
06160 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
06161 {
06162 MTX_ERROR_MSG( "sprintf_s returned failure." );
06163 return FALSE;
06164 }
06165 #else
06166 if( sprintf( format, "%% .%dg", precision ) < 0 )
06167 {
06168 MTX_ERROR_MSG( "sprintf returned failure." );
06169 return FALSE;
06170 }
06171 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
06172 {
06173 MTX_ERROR_MSG( "sprintf returned failure." );
06174 return FALSE;
06175 }
06176 #endif
06177 length = (unsigned int)strlen( ValueBuffer );
06178 if( length > maxwidth )
06179 maxwidth = length;
06180 }
06181 maxColumnWidth[j] = maxwidth+1;
06182 }
06183 }
06184 else
06185 {
06186 k = 0;
06187 for( j = 0; j < M->ncols; j++ )
06188 {
06189
06190 maxwidth = 0;
06191 maxwidth_im = 0;
06192 for( i = 0; i < M->nrows; i++ )
06193 {
06194 #ifndef _CRT_SECURE_NO_DEPRECATE
06195 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06196 {
06197 MTX_ERROR_MSG( "sprintf_s returned failure." );
06198 return FALSE;
06199 }
06200 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
06201 {
06202 MTX_ERROR_MSG( "sprintf_s returned failure." );
06203 return FALSE;
06204 }
06205 #else
06206 if( sprintf( format, "%% .%dg", precision ) < 0 )
06207 {
06208 MTX_ERROR_MSG( "sprintf returned failure." );
06209 return FALSE;
06210 }
06211 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
06212 {
06213 MTX_ERROR_MSG( "sprintf returned failure." );
06214 return FALSE;
06215 }
06216 #endif
06217
06218 length = (unsigned int)strlen( ValueBuffer );
06219 if( length > maxwidth )
06220 maxwidth = length;
06221
06222 #ifndef _CRT_SECURE_NO_DEPRECATE
06223 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
06224 {
06225 MTX_ERROR_MSG( "sprintf_s returned failure." );
06226 return FALSE;
06227 }
06228 #else
06229 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
06230 {
06231 MTX_ERROR_MSG( "sprintf returned failure." );
06232 return FALSE;
06233 }
06234 #endif
06235 length = (unsigned int)strlen( ValueBuffer );
06236 if( length > maxwidth_im )
06237 maxwidth_im = length;
06238 }
06239 maxColumnWidth[k] = maxwidth+1;
06240 k++;
06241 maxColumnWidth[k] = maxwidth_im+1;
06242 k++;
06243 }
06244
06245 }
06246
06247 if( M->isReal )
06248 {
06249 for( i = 0; i < M->nrows; i++ )
06250 {
06251 for( j = 0; j < M->ncols; j++ )
06252 {
06253 MTX_ValueToString( M->data[j][i], maxColumnWidth[j], precision, TRUE, TRUE, ValueBuffer, 512 );
06254 fprintf( out, ValueBuffer );
06255 }
06256 fprintf( out, "\n" );
06257 }
06258 }
06259 else
06260 {
06261 for( i = 0; i < M->nrows; i++ )
06262 {
06263 for( j = 0; j < M->ncols; j++ )
06264 {
06265 if( M->cplx[j][i].im == 0 )
06266 {
06267
06268 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06269 fprintf( out, ValueBuffer );
06270 for( k = 0; k < maxColumnWidth[j*2+1]; k++ )
06271 fprintf( out, " " );
06272 }
06273 else
06274 {
06275
06276 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06277 fprintf( out, ValueBuffer );
06278 MTX_ValueToString( M->cplx[j][i].im, maxColumnWidth[j*2+1], precision, FALSE, TRUE, ValueBuffer, 512 );
06279 fprintf( out, ValueBuffer );
06280 }
06281 }
06282 fprintf( out, "\n" );
06283 }
06284 }
06285
06286 fclose(out);
06287
06288 free(maxColumnWidth);
06289
06290 return TRUE;
06291 }
06292
06293
06294 BOOL MTX_PrintStdoutAutoWidth( const MTX *M, const unsigned precision )
06295 {
06296 unsigned i = 0;
06297 unsigned j = 0;
06298 unsigned k = 0;
06299 unsigned n = 0;
06300 unsigned maxwidth = 0;
06301 unsigned maxwidth_im = 0;
06302 unsigned length = 0;
06303 unsigned *maxColumnWidth;
06304 char format[16];
06305 char ValueBuffer[512];
06306
06307 if( MTX_isNull( M ) )
06308 {
06309 MTX_ERROR_MSG( "NULL Matrix" );
06310 return FALSE;
06311 }
06312
06313 if( M->ncols == 0 || M->nrows == 0 )
06314 {
06315 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
06316 return FALSE;
06317 }
06318
06319 if( precision > 200 )
06320 {
06321 MTX_ERROR_MSG( "if( precision > 200 )" );
06322 return FALSE;
06323 }
06324
06325 ValueBuffer[0] = '\0';
06326
06327 if( M->isReal )
06328 n = M->ncols;
06329 else
06330 n = M->ncols*2;
06331
06332 maxColumnWidth = (unsigned*)malloc( sizeof(unsigned)*n );
06333 if( !maxColumnWidth )
06334 {
06335 MTX_ERROR_MSG( "if( !maxColumnWidth )" );
06336 return FALSE;
06337 }
06338
06339 if( M->isReal )
06340 {
06341 for( j = 0; j < M->ncols; j++ )
06342 {
06343
06344 maxwidth = 0;
06345 for( i = 0; i < M->nrows; i++ )
06346 {
06347 #ifndef _CRT_SECURE_NO_DEPRECATE
06348 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06349 {
06350 MTX_ERROR_MSG( "sprintf_s returned failure." );
06351 return FALSE;
06352 }
06353 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
06354 {
06355 MTX_ERROR_MSG( "sprintf_s returned failure." );
06356 return FALSE;
06357 }
06358 #else
06359 if( sprintf( format, "%% .%dg", precision ) < 0 )
06360 {
06361 MTX_ERROR_MSG( "sprintf returned failure." );
06362 return FALSE;
06363 }
06364 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
06365 {
06366 MTX_ERROR_MSG( "sprintf returned failure." );
06367 return FALSE;
06368 }
06369 #endif
06370 length = (unsigned int)strlen( ValueBuffer );
06371 if( length > maxwidth )
06372 maxwidth = length;
06373 }
06374 maxColumnWidth[j] = maxwidth+1;
06375 }
06376 }
06377 else
06378 {
06379 k = 0;
06380 for( j = 0; j < M->ncols; j++ )
06381 {
06382
06383 maxwidth = 0;
06384 maxwidth_im = 0;
06385 for( i = 0; i < M->nrows; i++ )
06386 {
06387 #ifndef _CRT_SECURE_NO_DEPRECATE
06388 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06389 {
06390 MTX_ERROR_MSG( "sprintf_s returned failure." );
06391 return FALSE;
06392 }
06393 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
06394 {
06395 MTX_ERROR_MSG( "sprintf_s returned failure." );
06396 return FALSE;
06397 }
06398 #else
06399 if( sprintf( format, "%% .%dg", precision ) < 0 )
06400 {
06401 MTX_ERROR_MSG( "sprintf returned failure." );
06402 return FALSE;
06403 }
06404 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
06405 {
06406 MTX_ERROR_MSG( "sprintf returned failure." );
06407 return FALSE;
06408 }
06409 #endif
06410
06411 length = (unsigned int)strlen( ValueBuffer );
06412 if( length > maxwidth )
06413 maxwidth = length;
06414
06415 #ifndef _CRT_SECURE_NO_DEPRECATE
06416 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
06417 {
06418 MTX_ERROR_MSG( "sprintf_s returned failure." );
06419 return FALSE;
06420 }
06421 #else
06422 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
06423 {
06424 MTX_ERROR_MSG( "sprintf returned failure." );
06425 return FALSE;
06426 }
06427 #endif
06428 length = (unsigned int)strlen( ValueBuffer );
06429 if( length > maxwidth_im )
06430 maxwidth_im = length;
06431 }
06432 maxColumnWidth[k] = maxwidth+1;
06433 k++;
06434 maxColumnWidth[k] = maxwidth_im+1;
06435 k++;
06436 }
06437
06438 }
06439
06440 if( M->isReal )
06441 {
06442 for( i = 0; i < M->nrows; i++ )
06443 {
06444 for( j = 0; j < M->ncols; j++ )
06445 {
06446 MTX_ValueToString( M->data[j][i], maxColumnWidth[j], precision, TRUE, TRUE, ValueBuffer, 512 );
06447 printf( ValueBuffer );
06448 }
06449 printf( "\n" );
06450 }
06451 }
06452 else
06453 {
06454 for( i = 0; i < M->nrows; i++ )
06455 {
06456 for( j = 0; j < M->ncols; j++ )
06457 {
06458 if( M->cplx[j][i].im == 0 )
06459 {
06460
06461 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06462 printf( ValueBuffer );
06463 for( k = 0; k < maxColumnWidth[j*2+1]; k++ )
06464 printf( " " );
06465 }
06466 else
06467 {
06468
06469 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06470 printf( ValueBuffer );
06471 MTX_ValueToString( M->cplx[j][i].im, maxColumnWidth[j*2+1], precision, FALSE, TRUE, ValueBuffer, 512 );
06472 printf( ValueBuffer );
06473 }
06474 }
06475 printf( "\n" );
06476 }
06477 }
06478
06479 free(maxColumnWidth);
06480
06481 return TRUE;
06482 }
06483
06484
06485
06486 BOOL MTX_PrintAutoWidth_ToBuffer( const MTX *M, char *buffer, const unsigned maxlength, const unsigned precision )
06487 {
06488 unsigned i = 0;
06489 unsigned j = 0;
06490 unsigned k = 0;
06491 unsigned n = 0;
06492 unsigned maxwidth = 0;
06493 unsigned maxwidth_im = 0;
06494 unsigned length = 0;
06495 unsigned scount = 0;
06496 unsigned dcount = 0;
06497 BOOL endOfBuffer = FALSE;
06498 unsigned *maxColumnWidth;
06499 char format[16];
06500 char ValueBuffer[512];
06501
06502 if( MTX_isNull( M ) )
06503 {
06504 MTX_ERROR_MSG( "NULL Matrix" );
06505 return FALSE;
06506 }
06507
06508 if( buffer == NULL )
06509 {
06510 MTX_ERROR_MSG( "buffer is a NULL pointer." );
06511 return FALSE;
06512 }
06513
06514 if( maxlength == 0 )
06515 {
06516 MTX_ERROR_MSG( "if( maxlength == 0 )" );
06517 return FALSE;
06518 }
06519
06520 if( M->ncols == 0 || M->nrows == 0 )
06521 {
06522 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
06523 return FALSE;
06524 }
06525
06526 if( precision > 200 )
06527 {
06528 MTX_ERROR_MSG( "if( precision > 200 )" );
06529 return FALSE;
06530 }
06531
06532 ValueBuffer[0] = '\0';
06533
06534 if( M->isReal )
06535 n = M->ncols;
06536 else
06537 n = M->ncols*2;
06538
06539 maxColumnWidth = (unsigned*)malloc( sizeof(unsigned)*n );
06540 if( !maxColumnWidth )
06541 {
06542 MTX_ERROR_MSG( "malloc returned NULL." );
06543 return FALSE;
06544 }
06545
06546 if( M->isReal )
06547 {
06548 for( j = 0; j < M->ncols; j++ )
06549 {
06550
06551 maxwidth = 0;
06552 for( i = 0; i < M->nrows; i++ )
06553 {
06554 #ifndef _CRT_SECURE_NO_DEPRECATE
06555 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06556 {
06557 MTX_ERROR_MSG( "sprintf_s returned failure." );
06558 return FALSE;
06559 }
06560 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
06561 {
06562 MTX_ERROR_MSG( "sprintf_s returned failure." );
06563 return FALSE;
06564 }
06565 #else
06566 if( sprintf( format, "%% .%dg", precision ) < 0 )
06567 {
06568 MTX_ERROR_MSG( "sprintf returned failure." );
06569 return FALSE;
06570 }
06571 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
06572 {
06573 MTX_ERROR_MSG( "sprintf returned failure." );
06574 return FALSE;
06575 }
06576 #endif
06577 length = (unsigned int)strlen( ValueBuffer );
06578 if( length > maxwidth )
06579 maxwidth = length;
06580 }
06581 maxColumnWidth[j] = maxwidth+1;
06582 }
06583 }
06584 else
06585 {
06586 k = 0;
06587 for( j = 0; j < M->ncols; j++ )
06588 {
06589
06590 maxwidth = 0;
06591 maxwidth_im = 0;
06592 for( i = 0; i < M->nrows; i++ )
06593 {
06594 #ifndef _CRT_SECURE_NO_DEPRECATE
06595 if( sprintf_s( format, 16, "%% .%dg", precision ) < 0 )
06596 {
06597 MTX_ERROR_MSG( "sprintf_s returned failure." );
06598 return FALSE;
06599 }
06600 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
06601 {
06602 MTX_ERROR_MSG( "sprintf_s returned failure." );
06603 return FALSE;
06604 }
06605 #else
06606 if( sprintf( format, "%% .%dg", precision ) < 0 )
06607 {
06608 MTX_ERROR_MSG( "sprintf returned failure." );
06609 return FALSE;
06610 }
06611 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
06612 {
06613 MTX_ERROR_MSG( "sprintf returned failure." );
06614 return FALSE;
06615 }
06616 #endif
06617 length = (unsigned int)strlen( ValueBuffer );
06618 if( length > maxwidth )
06619 maxwidth = length;
06620
06621 #ifndef _CRT_SECURE_NO_DEPRECATE
06622 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
06623 {
06624 MTX_ERROR_MSG( "sprintf_s returned failure." );
06625 return FALSE;
06626 }
06627 #else
06628 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
06629 {
06630 MTX_ERROR_MSG( "sprintf returned failure." );
06631 return FALSE;
06632 }
06633 #endif
06634 length = (unsigned int)strlen( ValueBuffer );
06635 if( length > maxwidth_im )
06636 maxwidth_im = length;
06637 }
06638 maxColumnWidth[k] = maxwidth+1;
06639 k++;
06640 maxColumnWidth[k] = maxwidth_im+1;
06641 k++;
06642 }
06643 }
06644
06645 if( M->isReal )
06646 {
06647 for( i = 0; i < M->nrows; i++ )
06648 {
06649 for( j = 0; j < M->ncols; j++ )
06650 {
06651 MTX_ValueToString( M->data[j][i], maxColumnWidth[j], precision, TRUE, TRUE, ValueBuffer, 512 );
06652 if( scount+maxColumnWidth[j] >= maxlength )
06653 {
06654 endOfBuffer = TRUE;
06655 break;
06656 }
06657 #ifndef _CRT_SECURE_NO_DEPRECATE
06658 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
06659 if( dcount < 0 )
06660 {
06661 MTX_ERROR_MSG( "sprintf_s returned failure." );
06662 return FALSE;
06663 }
06664 scount += dcount;
06665 #else
06666 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
06667 if( dcount < 0 )
06668 {
06669 MTX_ERROR_MSG( "sprintf returned failure." );
06670 return FALSE;
06671 }
06672 scount += dcount;
06673 #endif
06674 }
06675 if( endOfBuffer )
06676 break;
06677 if( scount+2 >= maxlength )
06678 break;
06679 #ifndef _CRT_SECURE_NO_DEPRECATE
06680 dcount = sprintf_s( buffer+scount, maxlength-scount, "\n" );
06681 if( dcount < 0 )
06682 {
06683 MTX_ERROR_MSG( "sprintf_s returned failure." );
06684 return FALSE;
06685 }
06686 scount += dcount;
06687 #else
06688 dcount = sprintf( buffer+scount, "\n" );
06689 if( dcount < 0 )
06690 {
06691 MTX_ERROR_MSG( "sprintf returned failure." );
06692 return FALSE;
06693 }
06694 scount += dcount;
06695 #endif
06696 }
06697 }
06698 else
06699 {
06700 for( i = 0; i < M->nrows; i++ )
06701 {
06702 for( j = 0; j < M->ncols; j++ )
06703 {
06704 if( M->cplx[j][i].im == 0 )
06705 {
06706
06707 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06708 if( scount+maxColumnWidth[j] >= maxlength )
06709 {
06710 endOfBuffer = TRUE;
06711 break;
06712 }
06713 #ifndef _CRT_SECURE_NO_DEPRECATE
06714 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
06715 if( dcount < 0 )
06716 {
06717 MTX_ERROR_MSG( "sprintf_s returned failure." );
06718 return FALSE;
06719 }
06720 scount += dcount;
06721
06722 for( k = 0; k < maxColumnWidth[j*2+1]; k++ )
06723 {
06724 dcount = sprintf_s( buffer+scount, maxlength-scount, " " );
06725 if( dcount < 0 )
06726 {
06727 MTX_ERROR_MSG( "sprintf_s returned failure." );
06728 return FALSE;
06729 }
06730 scount += dcount;
06731 }
06732 #else
06733 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
06734 if( dcount < 0 )
06735 {
06736 MTX_ERROR_MSG( "sprintf returned failure." );
06737 return FALSE;
06738 }
06739 scount += dcount;
06740
06741 for( k = 0; k < maxColumnWidth[j*2+1]; k++ )
06742 {
06743 dcount = sprintf( buffer+scount, " " );
06744 if( dcount < 0 )
06745 {
06746 MTX_ERROR_MSG( "sprintf returned failure." );
06747 return FALSE;
06748 }
06749 scount += dcount;
06750 }
06751 #endif
06752 }
06753 else
06754 {
06755
06756 MTX_ValueToString( M->cplx[j][i].re, maxColumnWidth[j*2], precision, TRUE, FALSE, ValueBuffer, 512 );
06757 if( scount+maxColumnWidth[j] >= maxlength )
06758 {
06759 endOfBuffer = TRUE;
06760 break;
06761 }
06762 #ifndef _CRT_SECURE_NO_DEPRECATE
06763 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
06764 if( dcount < 0 )
06765 {
06766 MTX_ERROR_MSG( "sprintf_s returned failure." );
06767 return FALSE;
06768 }
06769 scount += dcount;
06770 #else
06771 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
06772 if( dcount < 0 )
06773 {
06774 MTX_ERROR_MSG( "sprintf returned failure." );
06775 return FALSE;
06776 }
06777 scount += dcount;
06778 #endif
06779
06780 MTX_ValueToString( M->cplx[j][i].im, maxColumnWidth[j*2+1], precision, FALSE, TRUE, ValueBuffer, 512 );
06781 if( scount+maxColumnWidth[j] >= maxlength )
06782 {
06783 endOfBuffer = TRUE;
06784 break;
06785 }
06786 #ifndef _CRT_SECURE_NO_DEPRECATE
06787 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
06788 if( dcount < 0 )
06789 {
06790 MTX_ERROR_MSG( "sprintf_s returned failure." );
06791 return FALSE;
06792 }
06793 scount += dcount;
06794 #else
06795 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
06796 if( dcount < 0 )
06797 {
06798 MTX_ERROR_MSG( "sprintf returned failure." );
06799 return FALSE;
06800 }
06801 scount += dcount;
06802 #endif
06803 }
06804 }
06805 if( endOfBuffer )
06806 break;
06807 if( scount+2 >= maxlength )
06808 break;
06809
06810 #ifndef _CRT_SECURE_NO_DEPRECATE
06811 dcount = sprintf_s( buffer+scount, maxlength-scount, "\n" );
06812 if( dcount < 0 )
06813 {
06814 MTX_ERROR_MSG( "sprintf_s returned failure." );
06815 return FALSE;
06816 }
06817 scount += dcount;
06818 #else
06819 dcount = sprintf( buffer+scount, "\n" );
06820 if( dcount < 0 )
06821 {
06822 MTX_ERROR_MSG( "sprintf returned failure." );
06823 return FALSE;
06824 }
06825 scount += dcount;
06826 #endif
06827 }
06828 }
06829
06830 free(maxColumnWidth);
06831
06832 return TRUE;
06833 }
06834
06835 BOOL MTX_PrintDelimited( const MTX *M, const char *path, const unsigned precision, const char delimiter, const BOOL append )
06836 {
06837 unsigned i = 0;
06838 unsigned j = 0;
06839 char format[16];
06840 char ValueBuffer[512];
06841 FILE* out;
06842
06843 if( MTX_isNull( M ) )
06844 {
06845 MTX_ERROR_MSG( "NULL Matrix" );
06846 return FALSE;
06847 }
06848
06849 if( M->ncols == 0 || M->nrows == 0 )
06850 {
06851 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
06852 return FALSE;
06853 }
06854
06855 if( precision > 200 )
06856 {
06857 MTX_ERROR_MSG( "if( precision > 200 )" );
06858 return FALSE;
06859 }
06860
06861 ValueBuffer[0] = '\0';
06862
06863 if( append )
06864 {
06865 #ifndef _CRT_SECURE_NO_DEPRECATE
06866 if( fopen_s( &out, path, "at+" ) != 0 )
06867 {
06868 MTX_ERROR_MSG( "fopen_s failed to open the file." );
06869 return FALSE;
06870 }
06871 #else
06872 out = fopen( path, "at+" );
06873 #endif
06874 }
06875 else
06876 {
06877 #ifndef _CRT_SECURE_NO_DEPRECATE
06878 if( fopen_s( &out, path, "w" ) != 0 )
06879 {
06880 MTX_ERROR_MSG( "fopen_s failed to open the file." );
06881 return FALSE;
06882 }
06883 #else
06884 out = fopen( path, "w" );
06885 #endif
06886 }
06887 if( !out )
06888 {
06889 #ifndef _CRT_SECURE_NO_DEPRECATE
06890 if( sprintf_s( ValueBuffer, 512, "Unable to open %s", path ) > 0 )
06891 MTX_ERROR_MSG( ValueBuffer );
06892 #else
06893 if( sprintf( ValueBuffer, "Unable to open %s", path ) > 0 )
06894 MTX_ERROR_MSG( ValueBuffer );
06895 #endif
06896 return FALSE;
06897 }
06898
06899 if( M->isReal )
06900 {
06901 for( i = 0; i < M->nrows; i++ )
06902 {
06903 for( j = 0; j < M->ncols-1; j++ )
06904 {
06905 #ifndef _CRT_SECURE_NO_DEPRECATE
06906 if( sprintf_s( format, 16, "%%.%dg%c", precision, delimiter ) < 0 )
06907 {
06908 MTX_ERROR_MSG( "sprintf_s returned failure." );
06909 return FALSE;
06910 }
06911 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
06912 {
06913 MTX_ERROR_MSG( "sprintf_s returned failure." );
06914 return FALSE;
06915 }
06916 #else
06917 if( sprintf( format, "%%.%dg%c", precision, delimiter ) < 0 )
06918 {
06919 MTX_ERROR_MSG( "sprintf returned failure." );
06920 return FALSE;
06921 }
06922 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
06923 {
06924 MTX_ERROR_MSG( "sprintf returned failure." );
06925 return FALSE;
06926 }
06927 #endif
06928 fprintf( out, ValueBuffer );
06929 }
06930 #ifndef _CRT_SECURE_NO_DEPRECATE
06931 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
06932 {
06933 MTX_ERROR_MSG( "sprintf_s returned failure." );
06934 return FALSE;
06935 }
06936 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
06937 {
06938 MTX_ERROR_MSG( "sprintf_s returned failure." );
06939 return FALSE;
06940 }
06941 #else
06942 if( sprintf( format, "%%.%dg", precision ) < 0 )
06943 {
06944 MTX_ERROR_MSG( "sprintf returned failure." );
06945 return FALSE;
06946 }
06947 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
06948 {
06949 MTX_ERROR_MSG( "sprintf returned failure." );
06950 return FALSE;
06951 }
06952 #endif
06953 fprintf( out, ValueBuffer );
06954 fprintf( out, "\n" );
06955 }
06956 }
06957 else
06958 {
06959 for( i = 0; i < M->nrows; i++ )
06960 {
06961 for( j = 0; j < M->ncols-1; j++ )
06962 {
06963 if( M->cplx[j][i].im == 0 )
06964 {
06965
06966 #ifndef _CRT_SECURE_NO_DEPRECATE
06967 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
06968 {
06969 MTX_ERROR_MSG( "sprintf_s returned failure." );
06970 return FALSE;
06971 }
06972 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
06973 {
06974 MTX_ERROR_MSG( "sprintf_s returned failure." );
06975 return FALSE;
06976 }
06977 #else
06978 if( sprintf( format, "%%.%dg", precision ) < 0 )
06979 {
06980 MTX_ERROR_MSG( "sprintf returned failure." );
06981 return FALSE;
06982 }
06983 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
06984 {
06985 MTX_ERROR_MSG( "sprintf returned failure." );
06986 return FALSE;
06987 }
06988 #endif
06989 fprintf( out, ValueBuffer );
06990 }
06991 else
06992 {
06993
06994 #ifndef _CRT_SECURE_NO_DEPRECATE
06995 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
06996 {
06997 MTX_ERROR_MSG( "sprintf_s returned failure." );
06998 return FALSE;
06999 }
07000 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07001 {
07002 MTX_ERROR_MSG( "sprintf_s returned failure." );
07003 return FALSE;
07004 }
07005 #else
07006 if( sprintf( format, "%%.%dg", precision ) < 0 )
07007 {
07008 MTX_ERROR_MSG( "sprintf returned failure." );
07009 return FALSE;
07010 }
07011 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07012 {
07013 MTX_ERROR_MSG( "sprintf returned failure." );
07014 return FALSE;
07015 }
07016 #endif
07017 fprintf( out, ValueBuffer );
07018
07019 #ifndef _CRT_SECURE_NO_DEPRECATE
07020 if( sprintf_s( format, 16, "%%+.%dgi%c", precision, delimiter ) < 0 )
07021 {
07022 MTX_ERROR_MSG( "sprintf_s returned failure." );
07023 return FALSE;
07024 }
07025 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
07026 {
07027 MTX_ERROR_MSG( "sprintf_s returned failure." );
07028 return FALSE;
07029 }
07030 #else
07031 if( sprintf( format, "%%+.%dgi%c", precision, delimiter ) < 0 )
07032 {
07033 MTX_ERROR_MSG( "sprintf returned failure." );
07034 return FALSE;
07035 }
07036 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
07037 {
07038 MTX_ERROR_MSG( "sprintf returned failure." );
07039 return FALSE;
07040 }
07041 #endif
07042 fprintf( out, ValueBuffer );
07043 }
07044 }
07045 if( M->cplx[j][i].im == 0 )
07046 {
07047
07048 #ifndef _CRT_SECURE_NO_DEPRECATE
07049 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07050 {
07051 MTX_ERROR_MSG( "sprintf_s returned failure." );
07052 return FALSE;
07053 }
07054 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07055 {
07056 MTX_ERROR_MSG( "sprintf_s returned failure." );
07057 return FALSE;
07058 }
07059 #else
07060 if( sprintf( format, "%%.%dg", precision ) < 0 )
07061 {
07062 MTX_ERROR_MSG( "sprintf returned failure." );
07063 return FALSE;
07064 }
07065 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07066 {
07067 MTX_ERROR_MSG( "sprintf returned failure." );
07068 return FALSE;
07069 }
07070 #endif
07071 fprintf( out, ValueBuffer );
07072 }
07073 else
07074 {
07075
07076 #ifndef _CRT_SECURE_NO_DEPRECATE
07077 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07078 {
07079 MTX_ERROR_MSG( "sprintf_s returned failure." );
07080 return FALSE;
07081 }
07082 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07083 {
07084 MTX_ERROR_MSG( "sprintf_s returned failure." );
07085 return FALSE;
07086 }
07087 #else
07088 if( sprintf( format, "%%.%dg", precision ) < 0 )
07089 {
07090 MTX_ERROR_MSG( "sprintf returned failure." );
07091 return FALSE;
07092 }
07093 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07094 {
07095 MTX_ERROR_MSG( "sprintf returned failure." );
07096 return FALSE;
07097 }
07098 #endif
07099 fprintf( out, ValueBuffer );
07100
07101 #ifndef _CRT_SECURE_NO_DEPRECATE
07102 if( sprintf_s( format, 16, "%%+.%dgi", precision ) < 0 )
07103 {
07104 MTX_ERROR_MSG( "sprintf_s returned failure." );
07105 return FALSE;
07106 }
07107 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
07108 {
07109 MTX_ERROR_MSG( "sprintf_s returned failure." );
07110 return FALSE;
07111 }
07112 #else
07113 if( sprintf( format, "%%+.%dgi", precision ) < 0 )
07114 {
07115 MTX_ERROR_MSG( "sprintf returned failure." );
07116 return FALSE;
07117 }
07118 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
07119 {
07120 MTX_ERROR_MSG( "sprintf returned failure." );
07121 return FALSE;
07122 }
07123 #endif
07124 fprintf( out, ValueBuffer );
07125 }
07126 fprintf( out, "\n" );
07127 }
07128 }
07129
07130 fclose(out);
07131
07132 return TRUE;
07133 }
07134
07135 BOOL MTX_PrintDelimited_ToBuffer( const MTX *M, char *buffer, const unsigned maxlength, const unsigned precision, const char delimiter )
07136 {
07137 unsigned i = 0;
07138 unsigned j = 0;
07139 unsigned scount = 0;
07140 unsigned dcount = 0;
07141 BOOL endOfBuffer = FALSE;
07142 char format[16];
07143 char ValueBuffer[512];
07144
07145 if( MTX_isNull( M ) )
07146 {
07147 MTX_ERROR_MSG( "NULL Matrix" );
07148 return FALSE;
07149 }
07150
07151 if( M->ncols == 0 || M->nrows == 0 )
07152 {
07153 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
07154 return FALSE;
07155 }
07156
07157 if( buffer == NULL )
07158 {
07159 MTX_ERROR_MSG( "if( buffer == NULL )" );
07160 return FALSE;
07161 }
07162
07163 if( maxlength == 0 )
07164 {
07165 MTX_ERROR_MSG( "if( maxlength == 0 )" );
07166 return FALSE;
07167 }
07168
07169 if( precision > 200 )
07170 {
07171 MTX_ERROR_MSG( "if( precision > 200 )" );
07172 return FALSE;
07173 }
07174
07175 ValueBuffer[0] = '\0';
07176
07177 #ifndef _CRT_SECURE_NO_DEPRECATE
07178 if( M->isReal )
07179 {
07180 for( i = 0; i < M->nrows; i++ )
07181 {
07182 for( j = 0; j < M->ncols-1; j++ )
07183 {
07184 if( sprintf_s( format, 16, "%%.%dg%c", precision, delimiter ) < 0 )
07185 {
07186 MTX_ERROR_MSG( "sprintf_s returned failure." );
07187 return FALSE;
07188 }
07189 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
07190 {
07191 MTX_ERROR_MSG( "sprintf_s returned failure." );
07192 return FALSE;
07193 }
07194 if( scount + strlen(ValueBuffer) >= maxlength )
07195 {
07196 endOfBuffer = TRUE;
07197 break;
07198 }
07199 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07200 if( dcount < 0 )
07201 {
07202 MTX_ERROR_MSG( "sprintf_s returned failure." );
07203 return FALSE;
07204 }
07205 scount += dcount;
07206 }
07207 if( endOfBuffer )
07208 break;
07209 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07210 {
07211 MTX_ERROR_MSG( "sprintf_s returned failure." );
07212 return FALSE;
07213 }
07214 if( sprintf_s( ValueBuffer, 512, format, M->data[j][i] ) < 0 )
07215 {
07216 MTX_ERROR_MSG( "sprintf_s returned failure." );
07217 return FALSE;
07218 }
07219 if( scount + strlen(ValueBuffer) >= maxlength )
07220 break;
07221 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07222 if( dcount < 0 )
07223 {
07224 MTX_ERROR_MSG( "sprintf_s returned failure." );
07225 return FALSE;
07226 }
07227 scount += dcount;
07228
07229 if( scount + 2 >= maxlength )
07230 break;
07231 dcount = sprintf_s( buffer+scount, maxlength-scount, "\n" );
07232 if( dcount < 0 )
07233 {
07234 MTX_ERROR_MSG( "sprintf_s returned failure." );
07235 return FALSE;
07236 }
07237 scount += dcount;
07238 }
07239 }
07240 else
07241 {
07242 for( i = 0; i < M->nrows; i++ )
07243 {
07244 for( j = 0; j < M->ncols-1; j++ )
07245 {
07246 if( M->cplx[j][i].im == 0 )
07247 {
07248
07249 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07250 {
07251 MTX_ERROR_MSG( "sprintf_s returned failure." );
07252 return FALSE;
07253 }
07254 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07255 {
07256 MTX_ERROR_MSG( "sprintf_s returned failure." );
07257 return FALSE;
07258 }
07259 if( scount + strlen(ValueBuffer) >= maxlength )
07260 {
07261 endOfBuffer = TRUE;
07262 break;
07263 }
07264 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07265 if( dcount < 0 )
07266 {
07267 MTX_ERROR_MSG( "sprintf_s returned failure." );
07268 return FALSE;
07269 }
07270 scount += dcount;
07271 }
07272 else
07273 {
07274
07275 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07276 {
07277 MTX_ERROR_MSG( "sprintf_s returned failure." );
07278 return FALSE;
07279 }
07280 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07281 {
07282 MTX_ERROR_MSG( "sprintf_s returned failure." );
07283 return FALSE;
07284 }
07285 if( scount + strlen(ValueBuffer) >= maxlength )
07286 {
07287 endOfBuffer = TRUE;
07288 break;
07289 }
07290 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07291 if( dcount < 0 )
07292 {
07293 MTX_ERROR_MSG( "sprintf_s returned failure." );
07294 return FALSE;
07295 }
07296 scount += dcount;
07297
07298 if( sprintf_s( format, 16, "%%+.%dgi%c", precision, delimiter ) < 0 )
07299 {
07300 MTX_ERROR_MSG( "sprintf_s returned failure." );
07301 return FALSE;
07302 }
07303 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
07304 {
07305 MTX_ERROR_MSG( "sprintf_s returned failure." );
07306 return FALSE;
07307 }
07308 if( scount + strlen(ValueBuffer) >= maxlength )
07309 {
07310 endOfBuffer = TRUE;
07311 break;
07312 }
07313 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07314 if( dcount < 0 )
07315 {
07316 MTX_ERROR_MSG( "sprintf_s returned failure." );
07317 return FALSE;
07318 }
07319 scount += dcount;
07320 }
07321 }
07322 if( endOfBuffer )
07323 break;
07324
07325 if( M->cplx[j][i].im == 0 )
07326 {
07327
07328 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07329 {
07330 MTX_ERROR_MSG( "sprintf_s returned failure." );
07331 return FALSE;
07332 }
07333 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07334 {
07335 MTX_ERROR_MSG( "sprintf_s returned failure." );
07336 return FALSE;
07337 }
07338 if( scount + strlen(ValueBuffer) >= maxlength )
07339 break;
07340 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07341 if( dcount < 0 )
07342 {
07343 MTX_ERROR_MSG( "sprintf_s returned failure." );
07344 return FALSE;
07345 }
07346 scount += dcount;
07347 }
07348 else
07349 {
07350
07351 if( sprintf_s( format, 16, "%%.%dg", precision ) < 0 )
07352 {
07353 MTX_ERROR_MSG( "sprintf_s returned failure." );
07354 return FALSE;
07355 }
07356 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].re ) < 0 )
07357 {
07358 MTX_ERROR_MSG( "sprintf_s returned failure." );
07359 return FALSE;
07360 }
07361 if( scount + strlen(ValueBuffer) >= maxlength )
07362 break;
07363 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07364 if( dcount < 0 )
07365 {
07366 MTX_ERROR_MSG( "sprintf_s returned failure." );
07367 return FALSE;
07368 }
07369 scount += dcount;
07370
07371 if( sprintf_s( format, 16, "%%+.%dgi", precision ) < 0 )
07372 {
07373 MTX_ERROR_MSG( "sprintf_s returned failure." );
07374 return FALSE;
07375 }
07376 if( sprintf_s( ValueBuffer, 512, format, M->cplx[j][i].im ) < 0 )
07377 {
07378 MTX_ERROR_MSG( "sprintf_s returned failure." );
07379 return FALSE;
07380 }
07381 if( scount + strlen(ValueBuffer) >= maxlength )
07382 break;
07383 dcount = sprintf_s( buffer+scount, maxlength-scount, "%s", ValueBuffer );
07384 if( dcount < 0 )
07385 {
07386 MTX_ERROR_MSG( "sprintf_s returned failure." );
07387 return FALSE;
07388 }
07389 scount += dcount;
07390 }
07391
07392 if( scount + 2 >= maxlength )
07393 break;
07394
07395 dcount = sprintf_s( buffer+scount, maxlength-scount, "\n" );
07396 if( dcount < 0 )
07397 {
07398 MTX_ERROR_MSG( "sprintf_s returned failure." );
07399 return FALSE;
07400 }
07401 scount += dcount;
07402 }
07403 }
07404 #else
07405 if( M->isReal )
07406 {
07407 for( i = 0; i < M->nrows; i++ )
07408 {
07409 for( j = 0; j < M->ncols-1; j++ )
07410 {
07411 if( sprintf( format, "%%.%dg%c", precision, delimiter ) < 0 )
07412 {
07413 MTX_ERROR_MSG( "sprintf returned failure." );
07414 return FALSE;
07415 }
07416 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
07417 {
07418 MTX_ERROR_MSG( "sprintf returned failure." );
07419 return FALSE;
07420 }
07421 if( scount + strlen(ValueBuffer) >= maxlength )
07422 {
07423 endOfBuffer = TRUE;
07424 break;
07425 }
07426 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07427 if( dcount < 0 )
07428 {
07429 MTX_ERROR_MSG( "sprintf returned failure." );
07430 return FALSE;
07431 }
07432 scount += dcount;
07433 }
07434 if( endOfBuffer )
07435 break;
07436 if( sprintf( format, "%%.%dg", precision ) < 0 )
07437 {
07438 MTX_ERROR_MSG( "sprintf returned failure." );
07439 return FALSE;
07440 }
07441 if( sprintf( ValueBuffer, format, M->data[j][i] ) < 0 )
07442 {
07443 MTX_ERROR_MSG( "sprintf returned failure." );
07444 return FALSE;
07445 }
07446 if( scount + strlen(ValueBuffer) >= maxlength )
07447 break;
07448 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07449 if( dcount < 0 )
07450 {
07451 MTX_ERROR_MSG( "sprintf returned failure." );
07452 return FALSE;
07453 }
07454 scount += dcount;
07455
07456 if( scount + 2 >= maxlength )
07457 break;
07458 dcount = sprintf( buffer+scount, "\n" );
07459 if( dcount < 0 )
07460 {
07461 MTX_ERROR_MSG( "sprintf returned failure." );
07462 return FALSE;
07463 }
07464 scount += dcount;
07465 }
07466 }
07467 else
07468 {
07469 for( i = 0; i < M->nrows; i++ )
07470 {
07471 for( j = 0; j < M->ncols-1; j++ )
07472 {
07473 if( M->cplx[j][i].im == 0 )
07474 {
07475
07476 if( sprintf( format, "%%.%dg", precision ) < 0 )
07477 {
07478 MTX_ERROR_MSG( "sprintf returned failure." );
07479 return FALSE;
07480 }
07481 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07482 {
07483 MTX_ERROR_MSG( "sprintf returned failure." );
07484 return FALSE;
07485 }
07486 if( scount + strlen(ValueBuffer) >= maxlength )
07487 {
07488 endOfBuffer = TRUE;
07489 break;
07490 }
07491 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07492 if( dcount < 0 )
07493 {
07494 MTX_ERROR_MSG( "sprintf returned failure." );
07495 return FALSE;
07496 }
07497 scount += dcount;
07498 }
07499 else
07500 {
07501
07502 if( sprintf( format, "%%.%dg", precision ) < 0 )
07503 {
07504 MTX_ERROR_MSG( "sprintf returned failure." );
07505 return FALSE;
07506 }
07507 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07508 {
07509 MTX_ERROR_MSG( "sprintf returned failure." );
07510 return FALSE;
07511 }
07512 if( scount + strlen(ValueBuffer) >= maxlength )
07513 {
07514 endOfBuffer = TRUE;
07515 break;
07516 }
07517 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07518 if( dcount < 0 )
07519 {
07520 MTX_ERROR_MSG( "sprintf returned failure." );
07521 return FALSE;
07522 }
07523 scount += dcount;
07524
07525 if( sprintf( format, "%%+.%dgi%c", precision, delimiter ) < 0 )
07526 {
07527 MTX_ERROR_MSG( "sprintf returned failure." );
07528 return FALSE;
07529 }
07530 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
07531 {
07532 MTX_ERROR_MSG( "sprintf returned failure." );
07533 return FALSE;
07534 }
07535 if( scount + strlen(ValueBuffer) >= maxlength )
07536 {
07537 endOfBuffer = TRUE;
07538 break;
07539 }
07540 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07541 if( dcount < 0 )
07542 {
07543 MTX_ERROR_MSG( "sprintf returned failure." );
07544 return FALSE;
07545 }
07546 scount += dcount;
07547 }
07548 }
07549 if( endOfBuffer )
07550 break;
07551
07552 if( M->cplx[j][i].im == 0 )
07553 {
07554
07555 if( sprintf( format, "%%.%dg", precision ) < 0 )
07556 {
07557 MTX_ERROR_MSG( "sprintf returned failure." );
07558 return FALSE;
07559 }
07560 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07561 {
07562 MTX_ERROR_MSG( "sprintf returned failure." );
07563 return FALSE;
07564 }
07565 if( scount + strlen(ValueBuffer) >= maxlength )
07566 break;
07567 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07568 if( dcount < 0 )
07569 {
07570 MTX_ERROR_MSG( "sprintf returned failure." );
07571 return FALSE;
07572 }
07573 scount += dcount;
07574 }
07575 else
07576 {
07577
07578 if( sprintf( format, "%%.%dg", precision ) < 0 )
07579 {
07580 MTX_ERROR_MSG( "sprintf returned failure." );
07581 return FALSE;
07582 }
07583 if( sprintf( ValueBuffer, format, M->cplx[j][i].re ) < 0 )
07584 {
07585 MTX_ERROR_MSG( "sprintf returned failure." );
07586 return FALSE;
07587 }
07588 if( scount + strlen(ValueBuffer) >= maxlength )
07589 break;
07590 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07591 if( dcount < 0 )
07592 {
07593 MTX_ERROR_MSG( "sprintf returned failure." );
07594 return FALSE;
07595 }
07596 scount += dcount;
07597
07598 if( sprintf( format, "%%+.%dgi", precision ) < 0 )
07599 {
07600 MTX_ERROR_MSG( "sprintf returned failure." );
07601 return FALSE;
07602 }
07603 if( sprintf( ValueBuffer, format, M->cplx[j][i].im ) < 0 )
07604 {
07605 MTX_ERROR_MSG( "sprintf returned failure." );
07606 return FALSE;
07607 }
07608 if( scount + strlen(ValueBuffer) >= maxlength )
07609 break;
07610 dcount = sprintf( buffer+scount, "%s", ValueBuffer );
07611 if( dcount < 0 )
07612 {
07613 MTX_ERROR_MSG( "sprintf returned failure." );
07614 return FALSE;
07615 }
07616 scount += dcount;
07617 }
07618
07619 if( scount + 2 >= maxlength )
07620 break;
07621
07622 dcount = sprintf( buffer+scount, "\n" );
07623 if( dcount < 0 )
07624 {
07625 MTX_ERROR_MSG( "sprintf returned failure." );
07626 return FALSE;
07627 }
07628 scount += dcount;
07629 }
07630 }
07631 #endif
07632
07633 return TRUE;
07634 }
07635
07636 BOOL MTX_PrintRowToString( const MTX *M, const unsigned row, char *buffer, const unsigned maxlength, const int width, const int precision )
07637 {
07638 unsigned j = 0;
07639 int k = 0;
07640 unsigned len = 0;
07641 unsigned scount = 0;
07642 unsigned dcount = 0;
07643
07644 char ValueBuffer[512];
07645 ValueBuffer[0] = '\0';
07646
07647 if( !buffer )
07648 {
07649 MTX_ERROR_MSG( "buffer is a NULL pointer." );
07650 return FALSE;
07651 }
07652
07653 if( MTX_isNull( M ) )
07654 {
07655 MTX_ERROR_MSG( "NULL Matrix" );
07656 return FALSE;
07657 }
07658
07659 if( M->ncols == 0 || M->nrows == 0 )
07660 {
07661 MTX_ERROR_MSG( "if( M->ncols == 0 || M->nrows == 0 )" );
07662 return FALSE;
07663 }
07664
07665 if( row >= M->nrows )
07666 {
07667 MTX_ERROR_MSG( "if( row >= M->nrows )" );
07668 return FALSE;
07669 }
07670
07671 if( precision > 200 )
07672 {
07673 MTX_ERROR_MSG( "if( precision > 200 )" );
07674 return FALSE;
07675 }
07676
07677 #ifndef _CRT_SECURE_NO_DEPRECATE
07678 for( j = 0; j < M->ncols; j++ )
07679 {
07680 if( M->isReal )
07681 {
07682 MTX_ValueToString( M->data[j][row], width, precision, TRUE, TRUE, ValueBuffer, 512 );
07683 len = (unsigned int)strlen( ValueBuffer );
07684 if( len + scount >= maxlength )
07685 {
07686 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07687 return FALSE;
07688 }
07689 dcount = sprintf_s( buffer+scount, maxlength-scount, ValueBuffer );
07690 if( dcount < 0 )
07691 {
07692 MTX_ERROR_MSG( "sprintf_s returned failure." );
07693 return FALSE;
07694 }
07695 scount += dcount;
07696 }
07697 else
07698 {
07699 if( M->cplx[j][row].im == 0 )
07700 {
07701
07702 MTX_ValueToString( M->cplx[j][row].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
07703 len = (unsigned int)strlen( ValueBuffer );
07704 if( len + scount >= maxlength )
07705 {
07706 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07707 return FALSE;
07708 }
07709 dcount = sprintf_s( buffer+scount, maxlength-scount, ValueBuffer );
07710 if( dcount < 0 )
07711 {
07712 MTX_ERROR_MSG( "sprintf_s returned failure." );
07713 return FALSE;
07714 }
07715 scount += dcount;
07716 for( k = 0; k < width; k++ )
07717 {
07718 dcount = sprintf_s( buffer+scount, maxlength-scount, " " );
07719 if( dcount < 0 )
07720 {
07721 MTX_ERROR_MSG( "sprintf_s returned failure." );
07722 return FALSE;
07723 }
07724 scount += dcount;
07725 }
07726 }
07727 else
07728 {
07729
07730 MTX_ValueToString( M->cplx[j][row].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
07731 len = (unsigned int)strlen( ValueBuffer );
07732 if( len + scount >= maxlength )
07733 {
07734 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07735 return FALSE;
07736 }
07737 dcount = sprintf_s( buffer+scount, maxlength-scount, ValueBuffer );
07738 if( dcount < 0 )
07739 {
07740 MTX_ERROR_MSG( "sprintf_s returned failure." );
07741 return FALSE;
07742 }
07743 scount += dcount;
07744
07745 MTX_ValueToString( M->cplx[j][row].im, width, precision, FALSE, TRUE, ValueBuffer, 512 );
07746 len = (unsigned int)strlen( ValueBuffer );
07747 if( len + scount >= maxlength )
07748 {
07749 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07750 return FALSE;
07751 }
07752 dcount = sprintf_s( buffer+scount, maxlength-scount, ValueBuffer );
07753 if( dcount < 0 )
07754 {
07755 MTX_ERROR_MSG( "sprintf_s returned failure." );
07756 return FALSE;
07757 }
07758 scount += dcount;
07759 }
07760 }
07761 }
07762 if( sprintf_s( buffer+scount, maxlength-scount, "\n" ) < 0 )
07763 {
07764 MTX_ERROR_MSG( "sprintf_s returned failure." );
07765 return FALSE;
07766 }
07767 #else
07768 for( j = 0; j < M->ncols; j++ )
07769 {
07770 if( M->isReal )
07771 {
07772 MTX_ValueToString( M->data[j][row], width, precision, TRUE, TRUE, ValueBuffer, 512 );
07773 len = (unsigned int)strlen( ValueBuffer );
07774 if( len + scount >= maxlength )
07775 {
07776 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07777 return FALSE;
07778 }
07779 dcount = sprintf( buffer+scount, ValueBuffer );
07780 if( dcount < 0 )
07781 {
07782 MTX_ERROR_MSG( "sprintf returned failure." );
07783 return FALSE;
07784 }
07785 scount += dcount;
07786 }
07787 else
07788 {
07789 if( M->cplx[j][row].im == 0 )
07790 {
07791
07792 MTX_ValueToString( M->cplx[j][row].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
07793 len = (unsigned int)strlen( ValueBuffer );
07794 if( len + scount >= maxlength )
07795 {
07796 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07797 return FALSE;
07798 }
07799 dcount = sprintf( buffer+scount, ValueBuffer );
07800 if( dcount < 0 )
07801 {
07802 MTX_ERROR_MSG( "sprintf returned failure." );
07803 return FALSE;
07804 }
07805 scount += dcount;
07806 for( k = 0; k < width; k++ )
07807 {
07808 dcount = sprintf( buffer+scount, " " );
07809 if( dcount < 0 )
07810 {
07811 MTX_ERROR_MSG( "sprintf returned failure." );
07812 return FALSE;
07813 }
07814 scount += dcount;
07815 }
07816 }
07817 else
07818 {
07819
07820 MTX_ValueToString( M->cplx[j][row].re, width, precision, TRUE, FALSE, ValueBuffer, 512 );
07821 len = (unsigned int)strlen( ValueBuffer );
07822 if( len + scount >= maxlength )
07823 {
07824 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07825 return FALSE;
07826 }
07827 dcount = sprintf( buffer+scount, ValueBuffer );
07828 if( dcount < 0 )
07829 {
07830 MTX_ERROR_MSG( "sprintf returned failure." );
07831 return FALSE;
07832 }
07833 scount += dcount;
07834
07835 MTX_ValueToString( M->cplx[j][row].im, width, precision, FALSE, TRUE, ValueBuffer, 512 );
07836 len = (unsigned int)strlen( ValueBuffer );
07837 if( len + scount >= maxlength )
07838 {
07839 MTX_ERROR_MSG( "if( len + scount >= maxlength )" );
07840 return FALSE;
07841 }
07842 dcount = sprintf( buffer+scount, ValueBuffer );
07843 if( dcount < 0 )
07844 {
07845 MTX_ERROR_MSG( "sprintf returned failure." );
07846 return FALSE;
07847 }
07848 scount += dcount;
07849 }
07850 }
07851 }
07852 if( sprintf( buffer+scount, "\n" ) < 0 )
07853 {
07854 MTX_ERROR_MSG( "sprintf returned failure." );
07855 return FALSE;
07856 }
07857 #endif
07858 return TRUE;
07859 }
07860
07861
07862
07863
07864
07865
07866
07867
07868
07869
07870
07871
07872 BOOL MTX_Add_Scalar( MTX *M, const double scalar )
07873 {
07874 unsigned i = 0;
07875 unsigned j = 0;
07876
07877 if( scalar == 0.0 )
07878 return TRUE;
07879
07880 if( M->isReal )
07881 {
07882 for( j = 0; j < M->ncols; j++ )
07883 {
07884 for( i = 0; i < M->nrows; i++ )
07885 {
07886 M->data[j][i] += scalar;
07887 }
07888 }
07889 }
07890 else
07891 {
07892 for( j = 0; j < M->ncols; j++ )
07893 {
07894 for( i = 0; i < M->nrows; i++ )
07895 {
07896 M->cplx[j][i].re += scalar;
07897 }
07898 }
07899 }
07900 return TRUE;
07901 }
07902
07903 BOOL MTX_Add_ScalarComplex( MTX *M, const double re, const double im )
07904 {
07905 unsigned i = 0;
07906 unsigned j = 0;
07907
07908
07909 if( re == 0.0 && im == 0.0 )
07910 {
07911 return TRUE;
07912 }
07913 if( im == 0.0 )
07914 {
07915 return MTX_Add_Scalar( M, re );
07916 }
07917
07918 if( M->isReal )
07919 {
07920 if( !MTX_ConvertRealToComplex( M ) )
07921 {
07922 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
07923 return FALSE;
07924 }
07925 }
07926
07927 if( re == 0.0 )
07928 {
07929 for( j = 0; j < M->ncols; j++ )
07930 {
07931 for( i = 0; i < M->nrows; i++ )
07932 {
07933 M->cplx[j][i].im += im;
07934 }
07935 }
07936 }
07937 else
07938 {
07939 for( j = 0; j < M->ncols; j++ )
07940 {
07941 for( i = 0; i < M->nrows; i++ )
07942 {
07943 M->cplx[j][i].re += re;
07944 M->cplx[j][i].im += im;
07945 }
07946 }
07947 }
07948 return TRUE;
07949 }
07950
07951 BOOL MTX_Subtract_Scalar( MTX *M, const double scalar )
07952 {
07953 unsigned i = 0;
07954 unsigned j = 0;
07955
07956 if( MTX_isNull( M ) )
07957 {
07958 MTX_ERROR_MSG( "NULL Matrix" );
07959 return FALSE;
07960 }
07961
07962 if( scalar == 0.0 )
07963 return TRUE;
07964
07965 if( M->isReal )
07966 {
07967 for( j = 0; j < M->ncols; j++ )
07968 {
07969 for( i = 0; i < M->nrows; i++ )
07970 {
07971 M->data[j][i] -= scalar;
07972 }
07973 }
07974 }
07975 else
07976 {
07977 for( j = 0; j < M->ncols; j++ )
07978 {
07979 for( i = 0; i < M->nrows; i++ )
07980 {
07981 M->cplx[j][i].re -= scalar;
07982 }
07983 }
07984 }
07985 return TRUE;
07986 }
07987
07988 BOOL MTX_Subtract_ScalarComplex( MTX *M, const double re, const double im )
07989 {
07990 unsigned i = 0;
07991 unsigned j = 0;
07992
07993
07994 if( re == 0.0 && im == 0.0 )
07995 {
07996 return TRUE;
07997 }
07998 if( im == 0.0 )
07999 {
08000 return MTX_Subtract_Scalar( M, re );
08001 }
08002
08003 if( M->isReal )
08004 {
08005 if( !MTX_ConvertRealToComplex( M ) )
08006 {
08007 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08008 return FALSE;
08009 }
08010 }
08011
08012 if( re == 0.0 )
08013 {
08014 for( j = 0; j < M->ncols; j++ )
08015 {
08016 for( i = 0; i < M->nrows; i++ )
08017 {
08018 M->cplx[j][i].im -= im;
08019 }
08020 }
08021 }
08022 else
08023 {
08024 for( j = 0; j < M->ncols; j++ )
08025 {
08026 for( i = 0; i < M->nrows; i++ )
08027 {
08028 M->cplx[j][i].re -= re;
08029 M->cplx[j][i].im -= im;
08030 }
08031 }
08032 }
08033 return TRUE;
08034 }
08035
08036 BOOL MTX_Multiply_Scalar( MTX *M, const double scalar )
08037 {
08038 unsigned i = 0;
08039 unsigned j = 0;
08040
08041 if( MTX_isNull( M ) )
08042 {
08043 MTX_ERROR_MSG( "NULL Matrix" );
08044 return FALSE;
08045 }
08046
08047 if( scalar == 0.0 )
08048 {
08049 return MTX_Zero( M );
08050 }
08051
08052 if( M->isReal )
08053 {
08054 for( j = 0; j < M->ncols; j++ )
08055 {
08056 for( i = 0; i < M->nrows; i++ )
08057 {
08058 M->data[j][i] *= scalar;
08059 }
08060 }
08061 }
08062 else
08063 {
08064 for( j = 0; j < M->ncols; j++ )
08065 {
08066 for( i = 0; i < M->nrows; i++ )
08067 {
08068 M->cplx[j][i].re *= scalar;
08069 M->cplx[j][i].im *= scalar;
08070 }
08071 }
08072 }
08073 return TRUE;
08074 }
08075
08076 BOOL MTX_Multiply_ScalarComplex( MTX *M, const double re, const double im )
08077 {
08078 unsigned i = 0;
08079 unsigned j = 0;
08080 double tre = 0;
08081 double tim = 0;
08082
08083 if( MTX_isNull( M ) )
08084 {
08085 MTX_ERROR_MSG( "NULL Matrix" );
08086 return FALSE;
08087 }
08088
08089
08090 if( re == 0.0 && im == 0.0 )
08091 {
08092 return TRUE;
08093 }
08094 if( im == 0.0 )
08095 {
08096 return MTX_Multiply_Scalar( M, re );
08097 }
08098
08099 if( M->isReal )
08100 {
08101 if( !MTX_ConvertRealToComplex( M ) )
08102 {
08103 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08104 return FALSE;
08105 }
08106 }
08107
08108 for( j = 0; j < M->ncols; j++ )
08109 {
08110 for( i = 0; i < M->nrows; i++ )
08111 {
08112 tre = M->cplx[j][i].re * re - M->cplx[j][i].im * im;
08113 tim = M->cplx[j][i].re * im + M->cplx[j][i].im * re;
08114 M->cplx[j][i].re = tre;
08115 M->cplx[j][i].im = tim;
08116 }
08117 }
08118 return TRUE;
08119 }
08120
08121 BOOL MTX_Divide_Scalar( MTX *M, const double scalar )
08122 {
08123 unsigned i = 0;
08124 unsigned j = 0;
08125
08126 if( MTX_isNull( M ) )
08127 {
08128 MTX_ERROR_MSG( "NULL Matrix" );
08129 return FALSE;
08130 }
08131
08132 if( M->isReal )
08133 {
08134 for( j = 0; j < M->ncols; j++ )
08135 {
08136 for( i = 0; i < M->nrows; i++ )
08137 {
08138 M->data[j][i] /= scalar;
08139 }
08140 }
08141 }
08142 else
08143 {
08144 for( j = 0; j < M->ncols; j++ )
08145 {
08146 for( i = 0; i < M->nrows; i++ )
08147 {
08148 M->cplx[j][i].re /= scalar;
08149 M->cplx[j][i].im /= scalar;
08150 }
08151 }
08152 }
08153 return TRUE;
08154 }
08155
08156 BOOL MTX_Divide_ScalarComplex( MTX *M, const double re, const double im )
08157 {
08158 unsigned i = 0;
08159 unsigned j = 0;
08160 double mag = 0;
08161 double tre = 0;
08162 double tim = 0;
08163
08164 if( MTX_isNull( M ) )
08165 {
08166 MTX_ERROR_MSG( "NULL Matrix" );
08167 return FALSE;
08168 }
08169
08170
08171 if( im == 0.0 )
08172 {
08173 return MTX_Divide_Scalar( M, re );
08174 }
08175
08176 if( M->isReal )
08177 {
08178 if( !MTX_ConvertRealToComplex( M ) )
08179 {
08180 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08181 return FALSE;
08182 }
08183 }
08184
08185 for( j = 0; j < M->ncols; j++ )
08186 {
08187 for( i = 0; i < M->nrows; i++ )
08188 {
08189 mag = re*re + im*im;
08190
08191 tre = (M->cplx[j][i].re * re + M->cplx[j][i].im * im )/mag;
08192 tim = (M->cplx[j][i].im * re - M->cplx[j][i].re * im )/mag;
08193
08194 M->cplx[j][i].re = tre;
08195 M->cplx[j][i].im = tim;
08196 }
08197 }
08198 return TRUE;
08199 }
08200
08201 BOOL MTX_Negate( MTX *M )
08202 {
08203 unsigned i = 0;
08204 unsigned j;
08205 if( MTX_isNull( M ) )
08206 {
08207 MTX_ERROR_MSG( "NULL Matrix" );
08208 return FALSE;
08209 }
08210
08211 if( M->isReal )
08212 {
08213 for( j = 0; j < M->ncols; j++ )
08214 {
08215 for( i = 0; i < M->nrows; i++ )
08216 {
08217 M->data[j][i] = -M->data[j][i];
08218 }
08219 }
08220 }
08221 else
08222 {
08223 for( j = 0; j < M->ncols; j++ )
08224 {
08225 for( i = 0; i < M->nrows; i++ )
08226 {
08227 M->cplx[j][i].re = -M->cplx[j][i].re;
08228 M->cplx[j][i].im = -M->cplx[j][i].im;
08229 }
08230 }
08231 }
08232 return TRUE;
08233 }
08234
08235 BOOL MTX_Abs( MTX *M )
08236 {
08237 unsigned i = 0;
08238 unsigned j = 0;
08239 unsigned k = 0;
08240
08241 if( MTX_isNull( M ) )
08242 {
08243 MTX_ERROR_MSG( "NULL Matrix" );
08244 return FALSE;
08245 }
08246
08247 if( !M->isReal )
08248 {
08249
08250
08251
08252 M->data = (double**)calloc( (M->ncols), sizeof(double*) );
08253 if( !M->data )
08254 {
08255 MTX_ERROR_MSG( "calloc returned NULL." );
08256 MTX_Free( M );
08257 return FALSE;
08258 }
08259 }
08260
08261 if( M->isReal )
08262 {
08263 for( j = 0; j < M->ncols; j++ )
08264 for( i = 0; i < M->nrows; i++ )
08265 M->data[j][i] = fabs(M->data[j][i]);
08266 }
08267 else
08268 {
08269 for( j = 0; j < M->ncols; j++ )
08270 {
08271
08272 M->data[j] = (double*)malloc( sizeof(double)*(M->nrows) );
08273 if( !M->data[j] )
08274 {
08275 for( k = 0; k < j; k++ )
08276 {
08277 if( M->data[j] )
08278 free( M->data[j] );
08279 }
08280 free( M->data );
08281 M->data = NULL;
08282 MTX_Free( M );
08283 MTX_ERROR_MSG( "malloc returned NULL." );
08284 return FALSE;
08285 }
08286
08287 for( i = 0; i < M->nrows; i++ )
08288 {
08289 M->data[j][i] = sqrt( M->cplx[j][i].re*M->cplx[j][i].re + M->cplx[j][i].im*M->cplx[j][i].im );
08290 }
08291
08292
08293 free( M->cplx[j] );
08294 }
08295 }
08296
08297 if( !M->isReal )
08298 {
08299
08300 free( M->cplx );
08301 M->cplx = NULL;
08302 M->isReal = TRUE;
08303 }
08304
08305 return TRUE;
08306 }
08307
08308
08309 BOOL MTX_acos( MTX *M )
08310 {
08311 unsigned i = 0;
08312 unsigned j = 0;
08313 double maxabs = 0;
08314
08315 if( MTX_isNull( M ) )
08316 {
08317 MTX_ERROR_MSG( "NULL Matrix" );
08318 return FALSE;
08319 }
08320
08321
08322 if( M->isReal )
08323 {
08324
08325 if( !MTX_MaxAbs( M, &maxabs ) )
08326 {
08327 MTX_ERROR_MSG( "MTX_MaxAbs returned FALSE." );
08328 return FALSE;
08329 }
08330
08331 if( maxabs > 1.0 )
08332 {
08333 if( !MTX_ConvertRealToComplex( M ) )
08334 {
08335 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08336 return FALSE;
08337 }
08338 }
08339 }
08340
08341 if( M->isReal )
08342 {
08343
08344 for( j = 0; j < M->ncols; j++ )
08345 {
08346 for( i = 0; i < M->nrows; i++ )
08347 {
08348 M->data[j][i] = acos(M->data[j][i]);
08349 }
08350 }
08351 }
08352 else
08353 {
08354
08355 double Xp2;
08356 double Xm2;
08357 double Y2;
08358 double A;
08359 double B;
08360
08361 for( j = 0; j < M->ncols; j++ )
08362 {
08363 for( i = 0; i < M->nrows; i++ )
08364 {
08365 Xp2 = M->cplx[j][i].re + 1.0;
08366 Xp2*= Xp2;
08367
08368 Xm2 = M->cplx[j][i].re - 1.0;
08369 Xm2*= Xm2;
08370
08371 Y2 = M->cplx[j][i].im;
08372 Y2 *= Y2;
08373
08374
08375
08376
08377 A = 0.5 * ( sqrt(Xp2 + Y2) + sqrt(Xm2 + Y2) );
08378 B = 0.5 * ( sqrt(Xp2 + Y2) - sqrt(Xm2 + Y2) );
08379
08380 if( M->cplx[j][i].im >= 0 )
08381 {
08382 M->cplx[j][i].re = acos(B);
08383 M->cplx[j][i].im = -log( A + sqrt( A*A-1.0 ) );
08384 }
08385 else
08386 {
08387 M->cplx[j][i].re = acos(B);
08388 M->cplx[j][i].im = log( A + sqrt( A*A-1.0 ) );
08389 }
08390 }
08391 }
08392 }
08393 return TRUE;
08394 }
08395
08396 BOOL MTX_angle( MTX *M )
08397 {
08398 MTX copyM;
08399
08400 if( MTX_isNull( M ) )
08401 {
08402 MTX_ERROR_MSG( "NULL Matrix" );
08403 return FALSE;
08404 }
08405
08406 MTX_Init(©M);
08407
08408 if( !MTX_Copy(M,©M) )
08409 {
08410 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08411 return FALSE;
08412 }
08413
08414 if( !MTX_Phase(©M,M) )
08415 {
08416 MTX_ERROR_MSG( "MTX_Phase returned FALSE." );
08417 return FALSE;
08418 }
08419
08420 MTX_Free(©M);
08421
08422 return TRUE;
08423 }
08424
08425 BOOL MTX_asin( MTX *M )
08426 {
08427 unsigned i = 0;
08428 unsigned j = 0;
08429
08430 if( MTX_isNull( M ) )
08431 {
08432 MTX_ERROR_MSG( "NULL Matrix" );
08433 return FALSE;
08434 }
08435
08436
08437 if( M->isReal )
08438 {
08439 double maxabs;
08440
08441 if( !MTX_MaxAbs( M, &maxabs ) )
08442 {
08443 MTX_ERROR_MSG( "MTX_MaxAbs returned FALSE." );
08444 return FALSE;
08445 }
08446
08447 if( maxabs > 1.0 )
08448 {
08449 if( !MTX_ConvertRealToComplex( M ) )
08450 {
08451 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08452 return FALSE;
08453 }
08454 }
08455 }
08456
08457 if( M->isReal )
08458 {
08459
08460 for( j = 0; j < M->ncols; j++ )
08461 {
08462 for( i = 0; i < M->nrows; i++ )
08463 {
08464 M->data[j][i] = asin(M->data[j][i]);
08465 }
08466 }
08467 }
08468 else
08469 {
08470
08471 double Xp2;
08472 double Xm2;
08473 double Y2;
08474 double A;
08475 double B;
08476
08477 for( j = 0; j < M->ncols; j++ )
08478 {
08479 for( i = 0; i < M->nrows; i++ )
08480 {
08481 Xp2 = M->cplx[j][i].re + 1.0;
08482 Xp2*= Xp2;
08483
08484 Xm2 = M->cplx[j][i].re - 1.0;
08485 Xm2*= Xm2;
08486
08487 Y2 = M->cplx[j][i].im;
08488 Y2 *= Y2;
08489
08490
08491
08492
08493 A = 0.5 * ( sqrt(Xp2 + Y2) + sqrt(Xm2 + Y2) );
08494 B = 0.5 * ( sqrt(Xp2 + Y2) - sqrt(Xm2 + Y2) );
08495
08496 if( M->cplx[j][i].im >= 0 )
08497 {
08498 M->cplx[j][i].re = asin(B);
08499 M->cplx[j][i].im = log( A + sqrt( A*A-1.0 ) );
08500 }
08501 else
08502 {
08503 M->cplx[j][i].re = asin(B);
08504 M->cplx[j][i].im = -log( A + sqrt( A*A-1.0 ) );
08505 }
08506 }
08507 }
08508 }
08509 return TRUE;
08510 }
08511
08512 BOOL MTX_Sqr( MTX *M )
08513 {
08514 unsigned i = 0;
08515 unsigned j = 0;
08516 double re = 0;
08517 double im = 0;
08518
08519 if( MTX_isNull( M ) )
08520 {
08521 MTX_ERROR_MSG( "NULL Matrix" );
08522 return FALSE;
08523 }
08524
08525 if( M->isReal )
08526 {
08527 for( j = 0; j < M->ncols; j++ )
08528 {
08529 for( i = 0; i < M->nrows; i++ )
08530 {
08531 M->data[j][i] *= M->data[j][i];
08532 }
08533 }
08534 }
08535 else
08536 {
08537 for( j = 0; j < M->ncols; j++ )
08538 {
08539 for( i = 0; i < M->nrows; i++ )
08540 {
08541 re = M->cplx[j][i].re*M->cplx[j][i].re - M->cplx[j][i].im*M->cplx[j][i].im;
08542 im = 2.0 * M->cplx[j][i].re*M->cplx[j][i].im;
08543 M->cplx[j][i].re = re;
08544 M->cplx[j][i].im = im;
08545 }
08546 }
08547 }
08548 return TRUE;
08549 }
08550
08551 void MTX_static_quick_sqrt( const double *a_re, const double *a_im, double *re, double *im )
08552 {
08553 double mag;
08554 if( *a_im == 0.0 )
08555 {
08556 if( *a_re < 0 )
08557 {
08558 *re = 0.0;
08559 *im = sqrt( -(*a_re) );
08560 }
08561 else
08562 {
08563 *re = sqrt( *a_re );
08564 *im = 0.0;
08565 }
08566 }
08567 else
08568 {
08569 mag = sqrt( (*a_re)*(*a_re) + (*a_im)*(*a_im) );
08570
08571 *re = sqrt( (mag + (*a_re))/2.0 );
08572 if( *a_im < 0 )
08573 *im = -1.0*sqrt( (mag - (*a_re))/2.0 );
08574 else
08575 *im = sqrt( (mag - (*a_re))/2.0 );
08576 }
08577 }
08578
08579 BOOL MTX_Sqrt( MTX *M )
08580 {
08581 unsigned i = 0;
08582 unsigned j = 0;
08583 double re = 0;
08584 double im = 0;
08585 BOOL convert = FALSE;
08586
08587 if( MTX_isNull( M ) )
08588 {
08589 MTX_ERROR_MSG( "NULL Matrix" );
08590 return FALSE;
08591 }
08592
08593 if( M->isReal )
08594 {
08595
08596 for( j = 0; j < M->ncols; j++ )
08597 {
08598 for( i = 0; i < M->nrows; i++ )
08599 {
08600 if( M->data[j][i] < 0 )
08601 {
08602 convert = TRUE;
08603 break;
08604 }
08605 }
08606 if( convert )
08607 break;
08608 }
08609
08610 if( convert )
08611 {
08612 if( !MTX_ConvertRealToComplex( M ) )
08613 {
08614 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
08615 return FALSE;
08616 }
08617 }
08618 }
08619
08620 if( M->isReal )
08621 {
08622 for( j = 0; j < M->ncols; j++ )
08623 {
08624 for( i = 0; i < M->nrows; i++ )
08625 {
08626 M->data[j][i] = sqrt(M->data[j][i]);
08627 }
08628 }
08629 }
08630 else
08631 {
08632 for( j = 0; j < M->ncols; j++ )
08633 {
08634 for( i = 0; i < M->nrows; i++ )
08635 {
08636 MTX_static_quick_sqrt( &(M->cplx[j][i].re), &(M->cplx[j][i].im), &re, &im );
08637 M->cplx[j][i].re = re;
08638 M->cplx[j][i].im = im;
08639 }
08640 }
08641 }
08642 return TRUE;
08643 }
08644
08645 BOOL MTX_Exp( MTX *M )
08646 {
08647 unsigned i = 0;
08648 unsigned j = 0;
08649
08650 if( MTX_isNull( M ) )
08651 {
08652 MTX_ERROR_MSG( "NULL Matrix" );
08653 return FALSE;
08654 }
08655
08656 if( M->isReal )
08657 {
08658 for( j = 0; j < M->ncols; j++ )
08659 {
08660 for( i = 0; i < M->nrows; i++ )
08661 {
08662 M->data[j][i] = exp(M->data[j][i]);
08663 }
08664 }
08665 }
08666 else
08667 {
08668
08669 MTX Re;
08670 MTX Im;
08671 double real_part;
08672 double imag_part;
08673
08674 MTX_Init( &Re );
08675 MTX_Init( &Im );
08676
08677 if( !MTX_Real( M, &Re ) )
08678 {
08679 MTX_ERROR_MSG( "MTX_Real returned FALSE." );
08680 MTX_Free( &Re );
08681 MTX_Free( &Im );
08682 return FALSE;
08683 }
08684
08685 if( !MTX_Imag( M, &Im ) )
08686 {
08687 MTX_ERROR_MSG( "MTX_Imag returned FALSE." );
08688 MTX_Free( &Re );
08689 MTX_Free( &Im );
08690 return FALSE;
08691 }
08692
08693 if( !MTX_Exp(&Re) )
08694 {
08695 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
08696 MTX_Free( &Re );
08697 MTX_Free( &Im );
08698 return FALSE;
08699 }
08700
08701 for( j = 0; j < M->ncols; j++ )
08702 {
08703 for( i = 0; i < M->nrows; i++ )
08704 {
08705 real_part = Re.data[j][i];
08706 imag_part = Im.data[j][i];
08707 M->cplx[j][i].re = real_part * cos( imag_part );
08708 M->cplx[j][i].im = real_part * sin( imag_part );
08709 }
08710 }
08711 MTX_Free( &Re );
08712 MTX_Free( &Im );
08713 }
08714 return TRUE;
08715 }
08716
08717 BOOL MTX_Eye( MTX *M, const unsigned nrows, const unsigned ncols )
08718 {
08719 unsigned i = 0;
08720 unsigned j = 0;
08721
08722 if( !MTX_Calloc( M, nrows, ncols, TRUE ) )
08723 {
08724 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
08725 return FALSE;
08726 }
08727
08728 if( nrows < ncols )
08729 {
08730 for( i = 0; i < nrows; i++ )
08731 M->data[i][i] = 1.0;
08732 }
08733 else
08734 {
08735 for( j = 0; j < ncols; j++ )
08736 M->data[j][j] = 1.0;
08737 }
08738
08739 return TRUE;
08740 }
08741
08742 BOOL MTX_Ln( MTX *M )
08743 {
08744 unsigned i = 0;
08745 unsigned j = 0;
08746 double re;
08747 double im;
08748 MTX lnmag;
08749 MTX phase;
08750 MTX_Init( &lnmag );
08751 MTX_Init( &phase );
08752
08753 if( MTX_isNull( M ) )
08754 {
08755 MTX_ERROR_MSG( "NULL Matrix" );
08756 return FALSE;
08757 }
08758
08759 if( !MTX_Min( M, &re, &im ) )
08760 {
08761 MTX_ERROR_MSG( "MTX_Min returned FALSE." );
08762 return FALSE;
08763 }
08764
08765 if( M->isReal && re >= 0 )
08766 {
08767 for( j = 0; j < M->ncols; j++ )
08768 {
08769 for( i = 0; i < M->nrows; i++ )
08770 {
08771 M->data[j][i] = log(M->data[j][i]);
08772 }
08773 }
08774 return TRUE;
08775 }
08776 if( !MTX_Magnitude( M, &lnmag ) )
08777 {
08778 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
08779 MTX_Free(&lnmag);
08780 return FALSE;
08781 }
08782 if( !MTX_Phase( M, &phase ) )
08783 {
08784 MTX_ERROR_MSG( "MTX_Phase returned FALSE." );
08785 MTX_Free(&lnmag);
08786 MTX_Free(&phase);
08787 return FALSE;
08788 }
08789
08790 if( !MTX_Ln( &lnmag ) )
08791 {
08792 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
08793 MTX_Free(&lnmag);
08794 MTX_Free(&phase);
08795 return FALSE;
08796 }
08797
08798 if( !MTX_Complex( M, &lnmag, &phase ) )
08799 {
08800 MTX_ERROR_MSG( "MTX_Complex returned FALSE." );
08801 MTX_Free(&lnmag);
08802 MTX_Free(&phase);
08803 return FALSE;
08804 }
08805
08806 MTX_Free(&lnmag);
08807 MTX_Free(&phase);
08808 return TRUE;
08809 }
08810
08811
08812 BOOL MTX_Pow( const MTX *src, MTX *dst, const double power_re, const double power_im )
08813 {
08814 unsigned i = 0;
08815 unsigned j = 0;
08816
08817 if( MTX_isNull( src ) )
08818 {
08819 MTX_ERROR_MSG( "NULL Matrix" );
08820 return FALSE;
08821 }
08822 if( !dst )
08823 {
08824 MTX_ERROR_MSG( "NULL Matrix" );
08825 return FALSE;
08826 }
08827
08828 if( power_im == 0.0 )
08829 {
08830
08831 if( !MTX_Malloc( dst, src->nrows, src->ncols, src->isReal ) )
08832 {
08833 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
08834 return FALSE;
08835 }
08836 }
08837 else
08838 {
08839 if( !MTX_Malloc( dst, src->nrows, src->ncols, FALSE ) )
08840 {
08841 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
08842 return FALSE;
08843 }
08844 }
08845
08846
08847 if( src->isReal && power_im == 0 && power_re >= 1.0 )
08848 {
08849 for( j = 0; j < src->ncols; j++ )
08850 for( i = 0; i < src->nrows; i++ )
08851 dst->data[j][i] = pow(src->data[j][i],power_re);
08852 }
08853 else
08854 {
08855
08856 MTX yLnX;
08857 stComplex cplxval;
08858
08859 MTX_Init( &yLnX );
08860 cplxval.re = power_re;
08861 cplxval.im = power_im;
08862
08863 if( !MTX_Copy( src, &yLnX ) )
08864 {
08865 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08866 return FALSE;
08867 }
08868
08869 if( !MTX_Ln( &yLnX ) )
08870 {
08871 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
08872 return FALSE;
08873 }
08874
08875 if( cplxval.im == 0 )
08876 {
08877 if( !MTX_Multiply_Scalar( &yLnX, cplxval.re ) )
08878 {
08879 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
08880 return FALSE;
08881 }
08882 }
08883 else
08884 {
08885 if( !MTX_Multiply_ScalarComplex( &yLnX, cplxval.re, cplxval.im ) )
08886 {
08887 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
08888 return FALSE;
08889 }
08890 }
08891
08892 if( !MTX_Copy( &yLnX, dst ) )
08893 {
08894 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08895 return FALSE;
08896 }
08897
08898 if( !MTX_Exp( dst ) )
08899 {
08900 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
08901 return FALSE;
08902 }
08903
08904 MTX_Free( &yLnX );
08905 }
08906
08907 return TRUE;
08908 }
08909
08910
08911 BOOL MTX_PowInplace( MTX *src, const double power_re, const double power_im )
08912 {
08913 MTX copy;
08914 MTX_Init( © );
08915
08916 if( MTX_isNull( src ) )
08917 {
08918 MTX_ERROR_MSG( "NULL Matrix" );
08919 return FALSE;
08920 }
08921
08922 if( !MTX_Copy( src, © ) )
08923 {
08924 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08925 MTX_Free( © );
08926 return FALSE;
08927 }
08928
08929 if( !MTX_Pow( src, ©, power_re, power_im ) )
08930 {
08931 MTX_ERROR_MSG( "MTX_Pow returned FALSE." );
08932 MTX_Free( © );
08933 return FALSE;
08934 }
08935
08936 if( !MTX_Copy( ©, src ) )
08937 {
08938 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08939 MTX_Free( © );
08940 return FALSE;
08941 }
08942
08943 MTX_Free( © );
08944 return TRUE;
08945 }
08946
08947
08948
08949 BOOL MTX_atan( MTX *M )
08950 {
08951 unsigned i = 0;
08952 unsigned j = 0;
08953
08954 if( MTX_isNull( M ) )
08955 {
08956 MTX_ERROR_MSG( "NULL Matrix" );
08957 return FALSE;
08958 }
08959
08960 if( M->isReal )
08961 {
08962 for( j = 0; j < M->ncols; j++ )
08963 {
08964 for( i = 0; i < M->nrows; i++ )
08965 {
08966 M->data[j][i] = atan( M->data[j][i] );
08967 }
08968 }
08969 }
08970 else
08971 {
08972
08973
08974 MTX LnOneMinusZ;
08975 MTX LnOnePlusZ;
08976 stComplex halfi;
08977
08978 halfi.re = 0;
08979 halfi.im = 0.5;
08980
08981 MTX_Init( &LnOneMinusZ );
08982 MTX_Init( &LnOnePlusZ );
08983
08984
08985 if( !MTX_Copy( M, &LnOnePlusZ ) )
08986 {
08987 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
08988 return FALSE;
08989 }
08990
08991 if( !MTX_Multiply_ScalarComplex( &LnOnePlusZ, 0.0, 1.0 ) )
08992 {
08993 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
08994 MTX_Free( &LnOnePlusZ );
08995 return FALSE;
08996 }
08997
08998 if( !MTX_Copy( &LnOnePlusZ, &LnOneMinusZ ) )
08999 {
09000 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09001 MTX_Free( &LnOnePlusZ );
09002 return FALSE;
09003 }
09004
09005
09006 for( j = 0; j < LnOneMinusZ.ncols; j++ )
09007 {
09008 for( i = 0; i < LnOneMinusZ.nrows; i++ )
09009 {
09010 LnOneMinusZ.cplx[j][i].re = 1.0 - LnOneMinusZ.cplx[j][i].re;
09011 LnOneMinusZ.cplx[j][i].im = -LnOneMinusZ.cplx[j][i].im;
09012 }
09013 }
09014
09015 if( !MTX_Increment( &LnOnePlusZ ) )
09016 {
09017 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
09018 MTX_Free( &LnOneMinusZ );
09019 MTX_Free( &LnOnePlusZ );
09020 return FALSE;
09021 }
09022
09023 if( !MTX_Ln( &LnOneMinusZ ) )
09024 {
09025 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
09026 MTX_Free( &LnOneMinusZ );
09027 MTX_Free( &LnOnePlusZ );
09028 return FALSE;
09029 }
09030 if( !MTX_Ln( &LnOnePlusZ ) )
09031 {
09032 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
09033 MTX_Free( &LnOneMinusZ );
09034 MTX_Free( &LnOnePlusZ );
09035 return FALSE;
09036 }
09037
09038 if( !MTX_Subtract( M, &LnOneMinusZ, &LnOnePlusZ ) )
09039 {
09040 MTX_ERROR_MSG( "MTX_Subtract returned FALSE." );
09041 MTX_Free( &LnOneMinusZ );
09042 MTX_Free( &LnOnePlusZ );
09043 return FALSE;
09044 }
09045
09046 if( !MTX_Multiply_ScalarComplex( M, halfi.re, halfi.im ) )
09047 {
09048 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
09049 MTX_Free( &LnOneMinusZ );
09050 MTX_Free( &LnOnePlusZ );
09051 return FALSE;
09052 }
09053
09054 MTX_Free( &LnOneMinusZ );
09055 MTX_Free( &LnOnePlusZ );
09056 }
09057 return TRUE;
09058 }
09059
09060 BOOL MTX_Increment( MTX *M )
09061 {
09062 return MTX_Add_Scalar( M, 1.0 );
09063 }
09064
09065 BOOL MTX_Decrement( MTX *M )
09066 {
09067 return MTX_Subtract_Scalar( M, 1.0 );
09068 }
09069
09070 BOOL MTX_Add_Inplace( MTX *A, const MTX* B )
09071 {
09072 unsigned i = 0;
09073 unsigned j = 0;
09074 double re = 0.0;
09075 double im = 0.0;
09076
09077 if( MTX_isNull( A ) )
09078 {
09079 MTX_ERROR_MSG( "NULL Matrix" );
09080 return FALSE;
09081 }
09082
09083 if( MTX_isNull( B ) )
09084 {
09085 MTX_ERROR_MSG( "NULL Matrix" );
09086 return FALSE;
09087 }
09088
09089 if( MTX_static_global_treat_1x1_as_scalar )
09090 {
09091 if( A->nrows == 1 && A->ncols == 1 )
09092 {
09093 if( A->isReal )
09094 {
09095 re = A->data[0][0];
09096 if( !MTX_Copy( B, A ) )
09097 {
09098 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09099 return FALSE;
09100 }
09101 return MTX_Add_Scalar( A, re );
09102 }
09103 else
09104 {
09105 re = A->cplx[0][0].re;
09106 im = A->cplx[0][0].im;
09107 if( !MTX_Copy( B, A ) )
09108 {
09109 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09110 return FALSE;
09111 }
09112 return MTX_Add_ScalarComplex( A, re, im );
09113 }
09114 }
09115 else if( B->nrows == 1 && B->ncols == 1 )
09116 {
09117 if( B->isReal )
09118 {
09119 return MTX_Add_Scalar( A, B->data[0][0] );
09120 }
09121 else
09122 {
09123 return MTX_Add_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09124 }
09125 }
09126 }
09127
09128 if( !MTX_isConformalForAddition( A, B ) )
09129 {
09130 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09131 return FALSE;
09132 }
09133
09134 if( A->isReal && !B->isReal )
09135 {
09136 if( !MTX_ConvertRealToComplex( A ) )
09137 {
09138 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
09139 return FALSE;
09140 }
09141 }
09142
09143 if( A->isReal && B->isReal )
09144 {
09145 for( j = 0; j < A->ncols; j++ )
09146 {
09147 for( i = 0; i < A->nrows; i++ )
09148 {
09149 A->data[j][i] += B->data[j][i];
09150 }
09151 }
09152 }
09153 else if( !A->isReal && !B->isReal )
09154 {
09155 for( j = 0; j < A->ncols; j++ )
09156 {
09157 for( i = 0; i < A->nrows; i++ )
09158 {
09159 A->cplx[j][i].re += B->cplx[j][i].re;
09160 A->cplx[j][i].im += B->cplx[j][i].im;
09161 }
09162 }
09163 }
09164 else
09165 {
09166 for( j = 0; j < A->ncols; j++ )
09167 {
09168 for( i = 0; i < A->nrows; i++ )
09169 {
09170 A->cplx[j][i].re += B->data[j][i];
09171 }
09172 }
09173 }
09174 return TRUE;
09175 }
09176
09177 BOOL MTX_Subtract_Inplace( MTX *A, const MTX* B )
09178 {
09179 unsigned i = 0;
09180 unsigned j = 0;
09181 double re = 0.0;
09182 double im = 0.0;
09183
09184 if( MTX_isNull( A ) )
09185 {
09186 MTX_ERROR_MSG( "NULL Matrix" );
09187 return FALSE;
09188 }
09189
09190 if( MTX_isNull( B ) )
09191 {
09192 MTX_ERROR_MSG( "NULL Matrix" );
09193 return FALSE;
09194 }
09195
09196 if( MTX_static_global_treat_1x1_as_scalar )
09197 {
09198 if( A->nrows == 1 && A->ncols == 1 )
09199 {
09200
09201 if( A->isReal )
09202 {
09203 re = A->data[0][0];
09204 if( !MTX_Copy( B, A ) )
09205 {
09206 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09207 return FALSE;
09208 }
09209 if( !MTX_Negate( A ) )
09210 {
09211 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
09212 return FALSE;
09213 }
09214 return MTX_Add_Scalar( A, re );
09215 }
09216 else
09217 {
09218 re = A->cplx[0][0].re;
09219 im = A->cplx[0][0].im;
09220 if( !MTX_Copy( B, A ) )
09221 {
09222 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09223 return FALSE;
09224 }
09225 if( !MTX_Negate( A ) )
09226 {
09227 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
09228 return FALSE;
09229 }
09230 return MTX_Add_ScalarComplex( A, re, im );
09231 }
09232 }
09233 else if( B->nrows == 1 && B->ncols == 1 )
09234 {
09235 if( B->isReal )
09236 {
09237 return MTX_Subtract_Scalar( A, B->data[0][0] );
09238 }
09239 else
09240 {
09241 return MTX_Subtract_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09242 }
09243 }
09244 }
09245
09246 if( !MTX_isConformalForAddition( A, B ) )
09247 {
09248 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09249 return FALSE;
09250 }
09251
09252 if( A->isReal && !B->isReal )
09253 {
09254 if( !MTX_ConvertRealToComplex( A ) )
09255 {
09256 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
09257 return FALSE;
09258 }
09259 }
09260
09261 if( A->isReal && B->isReal )
09262 {
09263 for( j = 0; j < A->ncols; j++ )
09264 {
09265 for( i = 0; i < A->nrows; i++ )
09266 {
09267 A->data[j][i] -= B->data[j][i];
09268 }
09269 }
09270 }
09271 else if( !A->isReal && !B->isReal )
09272 {
09273 for( j = 0; j < A->ncols; j++ )
09274 {
09275 for( i = 0; i < A->nrows; i++ )
09276 {
09277 A->cplx[j][i].re -= B->cplx[j][i].re;
09278 A->cplx[j][i].im -= B->cplx[j][i].im;
09279 }
09280 }
09281 }
09282 else
09283 {
09284 for( j = 0; j < A->ncols; j++ )
09285 {
09286 for( i = 0; i < A->nrows; i++ )
09287 {
09288 A->cplx[j][i].re -= B->data[j][i];
09289 }
09290 }
09291 }
09292 return TRUE;
09293 }
09294
09295
09296 BOOL MTX_PostMultiply_Inplace( MTX *A, const MTX* B )
09297 {
09298 MTX M;
09299 MTX_Init( &M );
09300
09301 if( !MTX_Multiply( &M, A, B ) )
09302 {
09303 MTX_ERROR_MSG( "MTX_Multiply returned FALSE." );
09304 MTX_Free( &M );
09305 return FALSE;
09306 }
09307 if( !MTX_Copy( &M, A ) )
09308 {
09309 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09310 MTX_Free( &M );
09311 return FALSE;
09312 }
09313 MTX_Free( &M );
09314 return TRUE;
09315 }
09316
09317
09318 BOOL MTX_PostMultiplyTranspose_Inplace( MTX *A, const MTX* B )
09319 {
09320 MTX M;
09321 MTX_Init( &M );
09322
09323 if( !MTX_MultiplyTranspose( &M, A, B ) )
09324 {
09325 MTX_ERROR_MSG( "MTX_MultiplyTranspose returned FALSE." );
09326 MTX_Free( &M );
09327 return FALSE;
09328 }
09329 if( !MTX_Copy( &M, A ) )
09330 {
09331 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09332 MTX_Free( &M );
09333 return FALSE;
09334 }
09335 MTX_Free( &M );
09336 return TRUE;
09337 }
09338
09339
09340
09341
09342 BOOL MTX_PreMultiply_Inplace( MTX *A, const MTX* B )
09343 {
09344 MTX M;
09345 MTX_Init( &M );
09346
09347 if( !MTX_Multiply( &M, B, A ) )
09348 {
09349 MTX_ERROR_MSG( "MTX_Multiply returned FALSE." );
09350 MTX_Free( &M );
09351 return FALSE;
09352 }
09353 if( !MTX_Copy( &M, A ) )
09354 {
09355 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09356 MTX_Free( &M );
09357 return FALSE;
09358 }
09359 MTX_Free( &M );
09360 return TRUE;
09361 }
09362
09363 BOOL MTX_TransposePreMultiply_Inplace( MTX *A, const MTX *B )
09364 {
09365 MTX M;
09366 MTX_Init( &M );
09367
09368 if( !MTX_TransposeMultiply( &M, B, A ) )
09369 {
09370 MTX_ERROR_MSG( "MTX_TransposeMultiply returned FALSE." );
09371 MTX_Free( &M );
09372 return FALSE;
09373 }
09374 if( !MTX_Copy( &M, A ) )
09375 {
09376 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09377 MTX_Free( &M );
09378 return FALSE;
09379 }
09380 MTX_Free( &M );
09381 return TRUE;
09382 }
09383
09384 BOOL MTX_DotMultiply_Inplace( MTX *A, const MTX* B )
09385 {
09386 unsigned i = 0;
09387 unsigned j = 0;
09388 double re = 0;
09389 double im = 0;
09390
09391 if( MTX_isNull( A ) )
09392 {
09393 MTX_ERROR_MSG( "NULL Matrix" );
09394 return FALSE;
09395 }
09396 if( MTX_isNull( B ) )
09397 {
09398 MTX_ERROR_MSG( "NULL Matrix" );
09399 return FALSE;
09400 }
09401
09402 if( MTX_static_global_treat_1x1_as_scalar )
09403 {
09404 if( A->nrows == 1 && A->ncols == 1 )
09405 {
09406 if( A->isReal )
09407 {
09408 re = A->data[0][0];
09409 if( !MTX_Copy( B, A ) )
09410 {
09411 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09412 return FALSE;
09413 }
09414 return MTX_Multiply_Scalar( A, re );
09415 }
09416 else
09417 {
09418 re = A->cplx[0][0].re;
09419 im = A->cplx[0][0].im;
09420 if( !MTX_Copy( B, A ) )
09421 {
09422 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09423 return FALSE;
09424 }
09425 return MTX_Multiply_ScalarComplex( A, re, im );
09426 }
09427 }
09428 else if( B->nrows == 1 && B->ncols == 1 )
09429 {
09430 if( B->isReal )
09431 {
09432 return MTX_Multiply_Scalar( A, B->data[0][0] );
09433 }
09434 else
09435 {
09436 return MTX_Multiply_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09437 }
09438 }
09439 }
09440
09441 if( !MTX_isConformalForAddition( A, B ) )
09442 {
09443 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09444 return FALSE;
09445 }
09446
09447 if( A->isReal && !B->isReal )
09448 {
09449 if( !MTX_ConvertRealToComplex( A ) )
09450 {
09451 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
09452 return FALSE;
09453 }
09454 }
09455
09456 if( A->isReal && B->isReal )
09457 {
09458 for( j = 0; j < A->ncols; j++ )
09459 for( i = 0; i < A->nrows; i++ )
09460 A->data[j][i] *= B->data[j][i];
09461 }
09462 else if( !A->isReal && !B->isReal )
09463 {
09464 for( j = 0; j < A->ncols; j++ )
09465 {
09466 for( i = 0; i < A->nrows; i++ )
09467 {
09468 re = A->cplx[j][i].re * B->cplx[j][i].re - A->cplx[j][i].im * B->cplx[j][i].im;
09469 im = A->cplx[j][i].re * B->cplx[j][i].im + A->cplx[j][i].im * B->cplx[j][i].re;
09470 A->cplx[j][i].re = re;
09471 A->cplx[j][i].im = im;
09472 }
09473 }
09474 }
09475 else
09476 {
09477 for( j = 0; j < A->ncols; j++ )
09478 {
09479 for( i = 0; i < A->nrows; i++ )
09480 {
09481 A->cplx[j][i].re *= B->data[j][i];
09482 A->cplx[j][i].im *= B->data[j][i];
09483 }
09484 }
09485 }
09486
09487 return TRUE;
09488 }
09489
09490 BOOL MTX_DotDivide_Inplace( MTX *A, const MTX* B )
09491 {
09492 unsigned i = 0;
09493 unsigned j = 0;
09494 double re = 0;
09495 double im = 0;
09496 double mag = 0;
09497
09498 if( MTX_isNull( A ) )
09499 {
09500 MTX_ERROR_MSG( "NULL Matrix" );
09501 return FALSE;
09502 }
09503
09504 if( MTX_isNull( B ) )
09505 {
09506 MTX_ERROR_MSG( "NULL Matrix" );
09507 return FALSE;
09508 }
09509
09510 if( A->nrows == 1 && A->ncols == 1 && B->nrows == 1 && B->ncols == 1 )
09511 {
09512 if( !A->isReal && !B->isReal )
09513 {
09514 re = A->cplx[0][0].re;
09515 im = A->cplx[0][0].im;
09516 MTX_static_quick_complex_divide( &re, &im, &B->cplx[0][0].re, &B->cplx[0][0].im, &A->cplx[0][0].re, &A->cplx[0][0].im );
09517 return TRUE;
09518 }
09519 else if( A->isReal && B->isReal )
09520 {
09521 A->data[0][0] /= B->data[0][0];
09522 return TRUE;
09523 }
09524 else
09525 {
09526 if( A->isReal )
09527 {
09528
09529 re = A->data[0][0];
09530 mag = B->cplx[0][0].re*B->cplx[0][0].re + B->cplx[0][0].im*B->cplx[0][0].im;
09531 if( !MTX_Malloc(A,1,1,FALSE) )
09532 {
09533 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09534 return FALSE;
09535 }
09536
09537 A->cplx[0][0].re = re*B->cplx[0][0].re / mag;
09538 A->cplx[0][0].im = -re*B->cplx[0][0].im / mag;
09539 }
09540 else
09541 {
09542 re = B->data[0][0];
09543
09544 A->cplx[0][0].re /= re;
09545 A->cplx[0][0].im /= re;
09546 }
09547 }
09548 return TRUE;
09549 }
09550
09551 if( MTX_static_global_treat_1x1_as_scalar )
09552 {
09553 if( A->nrows == 1 && A->ncols == 1 )
09554 {
09555
09556
09557 if( A->isReal )
09558 {
09559
09560 re = A->data[0][0];
09561 if( !MTX_Malloc( A, B->nrows, B->ncols, B->isReal ) )
09562 {
09563 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09564 return FALSE;
09565 }
09566 if( !MTX_Fill( A, re ) )
09567 {
09568 MTX_ERROR_MSG( "MTX_Fill returned FALSE." );
09569 return FALSE;
09570 }
09571 return MTX_DotDivide_Inplace( A, B );
09572 }
09573 else
09574 {
09575 re = A->cplx[0][0].re;
09576 im = A->cplx[0][0].im;
09577 if( !MTX_Malloc( A, B->nrows, B->ncols, FALSE ) )
09578 {
09579 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09580 return FALSE;
09581 }
09582 if( !MTX_FillComplex( A, re, im ) )
09583 {
09584 MTX_ERROR_MSG( "MTX_FillComplex returned FALSE." );
09585 return FALSE;
09586 }
09587 return MTX_DotDivide_Inplace( A, B );
09588 }
09589 }
09590 else if( B->nrows == 1 && B->ncols == 1 )
09591 {
09592 if( B->isReal )
09593 {
09594 return MTX_Divide_Scalar( A, B->data[0][0] );
09595 }
09596 else
09597 {
09598 return MTX_Divide_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09599 }
09600 }
09601 }
09602
09603 if( !MTX_isConformalForAddition( A, B ) )
09604 {
09605 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09606 return FALSE;
09607 }
09608
09609 if( A->isReal && !B->isReal )
09610 {
09611 if( !MTX_ConvertRealToComplex( A ) )
09612 {
09613 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
09614 return FALSE;
09615 }
09616 }
09617
09618 if( A->isReal && B->isReal )
09619 {
09620 for( j = 0; j < A->ncols; j++ )
09621 {
09622 for( i = 0; i < A->nrows; i++ )
09623 {
09624 A->data[j][i] /= B->data[j][i];
09625 }
09626 }
09627 }
09628 else if( !A->isReal && !B->isReal )
09629 {
09630 for( j = 0; j < A->ncols; j++ )
09631 {
09632 for( i = 0; i < A->nrows; i++ )
09633 {
09634 mag = B->cplx[j][i].re*B->cplx[j][i].re + B->cplx[j][i].im*B->cplx[j][i].im;
09635
09636 re = (A->cplx[j][i].re * B->cplx[j][i].re + A->cplx[j][i].im * B->cplx[j][i].im ) / mag;
09637 im = (A->cplx[j][i].im * B->cplx[j][i].re - A->cplx[j][i].re * B->cplx[j][i].im ) / mag;
09638
09639 A->cplx[j][i].re = re;
09640 A->cplx[j][i].im = im;
09641 }
09642 }
09643 }
09644 else
09645 {
09646 for( j = 0; j < A->ncols; j++ )
09647 {
09648 for( i = 0; i < A->nrows; i++ )
09649 {
09650 A->cplx[j][i].re /= B->data[j][i];
09651 A->cplx[j][i].im /= B->data[j][i];
09652 }
09653 }
09654 }
09655 return TRUE;
09656 }
09657
09658 BOOL MTX_Add( MTX *A, const MTX* B, const MTX* C )
09659 {
09660 unsigned i = 0;
09661 unsigned j = 0;
09662
09663 if( MTX_isNull( B ) )
09664 {
09665 MTX_ERROR_MSG( "NULL Matrix" );
09666 return FALSE;
09667 }
09668
09669 if( MTX_isNull( C ) )
09670 {
09671 MTX_ERROR_MSG( "NULL Matrix" );
09672 return FALSE;
09673 }
09674
09675 if( MTX_static_global_treat_1x1_as_scalar )
09676 {
09677 if( B->nrows == 1 && B->ncols == 1 )
09678 {
09679 if( B->isReal )
09680 {
09681 if( !MTX_Copy( C, A ) )
09682 {
09683 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09684 return FALSE;
09685 }
09686 return MTX_Add_Scalar( A, B->data[0][0] );
09687 }
09688 else
09689 {
09690 if( !MTX_Copy( C, A ) )
09691 {
09692 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09693 return FALSE;
09694 }
09695 return MTX_Add_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09696 }
09697 }
09698 else if( C->nrows == 1 && C->ncols == 1 )
09699 {
09700 if( C->isReal )
09701 {
09702 if( !MTX_Copy( B, A ) )
09703 {
09704 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09705 return FALSE;
09706 }
09707 return MTX_Add_Scalar( A, C->data[0][0] );
09708 }
09709 else
09710 {
09711 if( !MTX_Copy( B, A ) )
09712 {
09713 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09714 return FALSE;
09715 }
09716 return MTX_Add_ScalarComplex( A, C->cplx[0][0].re, C->cplx[0][0].im );
09717 }
09718 }
09719 }
09720
09721
09722 if( !MTX_isConformalForAddition( B, C ) )
09723 {
09724 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09725 return FALSE;
09726 }
09727
09728 if( !B->isReal || !C->isReal )
09729 {
09730
09731 if( !A->isReal )
09732 {
09733 if( !MTX_Resize( A, B->nrows, B->ncols, FALSE ) )
09734 {
09735 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
09736 return FALSE;
09737 }
09738 }
09739 else
09740 {
09741 if( !MTX_Malloc( A, B->nrows, B->ncols, FALSE ) )
09742 {
09743 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09744 return FALSE;
09745 }
09746 }
09747 }
09748 else
09749 {
09750 if( !A->isReal )
09751 {
09752 if( !MTX_Malloc( A, B->nrows, B->ncols, TRUE ) )
09753 {
09754 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09755 return FALSE;
09756 }
09757 }
09758 else
09759 {
09760 if( !MTX_Resize( A, B->nrows, B->ncols, TRUE ) )
09761 {
09762 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
09763 return FALSE;
09764 }
09765 }
09766 }
09767
09768 if( B->isReal && C->isReal )
09769 {
09770 for( j = 0; j < B->ncols; j++ )
09771 for( i = 0; i < A->nrows; i++ )
09772 A->data[j][i] = B->data[j][i] + C->data[j][i];
09773 }
09774 else if( !B->isReal && !C->isReal )
09775 {
09776 for( j = 0; j < B->ncols; j++ )
09777 {
09778 for( i = 0; i < A->nrows; i++ )
09779 {
09780 A->cplx[j][i].re = B->cplx[j][i].re + C->cplx[j][i].re;
09781 A->cplx[j][i].im = B->cplx[j][i].im + C->cplx[j][i].im;
09782 }
09783 }
09784 }
09785 else if( !B->isReal && C->isReal )
09786 {
09787 for( j = 0; j < B->ncols; j++ )
09788 {
09789 for( i = 0; i < A->nrows; i++ )
09790 {
09791 A->cplx[j][i].re = B->cplx[j][i].re + C->data[j][i];
09792 A->cplx[j][i].im = B->cplx[j][i].im;
09793 }
09794 }
09795 }
09796 else
09797 {
09798 for( j = 0; j < B->ncols; j++ )
09799 {
09800 for( i = 0; i < A->nrows; i++ )
09801 {
09802 A->cplx[j][i].re = B->data[j][i] + C->cplx[j][i].re;
09803 A->cplx[j][i].im = C->cplx[j][i].im;
09804 }
09805 }
09806 }
09807 return TRUE;
09808 }
09809
09810 BOOL MTX_Subtract( MTX *A, const MTX* B, const MTX* C )
09811 {
09812 unsigned i = 0;
09813 unsigned j = 0;
09814
09815 if( MTX_isNull( B ) )
09816 {
09817 MTX_ERROR_MSG( "NULL Matrix" );
09818 return FALSE;
09819 }
09820
09821 if( MTX_isNull( C ) )
09822 {
09823 MTX_ERROR_MSG( "NULL Matrix" );
09824 return FALSE;
09825 }
09826
09827 if( MTX_static_global_treat_1x1_as_scalar )
09828 {
09829 if( B->nrows == 1 && B->ncols == 1 )
09830 {
09831
09832 if( B->isReal )
09833 {
09834 if( !MTX_Copy( C, A ) )
09835 {
09836 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09837 return FALSE;
09838 }
09839 if( !MTX_Negate( A ) )
09840 {
09841 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
09842 return FALSE;
09843 }
09844 return MTX_Add_Scalar( A, B->data[0][0] );
09845 }
09846 else
09847 {
09848 if( !MTX_Copy( C, A ) )
09849 {
09850 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09851 return FALSE;
09852 }
09853 if( !MTX_Negate( A ) )
09854 {
09855 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
09856 return FALSE;
09857 }
09858 return MTX_Add_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
09859 }
09860 }
09861 else if( C->nrows == 1 && C->ncols == 1 )
09862 {
09863
09864 if( C->isReal )
09865 {
09866 if( !MTX_Copy( B, A ) )
09867 {
09868 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09869 return FALSE;
09870 }
09871 return MTX_Subtract_Scalar( A, C->data[0][0] );
09872 }
09873 else
09874 {
09875 if( !MTX_Copy( B, A ) )
09876 {
09877 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
09878 return FALSE;
09879 }
09880 return MTX_Subtract_ScalarComplex( A, C->cplx[0][0].re, C->cplx[0][0].im );
09881 }
09882 }
09883 }
09884
09885 if( !MTX_isConformalForAddition( B, C ) )
09886 {
09887 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
09888 return FALSE;
09889 }
09890
09891 if( !B->isReal || !C->isReal )
09892 {
09893
09894 if( !A->isReal )
09895 {
09896
09897 if( !MTX_Resize( A, B->nrows, B->ncols, FALSE ) )
09898 {
09899 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
09900 return FALSE;
09901 }
09902 }
09903 else
09904 {
09905 if( !MTX_Malloc( A, B->nrows, B->ncols, FALSE ) )
09906 {
09907 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09908 return FALSE;
09909 }
09910 }
09911 }
09912 else
09913 {
09914
09915 if( !A->isReal )
09916 {
09917 if( !MTX_Malloc( A, B->nrows, B->ncols, TRUE ) )
09918 {
09919 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
09920 return FALSE;
09921 }
09922 }
09923 else
09924 {
09925
09926 if( !MTX_Resize( A, B->nrows, B->ncols, TRUE ) )
09927 {
09928 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
09929 return FALSE;
09930 }
09931 }
09932 }
09933
09934 if( B->isReal && C->isReal )
09935 {
09936 for( j = 0; j < B->ncols; j++ )
09937 for( i = 0; i < A->nrows; i++ )
09938 A->data[j][i] = B->data[j][i] - C->data[j][i];
09939 }
09940 else if( !B->isReal && !C->isReal )
09941 {
09942 for( j = 0; j < B->ncols; j++ )
09943 {
09944 for( i = 0; i < A->nrows; i++ )
09945 {
09946 A->cplx[j][i].re = B->cplx[j][i].re - C->cplx[j][i].re;
09947 A->cplx[j][i].im = B->cplx[j][i].im - C->cplx[j][i].im;
09948 }
09949 }
09950 }
09951 else if( !B->isReal && C->isReal )
09952 {
09953 for( j = 0; j < B->ncols; j++ )
09954 {
09955 for( i = 0; i < A->nrows; i++ )
09956 {
09957 A->cplx[j][i].re = B->cplx[j][i].re - C->data[j][i];
09958 A->cplx[j][i].im = B->cplx[j][i].im;
09959 }
09960 }
09961 }
09962 else
09963 {
09964 for( j = 0; j < B->ncols; j++ )
09965 {
09966 for( i = 0; i < A->nrows; i++ )
09967 {
09968 A->cplx[j][i].re = B->data[j][i] - C->cplx[j][i].re;
09969 A->cplx[j][i].im = -1.0*C->cplx[j][i].im;
09970 }
09971 }
09972 }
09973 return TRUE;
09974 }
09975
09976 BOOL MTX_Multiply( MTX *A, const MTX* B, const MTX* C )
09977 {
09978 unsigned i = 0;
09979 unsigned j = 0;
09980 unsigned k = 0;
09981
09982 if( MTX_isNull( B ) )
09983 {
09984 MTX_ERROR_MSG( "NULL Matrix" );
09985 return FALSE;
09986 }
09987 if( MTX_isNull( C ) )
09988 {
09989 MTX_ERROR_MSG( "NULL Matrix" );
09990 return FALSE;
09991 }
09992
09993 if( MTX_static_global_treat_1x1_as_scalar )
09994 {
09995 if( B->nrows == 1 && B->ncols == 1 )
09996 {
09997
09998 if( B->isReal )
09999 {
10000 if( !MTX_Copy( C, A ) )
10001 {
10002 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10003 return FALSE;
10004 }
10005 return MTX_Multiply_Scalar( A, B->data[0][0] );
10006 }
10007 else
10008 {
10009 if( !MTX_Copy( C, A ) )
10010 {
10011 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10012 return FALSE;
10013 }
10014 return MTX_Multiply_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
10015 }
10016 }
10017 else if( C->nrows == 1 && C->ncols == 1 )
10018 {
10019
10020 if( C->isReal )
10021 {
10022 if( !MTX_Copy( B, A ) )
10023 {
10024 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10025 return FALSE;
10026 }
10027 return MTX_Multiply_Scalar( A, C->data[0][0] );
10028 }
10029 else
10030 {
10031 if( !MTX_Copy( B, A ) )
10032 {
10033 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10034 return FALSE;
10035 }
10036 return MTX_Multiply_ScalarComplex( A, C->cplx[0][0].re, C->cplx[0][0].im );
10037 }
10038 }
10039 }
10040
10041
10042 if( !MTX_isConformalForMultiplication( B, C ) )
10043 {
10044 MTX_ERROR_MSG( "MTX_isConformalForMultiplication returned FALSE." );
10045 return FALSE;
10046 }
10047
10048 if( !B->isReal || !C->isReal )
10049 {
10050
10051 if( !A->isReal )
10052 {
10053
10054 if( !MTX_Resize( A, B->nrows, C->ncols, FALSE ) )
10055 {
10056 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10057 return FALSE;
10058 }
10059 }
10060 else
10061 {
10062 if( !MTX_Malloc( A, B->nrows, C->ncols, FALSE ) )
10063 {
10064 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10065 return FALSE;
10066 }
10067 }
10068 }
10069 else
10070 {
10071
10072 if( !A->isReal )
10073 {
10074 if( !MTX_Malloc( A, B->nrows, C->ncols, TRUE ) )
10075 {
10076 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10077 return FALSE;
10078 }
10079 }
10080 else
10081 {
10082
10083 if( !MTX_Resize( A, B->nrows, C->ncols, TRUE ) )
10084 {
10085 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10086 return FALSE;
10087 }
10088 }
10089 }
10090
10091
10092
10093 if( B->isReal && C->isReal )
10094 {
10095 for( i = 0; i < B->nrows; i++ )
10096 {
10097 for( j = 0; j < C->ncols; j++ )
10098 {
10099 k = 0;
10100 A->data[j][i] = B->data[k][i] * C->data[j][k];
10101 for( k = 1; k < B->ncols; k++ )
10102 {
10103 A->data[j][i] += B->data[k][i] * C->data[j][k];
10104 }
10105 }
10106 }
10107 }
10108 else if( !B->isReal && !C->isReal )
10109 {
10110 for( i = 0; i < B->nrows; i++ )
10111 {
10112 for( j = 0; j < C->ncols; j++ )
10113 {
10114 k = 0;
10115 A->cplx[j][i].re = B->cplx[k][i].re * C->cplx[j][k].re - B->cplx[k][i].im * C->cplx[j][k].im;
10116 A->cplx[j][i].im = B->cplx[k][i].re * C->cplx[j][k].im + B->cplx[k][i].im * C->cplx[j][k].re;
10117 for( k = 1; k < B->ncols; k++ )
10118 {
10119 A->cplx[j][i].re += B->cplx[k][i].re * C->cplx[j][k].re - B->cplx[k][i].im * C->cplx[j][k].im;
10120 A->cplx[j][i].im += B->cplx[k][i].re * C->cplx[j][k].im + B->cplx[k][i].im * C->cplx[j][k].re;
10121 }
10122 }
10123 }
10124 }
10125 else if( !B->isReal && C->isReal )
10126 {
10127 for( i = 0; i < B->nrows; i++ )
10128 {
10129 for( j = 0; j < C->ncols; j++ )
10130 {
10131 k = 0;
10132 A->cplx[j][i].re = B->cplx[k][i].re * C->data[j][k];
10133 A->cplx[j][i].im = B->cplx[k][i].im * C->data[j][k];
10134 for( k = 1; k < B->ncols; k++ )
10135 {
10136 A->cplx[j][i].re += B->cplx[k][i].re * C->data[j][k];
10137 A->cplx[j][i].im += B->cplx[k][i].im * C->data[j][k];
10138 }
10139 }
10140 }
10141 }
10142 else if( B->isReal && !C->isReal )
10143 {
10144 for( i = 0; i < B->nrows; i++ )
10145 {
10146 for( j = 0; j < C->ncols; j++ )
10147 {
10148 k = 0;
10149 A->cplx[j][i].re = B->data[k][i] * C->cplx[j][k].re;
10150 A->cplx[j][i].im = B->data[k][i] * C->cplx[j][k].im;
10151 for( k = 1; k < B->ncols; k++ )
10152 {
10153 A->cplx[j][i].re += B->data[k][i] * C->cplx[j][k].re;
10154 A->cplx[j][i].im += B->data[k][i] * C->cplx[j][k].im;
10155 }
10156 }
10157 }
10158 }
10159
10160 return TRUE;
10161 }
10162
10163 BOOL MTX_TransposeMultiply( MTX *A, const MTX* B, const MTX* C )
10164 {
10165 unsigned i = 0;
10166 unsigned j = 0;
10167 unsigned k = 0;
10168 MTX vec;
10169 MTX_Init( &vec );
10170
10171 if( MTX_isNull( B ) )
10172 {
10173 MTX_ERROR_MSG( "NULL Matrix" );
10174 return FALSE;
10175 }
10176 if( MTX_isNull( C ) )
10177 {
10178 MTX_ERROR_MSG( "NULL Matrix" );
10179 return FALSE;
10180 }
10181
10182 if( MTX_static_global_treat_1x1_as_scalar )
10183 {
10184 if( B->nrows == 1 && B->ncols == 1 )
10185 {
10186
10187 if( B->isReal )
10188 {
10189 if( !MTX_Copy( C, A ) )
10190 {
10191 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10192 return FALSE;
10193 }
10194 return MTX_Multiply_Scalar( A, B->data[0][0] );
10195 }
10196 else
10197 {
10198 if( !MTX_Copy( C, A ) )
10199 {
10200 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10201 return FALSE;
10202 }
10203 return MTX_Multiply_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
10204 }
10205 }
10206 else if( C->nrows == 1 && C->ncols == 1 )
10207 {
10208
10209 if( C->isReal )
10210 {
10211 if( !MTX_Copy( B, A ) )
10212 {
10213 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10214 return FALSE;
10215 }
10216 return MTX_Multiply_Scalar( A, C->data[0][0] );
10217 }
10218 else
10219 {
10220 if( !MTX_Copy( B, A ) )
10221 {
10222 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10223 return FALSE;
10224 }
10225 return MTX_Multiply_ScalarComplex( A, C->cplx[0][0].re, C->cplx[0][0].im );
10226 }
10227 }
10228 }
10229
10230
10231 if( B->nrows != C->nrows )
10232 {
10233 MTX_ERROR_MSG( "Not conformal for multiplication." );
10234 return FALSE;
10235 }
10236
10237 if( !B->isReal || !C->isReal )
10238 {
10239
10240 if( !A->isReal )
10241 {
10242
10243 if( !MTX_Resize( A, B->ncols, C->ncols, FALSE ) )
10244 {
10245 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10246 return FALSE;
10247 }
10248 }
10249 else
10250 {
10251 if( !MTX_Malloc( A, B->ncols, C->ncols, FALSE ) )
10252 {
10253 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10254 return FALSE;
10255 }
10256 }
10257 }
10258 else
10259 {
10260
10261 if( !A->isReal )
10262 {
10263 if( !MTX_Malloc( A, B->ncols, C->ncols, TRUE ) )
10264 {
10265 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10266 return FALSE;
10267 }
10268 }
10269 else
10270 {
10271
10272 if( !MTX_Resize( A, B->ncols, C->ncols, TRUE ) )
10273 {
10274 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10275 return FALSE;
10276 }
10277 }
10278 }
10279
10280
10281
10282 if( B->isReal && C->isReal )
10283 {
10284 for( i = 0; i < B->ncols; i++ )
10285 {
10286 for( j = 0; j < C->ncols; j++ )
10287 {
10288 k = 0;
10289 A->data[j][i] = B->data[i][k] * C->data[j][k];
10290 for( k = 1; k < B->nrows; k++ )
10291 {
10292 A->data[j][i] += B->data[i][k] * C->data[j][k];
10293 }
10294 }
10295 }
10296 }
10297 else if( !B->isReal && !C->isReal )
10298 {
10299 for( i = 0; i < B->ncols; i++ )
10300 {
10301 for( j = 0; j < C->ncols; j++ )
10302 {
10303 k = 0;
10304 A->cplx[j][i].re = B->cplx[i][k].re * C->cplx[j][k].re - B->cplx[i][k].im * C->cplx[j][k].im;
10305 A->cplx[j][i].im = B->cplx[i][k].re * C->cplx[j][k].im + B->cplx[i][k].im * C->cplx[j][k].re;
10306 for( k = 1; k < B->nrows; k++ )
10307 {
10308 A->cplx[j][i].re += B->cplx[i][k].re * C->cplx[j][k].re - B->cplx[i][k].im * C->cplx[j][k].im;
10309 A->cplx[j][i].im += B->cplx[i][k].re * C->cplx[j][k].im + B->cplx[i][k].im * C->cplx[j][k].re;
10310 }
10311 }
10312 }
10313 }
10314 else if( !B->isReal && C->isReal )
10315 {
10316 for( i = 0; i < B->ncols; i++ )
10317 {
10318 for( j = 0; j < C->ncols; j++ )
10319 {
10320 k = 0;
10321 A->cplx[j][i].re = B->cplx[i][k].re * C->data[j][k];
10322 A->cplx[j][i].im = B->cplx[i][k].im * C->data[j][k];
10323 for( k = 1; k < B->nrows; k++ )
10324 {
10325 A->cplx[j][i].re += B->cplx[i][k].re * C->data[j][k];
10326 A->cplx[j][i].im += B->cplx[i][k].im * C->data[j][k];
10327 }
10328 }
10329 }
10330 }
10331 else if( B->isReal && !C->isReal )
10332 {
10333 for( i = 0; i < B->ncols; i++ )
10334 {
10335 for( j = 0; j < C->ncols; j++ )
10336 {
10337 k = 0;
10338 A->cplx[j][i].re = B->data[i][k] * C->cplx[j][k].re;
10339 A->cplx[j][i].im = B->data[i][k] * C->cplx[j][k].im;
10340 for( k = 1; k < B->nrows; k++ )
10341 {
10342 A->cplx[j][i].re += B->data[i][k] * C->cplx[j][k].re;
10343 A->cplx[j][i].im += B->data[i][k] * C->cplx[j][k].im;
10344 }
10345 }
10346 }
10347 }
10348
10349 return TRUE;
10350 }
10351
10352
10353 BOOL MTX_MultiplyTranspose( MTX *A, const MTX* B, const MTX* C )
10354 {
10355 unsigned i = 0;
10356 unsigned j = 0;
10357 unsigned k = 0;
10358
10359 if( MTX_isNull( B ) )
10360 {
10361 MTX_ERROR_MSG( "NULL Matrix" );
10362 return FALSE;
10363 }
10364 if( MTX_isNull( C ) )
10365 {
10366 MTX_ERROR_MSG( "NULL Matrix" );
10367 return FALSE;
10368 }
10369
10370 if( MTX_static_global_treat_1x1_as_scalar )
10371 {
10372 if( B->nrows == 1 && B->ncols == 1 )
10373 {
10374
10375 if( B->isReal )
10376 {
10377 if( !MTX_Copy( C, A ) )
10378 {
10379 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10380 return FALSE;
10381 }
10382 return MTX_Multiply_Scalar( A, B->data[0][0] );
10383 }
10384 else
10385 {
10386 if( !MTX_Copy( C, A ) )
10387 {
10388 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10389 return FALSE;
10390 }
10391 return MTX_Multiply_ScalarComplex( A, B->cplx[0][0].re, B->cplx[0][0].im );
10392 }
10393 }
10394 else if( C->nrows == 1 && C->ncols == 1 )
10395 {
10396
10397 if( C->isReal )
10398 {
10399 if( !MTX_Copy( B, A ) )
10400 {
10401 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10402 return FALSE;
10403 }
10404 return MTX_Multiply_Scalar( A, C->data[0][0] );
10405 }
10406 else
10407 {
10408 if( !MTX_Copy( B, A ) )
10409 {
10410 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
10411 return FALSE;
10412 }
10413 return MTX_Multiply_ScalarComplex( A, C->cplx[0][0].re, C->cplx[0][0].im );
10414 }
10415 }
10416 }
10417
10418
10419 if( B->ncols != C->ncols )
10420 {
10421 MTX_ERROR_MSG( "Not conformal for multiplication." );
10422 return FALSE;
10423 }
10424
10425
10426
10427 if( !B->isReal || !C->isReal )
10428 {
10429
10430 if( !A->isReal )
10431 {
10432
10433 if( !MTX_Resize( A, B->nrows, C->nrows, FALSE ) )
10434 {
10435 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10436 return FALSE;
10437 }
10438 }
10439 else
10440 {
10441 if( !MTX_Malloc( A, B->nrows, C->nrows, FALSE ) )
10442 {
10443 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10444 return FALSE;
10445 }
10446 }
10447 }
10448 else
10449 {
10450
10451 if( !A->isReal )
10452 {
10453 if( !MTX_Malloc( A, B->nrows, C->nrows, TRUE ) )
10454 {
10455 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
10456 return FALSE;
10457 }
10458 }
10459 else
10460 {
10461
10462 if( !MTX_Resize( A, B->nrows, C->nrows, TRUE ) )
10463 {
10464 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10465 return FALSE;
10466 }
10467 }
10468 }
10469
10470 if( B->isReal && C->isReal )
10471 {
10472 for( i = 0; i < B->nrows; i++ )
10473 {
10474 for( j = 0; j < C->nrows; j++ )
10475 {
10476 k = 0;
10477 A->data[j][i] = B->data[k][i] * C->data[k][j];
10478 for( k = 1; k < B->ncols; k++ )
10479 {
10480 A->data[j][i] += B->data[k][i] * C->data[k][j];
10481 }
10482 }
10483 }
10484 }
10485 else if( !B->isReal && !C->isReal )
10486 {
10487 for( i = 0; i < B->nrows; i++ )
10488 {
10489 for( j = 0; j < C->nrows; j++ )
10490 {
10491 k = 0;
10492 A->cplx[j][i].re = B->cplx[k][i].re * C->cplx[k][j].re - B->cplx[k][i].im * C->cplx[k][j].im;
10493 A->cplx[j][i].im = B->cplx[k][i].re * C->cplx[k][j].im + B->cplx[k][i].im * C->cplx[k][j].re;
10494 for( k = 1; k < B->ncols; k++ )
10495 {
10496 A->cplx[j][i].re += B->cplx[k][i].re * C->cplx[k][j].re - B->cplx[k][i].im * C->cplx[k][j].im;
10497 A->cplx[j][i].im += B->cplx[k][i].re * C->cplx[k][j].im + B->cplx[k][i].im * C->cplx[k][j].re;
10498 }
10499 }
10500 }
10501 }
10502 else if( !B->isReal && C->isReal )
10503 {
10504 for( i = 0; i < B->nrows; i++ )
10505 {
10506 for( j = 0; j < C->nrows; j++ )
10507 {
10508 k = 0;
10509 A->cplx[j][i].re = B->cplx[k][i].re * C->data[k][j];
10510 A->cplx[j][i].im = B->cplx[k][i].im * C->data[k][j];
10511 for( k = 1; k < B->ncols; k++ )
10512 {
10513 A->cplx[j][i].re += B->cplx[k][i].re * C->data[k][j];
10514 A->cplx[j][i].im += B->cplx[k][i].im * C->data[k][j];
10515 }
10516 }
10517 }
10518 }
10519 else if( B->isReal && !C->isReal )
10520 {
10521 for( i = 0; i < B->nrows; i++ )
10522 {
10523 for( j = 0; j < C->nrows; j++ )
10524 {
10525 k = 0;
10526 A->cplx[j][i].re = B->data[k][i] * C->cplx[k][j].re;
10527 A->cplx[j][i].im = B->data[k][i] * C->cplx[k][j].im;
10528 for( k = 1; k < B->ncols; k++ )
10529 {
10530 A->cplx[j][i].re += B->data[k][i] * C->cplx[k][j].re;
10531 A->cplx[j][i].im += B->data[k][i] * C->cplx[k][j].im;
10532 }
10533 }
10534 }
10535 }
10536 return TRUE;
10537 }
10538
10539
10540
10541 BOOL MTX_IsEqual( const MTX *A, const MTX *B, const double tolerance, BOOL *isEqual )
10542 {
10543 unsigned i = 0;
10544 unsigned j = 0;
10545 double fabsval;
10546
10547 if( MTX_isNull( A ) )
10548 {
10549 MTX_ERROR_MSG( "NULL Matrix" );
10550 return FALSE;
10551 }
10552
10553 if( MTX_isNull( B ) )
10554 {
10555 MTX_ERROR_MSG( "NULL Matrix" );
10556 return FALSE;
10557 }
10558
10559
10560 if( MTX_static_global_treat_1x1_as_scalar )
10561 {
10562 if( A->nrows == 1 && A->ncols == 1 )
10563 {
10564 if( A->isReal )
10565 {
10566 if( B->isReal )
10567 {
10568 for( j = 0; j < B->ncols; j++ )
10569 {
10570 for( i = 0; i < B->nrows; i++ )
10571 {
10572 fabsval = fabs( A->data[0][0] - B->data[j][i] );
10573 if( fabsval > tolerance )
10574 {
10575 *isEqual = FALSE;
10576 return TRUE;
10577 }
10578 }
10579 }
10580 *isEqual = TRUE;
10581 return TRUE;
10582 }
10583 else
10584 {
10585
10586 for( j = 0; j < B->ncols; j++ )
10587 {
10588 for( i = 0; i < B->nrows; i++ )
10589 {
10590 fabsval = fabs( A->data[0][0] - B->cplx[j][i].re );
10591 if( fabsval > tolerance )
10592 {
10593 *isEqual = FALSE;
10594 return TRUE;
10595 }
10596
10597 fabsval = fabs( B->cplx[j][i].im );
10598 if( fabsval > tolerance )
10599 {
10600 *isEqual = FALSE;
10601 return TRUE;
10602 }
10603 }
10604 }
10605 *isEqual = TRUE;
10606 return TRUE;
10607 }
10608 }
10609 else
10610 {
10611 if( B->isReal )
10612 {
10613 fabsval = fabs( A->cplx[0][0].im );
10614 if( fabsval > tolerance )
10615 {
10616 *isEqual = FALSE;
10617 return TRUE;
10618 }
10619
10620 for( j = 0; j < B->ncols; j++ )
10621 {
10622 for( i = 0; i < B->nrows; i++ )
10623 {
10624 fabsval = fabs( A->cplx[0][0].re - B->data[j][i] );
10625 if( fabsval > tolerance )
10626 {
10627 *isEqual = FALSE;
10628 return TRUE;
10629 }
10630 }
10631 }
10632 *isEqual = TRUE;
10633 return TRUE;
10634 }
10635 else
10636 {
10637
10638 for( j = 0; j < B->ncols; j++ )
10639 {
10640 for( i = 0; i < B->nrows; i++ )
10641 {
10642 fabsval = fabs( A->cplx[0][0].re - B->cplx[j][i].re );
10643 if( fabsval > tolerance )
10644 {
10645 *isEqual = FALSE;
10646 return TRUE;
10647 }
10648
10649 fabsval = fabs( A->cplx[0][0].im - B->cplx[j][i].im );
10650 if( fabsval > tolerance )
10651 {
10652 *isEqual = FALSE;
10653 return TRUE;
10654 }
10655 }
10656 }
10657 *isEqual = TRUE;
10658 return TRUE;
10659 }
10660 }
10661 }
10662 else if( B->nrows == 1 && B->ncols == 1 )
10663 {
10664
10665 return MTX_IsEqual( B, A, tolerance, isEqual );
10666 }
10667 }
10668
10669 if( !MTX_isConformalForAddition( A, B ) )
10670 {
10671 MTX_ERROR_MSG( "MTX_isConformalForAddition returned FALSE." );
10672 return FALSE;
10673 }
10674
10675 *isEqual = TRUE;
10676
10677 if( A->isReal && B->isReal )
10678 {
10679 for( j = 0; j < A->ncols; j++ )
10680 {
10681 for( i = 0; i < A->nrows; i++ )
10682 {
10683 fabsval = fabs( A->data[j][i] - B->data[j][i] );
10684 if( fabsval > tolerance )
10685 {
10686 *isEqual = FALSE;
10687 return TRUE;
10688 }
10689 }
10690 }
10691 }
10692 else if( !A->isReal && !B->isReal )
10693 {
10694 for( j = 0; j < A->ncols; j++ )
10695 {
10696 for( i = 0; i < A->nrows; i++ )
10697 {
10698 fabsval = fabs( A->cplx[j][i].re - B->cplx[j][i].re );
10699 if( fabsval > tolerance )
10700 {
10701 *isEqual = FALSE;
10702 return TRUE;
10703 }
10704 fabsval = fabs( A->cplx[j][i].im - B->cplx[j][i].im );
10705 if( fabsval > tolerance )
10706 {
10707 *isEqual = FALSE;
10708 return TRUE;
10709 }
10710 }
10711 }
10712 }
10713 else if( !A->isReal && B->isReal )
10714 {
10715 for( j = 0; j < A->ncols; j++ )
10716 {
10717 for( i = 0; i < A->nrows; i++ )
10718 {
10719 fabsval = fabs( A->cplx[j][i].re - B->data[j][i] );
10720 if( fabsval > tolerance )
10721 {
10722 *isEqual = FALSE;
10723 return TRUE;
10724 }
10725 fabsval = fabs( A->cplx[j][i].im );
10726 if( fabsval > tolerance )
10727 {
10728 *isEqual = FALSE;
10729 return TRUE;
10730 }
10731 }
10732 }
10733 }
10734 else if( A->isReal && !B->isReal )
10735 {
10736 for( j = 0; j < A->ncols; j++ )
10737 {
10738 for( i = 0; i < A->nrows; i++ )
10739 {
10740 fabsval = fabs( A->data[j][i] - B->cplx[j][i].re );
10741 if( fabsval > tolerance )
10742 {
10743 *isEqual = FALSE;
10744 return TRUE;
10745 }
10746 fabsval = fabs( B->cplx[j][i].im );
10747 if( fabsval > tolerance )
10748 {
10749 *isEqual = FALSE;
10750 return TRUE;
10751 }
10752 }
10753 }
10754 }
10755
10756 return TRUE;
10757 }
10758
10759 BOOL MTX_ColumnDiff( const MTX *M, MTX *Diff, const unsigned col )
10760 {
10761 unsigned i = 0;
10762
10763 if( MTX_isNull( M ) )
10764 {
10765 MTX_ERROR_MSG( "NULL Matrix" );
10766 return FALSE;
10767 }
10768
10769 if( col >= M->ncols )
10770 {
10771 MTX_ERROR_MSG( "if( col >= M->ncols )" );
10772 return FALSE;
10773 }
10774
10775 if( M->nrows == 1 )
10776 {
10777 MTX_ERROR_MSG( "if( M->nrows == 1 )" );
10778 return FALSE;
10779 }
10780
10781 if( M->isReal != Diff->isReal )
10782 {
10783 if( !MTX_Resize( Diff, M->nrows-1, 1, M->isReal ) )
10784 {
10785 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10786 return FALSE;
10787 }
10788 }
10789 else if( Diff->nrows != M->nrows-1 || Diff->ncols != 1 )
10790 {
10791 if( !MTX_Resize( Diff, M->nrows-1, 1, M->isReal ) )
10792 {
10793 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10794 return FALSE;
10795 }
10796 }
10797
10798 if( M->isReal )
10799 {
10800 for( i = 0; i < M->nrows-1; i++ )
10801 {
10802 Diff->data[0][i] = M->data[col][i+1] - M->data[col][i];
10803 }
10804 }
10805 else
10806 {
10807 for( i = 0; i < M->nrows-1; i++ )
10808 {
10809 Diff->cplx[0][i].re = M->cplx[col][i+1].re - M->cplx[col][i].re;
10810 Diff->cplx[0][i].im = M->cplx[col][i+1].im - M->cplx[col][i].im;
10811 }
10812 }
10813
10814 return TRUE;
10815 }
10816
10817 BOOL MTX_Diff( const MTX *M, MTX *Diff )
10818 {
10819 unsigned i = 0;
10820 unsigned j = 0;
10821
10822 if( MTX_isNull( M ) )
10823 {
10824 MTX_ERROR_MSG( "NULL Matrix" );
10825 return FALSE;
10826 }
10827
10828 if( M->nrows == 1 )
10829 {
10830 MTX_ERROR_MSG( "if( M->nrows == 1 )" );
10831 return FALSE;
10832 }
10833
10834 if( M->isReal != Diff->isReal )
10835 {
10836 if( !MTX_Resize( Diff, M->nrows-1, M->ncols, M->isReal ) )
10837 {
10838 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10839 return FALSE;
10840 }
10841 }
10842 else if( Diff->nrows != M->nrows-1 || Diff->ncols != M->ncols )
10843 {
10844 if( !MTX_Resize( Diff, M->nrows-1, M->ncols, M->isReal ) )
10845 {
10846 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
10847 return FALSE;
10848 }
10849 }
10850
10851
10852 if( M->isReal )
10853 {
10854 for( j = 0; j < M->ncols; j++ )
10855 {
10856 for( i = 0; i < M->nrows-1; i++ )
10857 {
10858 Diff->data[j][i] = M->data[j][i+1] - M->data[j][i];
10859 }
10860 }
10861 }
10862 else
10863 {
10864 for( j = 0; j < M->ncols; j++ )
10865 {
10866 for( i = 0; i < M->nrows-1; i++ )
10867 {
10868 Diff->cplx[j][i].re = M->cplx[j][i+1].re - M->cplx[j][i].re;
10869 Diff->cplx[j][i].im = M->cplx[j][i+1].im - M->cplx[j][i].im;
10870 }
10871 }
10872 }
10873
10874 return TRUE;
10875 }
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890 BOOL MTX_MaxColIndex( const MTX *M, const unsigned col, double *re, double *im, unsigned *row )
10891 {
10892 unsigned i = 0;
10893
10894 if( MTX_isNull( M ) )
10895 {
10896 MTX_ERROR_MSG( "NULL Matrix" );
10897 return FALSE;
10898 }
10899
10900 if( col >= M->ncols )
10901 {
10902 MTX_ERROR_MSG( "if( col >= M->ncols )" );
10903 return FALSE;
10904 }
10905
10906 if( M->isReal )
10907 {
10908 *im = 0;
10909 *re = M->data[col][0];
10910 *row = 0;
10911 for( i = 1; i < M->nrows; i++ )
10912 {
10913 if( M->data[col][i] > *re )
10914 {
10915 *re = M->data[col][i];
10916 *row = i;
10917 }
10918 }
10919 }
10920 else
10921 {
10922 MTX C;
10923 MTX mag;
10924 MTX_Init( &C );
10925 MTX_Init( &mag );
10926
10927 if( !MTX_CopyColumn( M, col, &C ) )
10928 {
10929 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
10930 return FALSE;
10931 }
10932 if( !MTX_Magnitude( &C, &mag ) )
10933 {
10934 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
10935 MTX_Free( &C );
10936 return FALSE;
10937 }
10938
10939 *re = 0;
10940 *im = 0;
10941 *re = mag.data[0][0];
10942 *row = 0;
10943 for( i = 1; i < mag.nrows; i++ )
10944 {
10945 if( mag.data[0][i] > *re )
10946 {
10947 *re = mag.data[0][i];
10948 *row = i;
10949 }
10950 }
10951
10952 *re = C.cplx[0][*row].re;
10953 *im = C.cplx[0][*row].im;
10954
10955 MTX_Free( &C );
10956 MTX_Free( &mag );
10957 }
10958
10959 return TRUE;
10960 }
10961
10962 BOOL MTX_MaxRowIndex( const MTX *M, const unsigned row, double *re, double *im, unsigned *col )
10963 {
10964 unsigned i = 0;
10965
10966 if( MTX_isNull( M ) )
10967 {
10968 MTX_ERROR_MSG( "NULL Matrix" );
10969 return FALSE;
10970 }
10971
10972 if( row >= M->nrows )
10973 {
10974 MTX_ERROR_MSG( "if( row >= M->nrows )" );
10975 return FALSE;
10976 }
10977
10978 if( M->isReal )
10979 {
10980 *im = 0;
10981 *re = M->data[0][row];
10982 *col = 0;
10983 for( i = 1; i < M->ncols; i++ )
10984 {
10985 if( M->data[i][row] > *re )
10986 {
10987 *re = M->data[i][row];
10988 *col = i;
10989 }
10990 }
10991 }
10992 else
10993 {
10994 MTX C;
10995 MTX mag;
10996 MTX_Init( &C );
10997 MTX_Init( &mag );
10998
10999 if( !MTX_CopyRowIntoAColumnMatrix( M, row, &C ) )
11000 {
11001 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
11002 return FALSE;
11003 }
11004 if( !MTX_Magnitude( &C, &mag ) )
11005 {
11006 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
11007 MTX_Free( &C );
11008 return FALSE;
11009 }
11010
11011 *re = 0;
11012 *im = 0;
11013 *re = mag.data[0][0];
11014 *col = 0;
11015 for( i = 1; i < mag.nrows; i++ )
11016 {
11017 if( mag.data[0][i] > *re )
11018 {
11019 *re = mag.data[0][i];
11020 *col = i;
11021 }
11022 }
11023
11024 *re = M->cplx[*col][row].re;
11025 *im = M->cplx[*col][row].im;
11026
11027 MTX_Free( &C );
11028 MTX_Free( &mag );
11029 }
11030
11031 return TRUE;
11032 }
11033
11034 BOOL MTX_MinColIndex( const MTX *M, const unsigned col, double *re, double *im, unsigned *row )
11035 {
11036 unsigned i = 0;
11037
11038 if( MTX_isNull( M ) )
11039 {
11040 MTX_ERROR_MSG( "NULL Matrix" );
11041 return FALSE;
11042 }
11043
11044 if( col >= M->ncols )
11045 {
11046 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11047 return FALSE;
11048 }
11049
11050 if( M->isReal )
11051 {
11052 *im = 0;
11053 *re = M->data[col][0];
11054 *row = 0;
11055 for( i = 1; i < M->nrows; i++ )
11056 {
11057 if( M->data[col][i] < *re )
11058 {
11059 *re = M->data[col][i];
11060 *row = i;
11061 }
11062 }
11063 }
11064 else
11065 {
11066 MTX C;
11067 MTX mag;
11068 MTX_Init( &C );
11069 MTX_Init( &mag );
11070
11071 if( !MTX_CopyColumn( M, col, &C ) )
11072 {
11073 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
11074 return FALSE;
11075 }
11076 if( !MTX_Magnitude( &C, &mag ) )
11077 {
11078 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
11079 MTX_Free( &C );
11080 return FALSE;
11081 }
11082
11083 *re = 0;
11084 *im = 0;
11085 *re = mag.data[0][0];
11086 *row = 0;
11087 for( i = 1; i < mag.nrows; i++ )
11088 {
11089 if( mag.data[0][i] < *re )
11090 {
11091 *re = mag.data[0][i];
11092 *row = i;
11093 }
11094 }
11095
11096 *re = C.cplx[0][*row].re;
11097 *im = C.cplx[0][*row].im;
11098
11099 MTX_Free( &C );
11100 MTX_Free( &mag );
11101 }
11102
11103 return TRUE;
11104 }
11105
11106 BOOL MTX_MinRowIndex( const MTX *M, const unsigned row, double *re, double *im, unsigned *col )
11107 {
11108 unsigned i = 0;
11109
11110 if( MTX_isNull( M ) )
11111 {
11112 MTX_ERROR_MSG( "NULL Matrix" );
11113 return FALSE;
11114 }
11115
11116 if( row >= M->nrows )
11117 {
11118 MTX_ERROR_MSG( "if( row >= M->nrows )" );
11119 return FALSE;
11120 }
11121
11122 if( M->isReal )
11123 {
11124 *im = 0;
11125 *re = M->data[0][row];
11126 *col = 0;
11127 for( i = 1; i < M->ncols; i++ )
11128 {
11129 if( M->data[i][row] < *re )
11130 {
11131 *re = M->data[i][row];
11132 *col = i;
11133 }
11134 }
11135 }
11136 else
11137 {
11138 MTX C;
11139 MTX mag;
11140 MTX_Init( &C );
11141 MTX_Init( &mag );
11142
11143 if( !MTX_CopyRowIntoAColumnMatrix( M, row, &C ) )
11144 {
11145 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
11146 return FALSE;
11147 }
11148 if( !MTX_Magnitude( &C, &mag ) )
11149 {
11150 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
11151 MTX_Free( &C );
11152 return FALSE;
11153 }
11154
11155 *re = 0;
11156 *im = 0;
11157 *re = mag.data[0][0];
11158 *col = 0;
11159 for( i = 1; i < mag.nrows; i++ )
11160 {
11161 if( mag.data[0][i] < *re )
11162 {
11163 *re = mag.data[0][i];
11164 *col = i;
11165 }
11166 }
11167
11168 *re = M->cplx[*col][row].re;
11169 *im = M->cplx[*col][row].im;
11170
11171 MTX_Free( &C );
11172 MTX_Free( &mag );
11173 }
11174
11175 return TRUE;
11176 }
11177
11178 BOOL MTX_MaxAbsColIndex( const MTX *M, const unsigned col, double *value, unsigned *row )
11179 {
11180 double re;
11181 double im;
11182 MTX copyCol;
11183
11184 if( MTX_isNull( M ) )
11185 {
11186 MTX_ERROR_MSG( "NULL Matrix" );
11187 return FALSE;
11188 }
11189
11190 if( col >= M->ncols )
11191 {
11192 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11193 return FALSE;
11194 }
11195
11196
11197 MTX_Init( ©Col );
11198
11199
11200 if( !MTX_CopyColumn( M, col, ©Col ) )
11201 {
11202 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
11203 return FALSE;
11204 }
11205
11206
11207 if( !MTX_Abs( ©Col ) )
11208 {
11209 MTX_ERROR_MSG( "MTX_Abs returned FALSE." );
11210 MTX_Free( ©Col );
11211 return FALSE;
11212 }
11213
11214
11215 if( !MTX_MaxColIndex( ©Col, 0, &re, &im, row ) )
11216 {
11217 MTX_ERROR_MSG( "MTX_MaxColIndex returned FALSE." );
11218 MTX_Free( ©Col );
11219 return FALSE;
11220 }
11221
11222 *value = re;
11223
11224 MTX_Free( ©Col );
11225 return TRUE;
11226 }
11227
11228 BOOL MTX_MaxAbsRowIndex( const MTX *M, const unsigned row, double *value, unsigned *col )
11229 {
11230 double re;
11231 double im;
11232 MTX copyCol;
11233
11234 if( MTX_isNull( M ) )
11235 {
11236 MTX_ERROR_MSG( "NULL Matrix" );
11237 return FALSE;
11238 }
11239
11240 if( row >= M->nrows )
11241 {
11242 MTX_ERROR_MSG( "if( row >= M->nrows )" );
11243 return FALSE;
11244 }
11245
11246
11247 MTX_Init( ©Col );
11248
11249
11250 if( !MTX_CopyRowIntoAColumnMatrix( M, row, ©Col ) )
11251 {
11252 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
11253 MTX_Free( ©Col );
11254 return FALSE;
11255 }
11256
11257
11258 if( !MTX_Abs( ©Col ) )
11259 {
11260 MTX_ERROR_MSG( "MTX_Abs returned FALSE." );
11261 MTX_Free( ©Col );
11262 return FALSE;
11263 }
11264
11265
11266 if( !MTX_MaxColIndex( ©Col, 0, &re, &im, col ) )
11267 {
11268 MTX_ERROR_MSG( "MTX_MaxColIndex returned FALSE." );
11269 MTX_Free( ©Col );
11270 return FALSE;
11271 }
11272
11273 *value = re;
11274
11275 MTX_Free( ©Col );
11276 return TRUE;
11277 }
11278
11279 BOOL MTX_MinAbsColIndex( const MTX *M, const unsigned col, double *value, unsigned *row )
11280 {
11281 double re;
11282 double im;
11283 MTX copyCol;
11284
11285 if( MTX_isNull( M ) )
11286 {
11287 MTX_ERROR_MSG( "NULL Matrix" );
11288 return FALSE;
11289 }
11290
11291 if( col >= M->ncols )
11292 {
11293 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11294 return FALSE;
11295 }
11296
11297
11298 MTX_Init( ©Col );
11299
11300
11301 if( !MTX_CopyColumn( M, col, ©Col ) )
11302 {
11303 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
11304 MTX_Free( ©Col );
11305 return FALSE;
11306 }
11307
11308
11309 if( !MTX_Abs( ©Col ) )
11310 {
11311 MTX_ERROR_MSG( "MTX_Abs returned FALSE." );
11312 MTX_Free( ©Col );
11313 return FALSE;
11314 }
11315
11316
11317 if( !MTX_MinColIndex( ©Col, 0, &re, &im, row ) )
11318 {
11319 MTX_ERROR_MSG( "MTX_MinColIndex returned FALSE." );
11320 MTX_Free( ©Col );
11321 return FALSE;
11322 }
11323
11324 *value = re;
11325
11326 MTX_Free( ©Col );
11327 return TRUE;
11328 }
11329
11330 BOOL MTX_MinAbsRowIndex( const MTX *M, const unsigned row, double *value, unsigned *col )
11331 {
11332 double re;
11333 double im;
11334 MTX copyCol;
11335
11336 if( MTX_isNull( M ) )
11337 {
11338 MTX_ERROR_MSG( "NULL Matrix" );
11339 return FALSE;
11340 }
11341
11342 if( row >= M->nrows )
11343 {
11344 MTX_ERROR_MSG( "if( row >= M->nrows )" );
11345 return FALSE;
11346 }
11347
11348
11349 MTX_Init( ©Col );
11350
11351
11352 if( !MTX_CopyRowIntoAColumnMatrix( M, row, ©Col ) )
11353 {
11354 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
11355 MTX_Free( ©Col );
11356 return FALSE;
11357 }
11358
11359
11360 if( !MTX_Abs( ©Col ) )
11361 {
11362 MTX_ERROR_MSG( "MTX_Abs returned FALSE." );
11363 MTX_Free( ©Col );
11364 return FALSE;
11365 }
11366
11367
11368 if( !MTX_MinColIndex( ©Col, 0, &re, &im, col ) )
11369 {
11370 MTX_ERROR_MSG( "MTX_MinColIndex returned FALSE." );
11371 MTX_Free( ©Col );
11372 return FALSE;
11373 }
11374
11375 *value = re;
11376
11377 MTX_Free( ©Col );
11378 return TRUE;
11379 }
11380
11381 BOOL MTX_MaxColumn( const MTX *M, const unsigned col, double *re, double *im )
11382 {
11383 unsigned row;
11384 return MTX_MaxColIndex( M, col, re, im, &row );
11385 }
11386
11387 BOOL MTX_MaxRow( const MTX *M, const unsigned row, double *re, double *im )
11388 {
11389 unsigned col;
11390 return MTX_MaxRowIndex( M, row, re, im, &col );
11391 }
11392
11393 BOOL MTX_MinColumn( const MTX *M, const unsigned col, double *re, double *im )
11394 {
11395 unsigned row;
11396 return MTX_MinColIndex( M, col, re, im, &row );
11397 }
11398
11399 BOOL MTX_MinRow( const MTX *M, const unsigned row, double *re, double *im )
11400 {
11401 unsigned col;
11402 return MTX_MinRowIndex( M, row, re, im, &col );
11403 }
11404
11405 BOOL MTX_MaxAbsColumn( const MTX *M, const unsigned col, double *value )
11406 {
11407 unsigned row;
11408 return MTX_MaxAbsColIndex( M, col, value, &row );
11409 }
11410
11411 BOOL MTX_MaxAbsRow( const MTX *M, const unsigned row, double *value )
11412 {
11413 unsigned col;
11414 return MTX_MaxAbsRowIndex( M, row, value, &col );
11415 }
11416
11417 BOOL MTX_MinAbsColumn( const MTX *M, const unsigned col, double *value )
11418 {
11419 unsigned row;
11420 return MTX_MinAbsColIndex( M, col, value, &row );
11421 }
11422
11423 BOOL MTX_MinAbsRow( const MTX *M, const unsigned row, double *value )
11424 {
11425 unsigned col;
11426 return MTX_MinAbsRowIndex( M, row, value, &col );
11427 }
11428
11429 BOOL MTX_MaxAbsIndex( const MTX *M, double* value, unsigned *row, unsigned *col )
11430 {
11431 unsigned j = 0;
11432 unsigned trow = 0;
11433 double tval = 0.0;
11434
11435 if( MTX_isNull( M ) )
11436 {
11437 MTX_ERROR_MSG( "NULL Matrix" );
11438 return FALSE;
11439 }
11440
11441 *col = 0;
11442 if( !MTX_MaxAbsColIndex( M, 0, value, row ) )
11443 {
11444 MTX_ERROR_MSG( "MTX_MaxAbsColIndex returned FALSE." );
11445 return FALSE;
11446 }
11447
11448 for( j = 1; j < M->ncols; j++ )
11449 {
11450 if( !MTX_MaxAbsColIndex( M, j, &tval, &trow ) )
11451 {
11452 MTX_ERROR_MSG( "MTX_MaxAbsColIndex returned FALSE." );
11453 return FALSE;
11454 }
11455
11456 if( tval > *value )
11457 {
11458 *value = tval;
11459 *row = trow;
11460 *col = j;
11461 }
11462 }
11463 return TRUE;
11464 }
11465
11466
11467 BOOL MTX_MaxIndex( const MTX *M, double *re, double *im, unsigned *row, unsigned *col )
11468 {
11469 unsigned j = 0;
11470 unsigned trow = 0;
11471 double tre = 0.0;
11472 double tim = 0.0;
11473 double tmp = 0.0;
11474
11475 if( MTX_isNull( M ) )
11476 {
11477 MTX_ERROR_MSG( "NULL Matrix" );
11478 return FALSE;
11479 }
11480
11481 *col = 0;
11482 if( !MTX_MaxColIndex( M, 0, re, im, row ) )
11483 {
11484 MTX_ERROR_MSG( "MTX_MaxColIndex returned FALSE." );
11485 return FALSE;
11486 }
11487
11488 if( M->isReal )
11489 tmp = *re;
11490 else
11491 tmp = (*re)*(*re) + (*im)*(*im);
11492
11493 for( j = 1; j < M->ncols; j++ )
11494 {
11495 if( !MTX_MaxColIndex( M, j, &tre, &tim, &trow ) )
11496 {
11497 MTX_ERROR_MSG( "MTX_MaxColIndex returned FALSE." );
11498 return FALSE;
11499 }
11500
11501 if( M->isReal )
11502 {
11503 if( tre > tmp )
11504 {
11505 *re = tre;
11506 tmp = *re;
11507 *row = trow;
11508 *col = j;
11509 }
11510 }
11511 else
11512 {
11513 if( (tre*tre+tim*tim) > tmp )
11514 {
11515 *re = tre;
11516 *im = tim;
11517 tmp = (*re)*(*re) + (*im)*(*im);
11518 *row = trow;
11519 *col = j;
11520 }
11521 }
11522 }
11523 return TRUE;
11524 }
11525
11526
11527 BOOL MTX_MaxAbs( const MTX *M, double* value )
11528 {
11529 unsigned row;
11530 unsigned col;
11531 return MTX_MaxAbsIndex( M, value, &row, &col );
11532 }
11533
11534
11535 BOOL MTX_Max( const MTX *M, double *re, double *im )
11536 {
11537 unsigned j = 0;
11538 double tre = 0.0;
11539 double tim = 0.0;
11540 double tmp = 0.0;
11541
11542 if( MTX_isNull( M ) )
11543 {
11544 MTX_ERROR_MSG( "NULL Matrix" );
11545 return FALSE;
11546 }
11547
11548 if( !MTX_MaxColumn( M, 0, re, im ) )
11549 {
11550 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
11551 return FALSE;
11552 }
11553 if( M->isReal )
11554 tmp = *re;
11555 else
11556 tmp = (*re)*(*re) + (*im)*(*im);
11557
11558 for( j = 1; j < M->ncols; j++ )
11559 {
11560 if( !MTX_MaxColumn( M, j, &tre, &tim ) )
11561 {
11562 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
11563 return FALSE;
11564 }
11565
11566 if( M->isReal )
11567 {
11568 if( tre > tmp )
11569 {
11570 *re = tre;
11571 tmp = *re;
11572 }
11573 }
11574 else
11575 {
11576 if( (tre*tre+tim*tim) > tmp )
11577 {
11578 *re = tre;
11579 *im = tim;
11580 tmp = (*re)*(*re) + (*im)*(*im);
11581 }
11582 }
11583 }
11584 return TRUE;
11585 }
11586
11587
11588 BOOL MTX_MinAbsIndex( const MTX *M, double* value, unsigned *row, unsigned *col )
11589 {
11590 unsigned j = 0;
11591 unsigned trow = 0;
11592 double tval = 0.0;
11593
11594 if( MTX_isNull( M ) )
11595 {
11596 MTX_ERROR_MSG( "NULL Matrix" );
11597 return FALSE;
11598 }
11599
11600 *col = 0;
11601 if( !MTX_MinAbsColIndex( M, 0, value, row ) )
11602 {
11603 MTX_ERROR_MSG( "MTX_MinAbsColIndex returned FALSE." );
11604 return FALSE;
11605 }
11606
11607 for( j = 1; j < M->ncols; j++ )
11608 {
11609 if( !MTX_MinAbsColIndex( M, j, &tval, &trow ) )
11610 {
11611 MTX_ERROR_MSG( "MTX_MinAbsColIndex returned FALSE." );
11612 return FALSE;
11613 }
11614
11615 if( tval < *value )
11616 {
11617 *value = tval;
11618 *row = trow;
11619 *col = j;
11620 }
11621 }
11622 return TRUE;
11623 }
11624
11625 BOOL MTX_MinAbs( const MTX *M, double* value )
11626 {
11627 unsigned row;
11628 unsigned col;
11629 return MTX_MinAbsIndex( M, value, &row, &col );
11630 }
11631
11632 BOOL MTX_MinIndex( const MTX *M, double *re, double *im, unsigned *row, unsigned *col )
11633 {
11634 unsigned j = 0;
11635 unsigned trow = 0;
11636 double tre = 0.0;
11637 double tim = 0.0;
11638 double tmp = 0.0;
11639
11640 if( MTX_isNull( M ) )
11641 {
11642 MTX_ERROR_MSG( "NULL Matrix" );
11643 return FALSE;
11644 }
11645
11646 *col = 0;
11647 if( !MTX_MinColIndex( M, 0, re, im, row ) )
11648 {
11649 MTX_ERROR_MSG( "MTX_MinColIndex returned FALSE." );
11650 return FALSE;
11651 }
11652 if( M->isReal )
11653 tmp = *re;
11654 else
11655 tmp = (*re)*(*re) + (*im)*(*im);
11656
11657 for( j = 1; j < M->ncols; j++ )
11658 {
11659 if( !MTX_MinColIndex( M, j, &tre, &tim, &trow ) )
11660 {
11661 MTX_ERROR_MSG( "MTX_MinColIndex returned FALSE." );
11662 return FALSE;
11663 }
11664
11665 if( M->isReal )
11666 {
11667 if( tre < tmp )
11668 {
11669 *re = tre;
11670 tmp = *re;
11671 *row = trow;
11672 *col = j;
11673 }
11674 }
11675 else
11676 {
11677 if( (tre*tre+tim*tim) < tmp )
11678 {
11679 *re = tre;
11680 *im = tim;
11681 tmp = (*re)*(*re) + (*im)*(*im);
11682 *row = trow;
11683 *col = j;
11684 }
11685 }
11686 }
11687 return TRUE;
11688 }
11689
11690 BOOL MTX_Min( const MTX *M, double *re, double *im )
11691 {
11692 unsigned j = 0;
11693 double tre = 0.0;
11694 double tim = 0.0;
11695 double tmp = 0.0;
11696
11697 if( MTX_isNull( M ) )
11698 {
11699 MTX_ERROR_MSG( "NULL Matrix" );
11700 return FALSE;
11701 }
11702
11703 if( !MTX_MinColumn( M, 0, re, im ) )
11704 {
11705 MTX_ERROR_MSG( "MTX_MinColumn returned FALSE." );
11706 return FALSE;
11707 }
11708
11709 if( M->isReal )
11710 tmp = *re;
11711 else
11712 tmp = (*re)*(*re) + (*im)*(*im);
11713
11714 for( j = 1; j < M->ncols; j++ )
11715 {
11716 if( !MTX_MinColumn( M, j, &tre, &tim ) )
11717 {
11718 MTX_ERROR_MSG( "MTX_MinColumn returned FALSE." );
11719 return FALSE;
11720 }
11721
11722 if( M->isReal )
11723 {
11724 if( tre < tmp )
11725 {
11726 *re = tre;
11727 tmp = *re;
11728 }
11729 }
11730 else
11731 {
11732 if( (tre*tre+tim*tim) < tmp )
11733 {
11734 *re = tre;
11735 *im = tim;
11736 tmp = (*re)*(*re) + (*im)*(*im);
11737 }
11738 }
11739 }
11740 return TRUE;
11741 }
11742
11743 BOOL MTX_ColumnRange( const MTX *M, const unsigned col, double *re, double *im )
11744 {
11745 double re_maxval = 0;
11746 double im_maxval = 0;
11747 double re_minval = 0;
11748 double im_minval = 0;
11749
11750 if( MTX_isNull( M ) )
11751 {
11752 MTX_ERROR_MSG( "NULL Matrix" );
11753 return FALSE;
11754 }
11755
11756 if( !MTX_MinColumn( M, col, &re_minval, &im_minval ) )
11757 {
11758 MTX_ERROR_MSG( "MTX_MinColumn returned FALSE." );
11759 return FALSE;
11760 }
11761 if( !MTX_MaxColumn( M, col, &re_maxval, &im_maxval ) )
11762 {
11763 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
11764 return FALSE;
11765 }
11766
11767 *re = re_maxval - re_minval;
11768 *im = im_maxval - im_minval;
11769 return TRUE;
11770 }
11771
11772 BOOL MTX_RowRange( const MTX *M, const unsigned row, double *re, double *im )
11773 {
11774 double re_maxval = 0;
11775 double im_maxval = 0;
11776 double re_minval = 0;
11777 double im_minval = 0;
11778
11779 if( MTX_isNull( M ) )
11780 {
11781 MTX_ERROR_MSG( "NULL Matrix" );
11782 return FALSE;
11783 }
11784
11785
11786 if( !MTX_MinRow( M, row, &re_minval, &im_minval ) )
11787 {
11788 MTX_ERROR_MSG( "MTX_MinRow returned FALSE." );
11789 return FALSE;
11790 }
11791 if( !MTX_MaxRow( M, row, &re_maxval, &im_maxval ) )
11792 {
11793 MTX_ERROR_MSG( "MTX_MaxRow returned FALSE." );
11794 return FALSE;
11795 }
11796
11797 *re = re_maxval - re_minval;
11798 *im = im_maxval - im_minval;
11799 return TRUE;
11800 }
11801
11802
11803 BOOL MTX_Range( const MTX *M, double *re, double *im )
11804 {
11805 double re_maxval = 0;
11806 double im_maxval = 0;
11807 double re_minval = 0;
11808 double im_minval = 0;
11809
11810 if( MTX_isNull( M ) )
11811 {
11812 MTX_ERROR_MSG( "NULL Matrix" );
11813 return FALSE;
11814 }
11815
11816 if( !MTX_Min( M, &re_minval, &im_minval ) )
11817 {
11818 MTX_ERROR_MSG( "MTX_Min returned FALSE." );
11819 return FALSE;
11820 }
11821 if( !MTX_Max( M, &re_maxval, &im_maxval ) )
11822 {
11823 MTX_ERROR_MSG( "MTX_Max returned FALSE." );
11824 return FALSE;
11825 }
11826
11827 *re = re_maxval - re_minval;
11828 *im = im_maxval - im_minval;
11829 return TRUE;
11830 }
11831
11832
11833 BOOL MTX_ColumnSum( const MTX *M, const unsigned col, double *re, double *im )
11834 {
11835 unsigned i = 0;
11836
11837 if( MTX_isNull( M ) )
11838 {
11839 MTX_ERROR_MSG( "NULL Matrix" );
11840 return FALSE;
11841 }
11842
11843 if( col >= M->ncols )
11844 {
11845 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11846 return FALSE;
11847 }
11848
11849 *re = 0;
11850 *im = 0;
11851
11852 if( M->isReal )
11853 {
11854 for( i = 0; i < M->nrows; i++ )
11855 {
11856 *re += M->data[col][i];
11857 }
11858 }
11859 else
11860 {
11861 for( i = 0; i < M->nrows; i++ )
11862 {
11863 *re += M->cplx[col][i].re;
11864 *im += M->cplx[col][i].im;
11865 }
11866 }
11867 return TRUE;
11868 }
11869
11870
11871 BOOL MTX_ColumnSumAbs( const MTX *M, const unsigned col, double *value )
11872 {
11873 unsigned i = 0;
11874 MTX copyCol;
11875
11876 if( MTX_isNull( M ) )
11877 {
11878 MTX_ERROR_MSG( "NULL Matrix" );
11879 return FALSE;
11880 }
11881
11882 if( col >= M->ncols )
11883 {
11884 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11885 return FALSE;
11886 }
11887
11888 MTX_Init(©Col);
11889
11890 if( !MTX_CopyColumn( M, col, ©Col ) )
11891 {
11892 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
11893 MTX_Free( ©Col );
11894 return FALSE;
11895 }
11896
11897 *value = 0;
11898
11899 if( M->isReal )
11900 {
11901 for( i = 0; i < M->nrows; i++ )
11902 {
11903 *value += fabs(M->data[col][i]);
11904 }
11905 }
11906 else
11907 {
11908 for( i = 0; i < M->nrows; i++ )
11909 {
11910 *value += sqrt( M->cplx[col][i].re*M->cplx[col][i].re + M->cplx[col][i].im*M->cplx[col][i].im );
11911 }
11912 }
11913 return TRUE;
11914 }
11915
11916
11917
11918 BOOL MTX_RowSum( const MTX *M, const unsigned row, double *re, double *im )
11919 {
11920 unsigned j = 0;
11921
11922 if( MTX_isNull( M ) )
11923 {
11924 MTX_ERROR_MSG( "NULL Matrix" );
11925 return FALSE;
11926 }
11927
11928 if( row >= M->nrows )
11929 {
11930 MTX_ERROR_MSG( "if( row >= M->nrows )" );
11931 return FALSE;
11932 }
11933
11934 *re = 0;
11935 *im = 0;
11936
11937 if( M->isReal )
11938 {
11939 for( j = 0; j < M->ncols; j++ )
11940 {
11941 *re += M->data[j][row];
11942 }
11943 }
11944 else
11945 {
11946 for( j = 0; j < M->ncols; j++ )
11947 {
11948 *re += M->cplx[j][row].re;
11949 *im += M->cplx[j][row].im;
11950 }
11951 }
11952 return TRUE;
11953 }
11954
11955 BOOL MTX_Sum( const MTX *M, double *re, double *im )
11956 {
11957 unsigned j = 0;
11958 double sumre = 0.0;
11959 double sumim = 0.0;
11960
11961 if( MTX_isNull( M ) )
11962 {
11963 MTX_ERROR_MSG( "NULL Matrix" );
11964 return FALSE;
11965 }
11966
11967 *re = 0;
11968 *im = 0;
11969
11970 for( j = 0; j < M->ncols; j++ )
11971 {
11972 if( !MTX_ColumnSum( M, j, &sumre, &sumim ) )
11973 {
11974 MTX_ERROR_MSG( "MTX_ColumnSum returned FALSE." );
11975 return FALSE;
11976 }
11977
11978 *re += sumre;
11979 *im += sumim;
11980 }
11981 return TRUE;
11982 }
11983
11984
11985 BOOL MTX_ColumnMean( const MTX *M, const unsigned col, double *re, double *im )
11986 {
11987 unsigned i = 0;
11988
11989 if( MTX_isNull( M ) )
11990 {
11991 MTX_ERROR_MSG( "NULL Matrix" );
11992 return FALSE;
11993 }
11994
11995 if( col >= M->ncols )
11996 {
11997 MTX_ERROR_MSG( "if( col >= M->ncols )" );
11998 return FALSE;
11999 }
12000
12001 *re = 0;
12002 *im = 0;
12003
12004 if( M->isReal )
12005 {
12006 for( i = 0; i < M->nrows; i++ )
12007 {
12008 *re += M->data[col][i];
12009 }
12010 *re /= (double)(M->nrows);
12011 }
12012 else
12013 {
12014 for( i = 0; i < M->nrows; i++ )
12015 {
12016 *re += M->cplx[col][i].re;
12017 *im += M->cplx[col][i].im;
12018 }
12019 *re /= (double)(M->nrows);
12020 *im /= (double)(M->nrows);
12021 }
12022 return TRUE;
12023 }
12024
12025 BOOL MTX_RowMean( const MTX *M, const unsigned row, double *re, double *im )
12026 {
12027 unsigned j = 0;
12028
12029 if( MTX_isNull( M ) )
12030 {
12031 MTX_ERROR_MSG( "NULL Matrix" );
12032 return FALSE;
12033 }
12034
12035 if( row >= M->nrows )
12036 {
12037 MTX_ERROR_MSG( "if( row >= M->nrows )" );
12038 return FALSE;
12039 }
12040
12041 *re = 0;
12042 *im = 0;
12043
12044 if( M->isReal )
12045 {
12046 for( j = 0; j < M->ncols; j++ )
12047 {
12048 *re += M->data[j][row];
12049 }
12050 *re /= (double)(M->ncols);
12051 }
12052 else
12053 {
12054 for( j = 0; j < M->ncols; j++ )
12055 {
12056 *re += M->cplx[j][row].re;
12057 *im += M->cplx[j][row].im;
12058 }
12059 *re /= (double)(M->ncols);
12060 *im /= (double)(M->ncols);
12061 }
12062
12063 return TRUE;
12064 }
12065
12066
12067 BOOL MTX_Mean( const MTX *M, double *re, double *im )
12068 {
12069 double sumre = 0.0;
12070 double sumim = 0.0;
12071 double n = (double)(M->nrows*M->ncols);
12072
12073 if( MTX_isNull( M ) )
12074 {
12075 MTX_ERROR_MSG( "NULL Matrix" );
12076 return FALSE;
12077 }
12078
12079 *re = 0;
12080 *im = 0;
12081
12082 if( !MTX_Sum( M, &sumre, &sumim ) )
12083 {
12084 MTX_ERROR_MSG( "MTX_Sum returned FALSE." );
12085 return FALSE;
12086 }
12087
12088 *re = sumre/n;
12089 *im = sumim/n;
12090
12091 return TRUE;
12092 }
12093
12094 BOOL MTX_ColumnStdev( const MTX *M, const unsigned col, double *value )
12095 {
12096 unsigned i = 0;
12097 double n = 0;
12098 double sumx2 = 0;
12099 double sumx_re = 0;
12100 double sumx_im = 0;
12101 double var = 0;
12102
12103 if( MTX_isNull( M ) )
12104 {
12105 MTX_ERROR_MSG( "NULL Matrix" );
12106 return FALSE;
12107 }
12108
12109 if( col >= M->ncols )
12110 {
12111 MTX_ERROR_MSG( "if( col >= M->ncols )" );
12112 return FALSE;
12113 }
12114
12115
12116 if( M->nrows == 1 )
12117 {
12118 *value = 0.0;
12119 return TRUE;
12120 }
12121
12122 if( M->isReal)
12123 {
12124 n = M->nrows;
12125 for( i = 0; i < M->nrows; i++ )
12126 {
12127 sumx_re += M->data[col][i];
12128 sumx2 += M->data[col][i]*M->data[col][i];
12129 }
12130 if( MTX_IsPostiveINF( sumx2 ) )
12131 {
12132 *value = MTX_POS_INF;
12133 }
12134 else
12135 {
12136 var = (n*sumx2 - sumx_re*sumx_re) / (n*(n-1.0));
12137 *value = sqrt(var);
12138 }
12139 }
12140 else
12141 {
12142 n = M->nrows;
12143 for( i = 0; i < M->nrows; i++ )
12144 {
12145 sumx_re += M->cplx[col][i].re;
12146 sumx_im += M->cplx[col][i].im;
12147 sumx2 += M->cplx[col][i].re*M->cplx[col][i].re + M->cplx[col][i].im*M->cplx[col][i].im;
12148 }
12149 if( MTX_IsPostiveINF( sumx2 ) )
12150 {
12151 *value = MTX_POS_INF;
12152 }
12153 else
12154 {
12155 sumx_re = sqrt( sumx_re*sumx_re + sumx_im*sumx_im );
12156 var = (n*sumx2 - sumx_re*sumx_re) / (n*(n-1.0));
12157 *value = sqrt(var);
12158 }
12159 }
12160 return TRUE;
12161 }
12162
12163 BOOL MTX_RowStdev( const MTX *M, const unsigned row, double *value )
12164 {
12165 MTX copyCol;
12166 MTX_Init( ©Col );
12167 if( !MTX_CopyRowIntoAColumnMatrix( M, row, ©Col ) )
12168 {
12169 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
12170 MTX_Free( ©Col );
12171 return FALSE;
12172 }
12173
12174 if( !MTX_ColumnStdev( ©Col, 0, value ) )
12175 {
12176 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
12177 MTX_Free( ©Col );
12178 return FALSE;
12179 }
12180 MTX_Free( ©Col );
12181 return TRUE;
12182 }
12183
12184 BOOL MTX_Stdev( const MTX *M, double *value )
12185 {
12186 unsigned i = 0;
12187 unsigned j = 0;
12188 double n = M->nrows*M->ncols;
12189 double sumx2 = 0;
12190 double sumx_re = 0;
12191 double sumx_im = 0;
12192 double var = 0;
12193
12194 *value = 0.0;
12195
12196 if( MTX_isNull( M ) )
12197 {
12198 MTX_ERROR_MSG( "NULL Matrix" );
12199 return FALSE;
12200 }
12201
12202
12203 if( M->nrows == 1 && M->ncols == 1 )
12204 return TRUE;
12205
12206
12207
12208 if( M->isReal)
12209 {
12210 for( j = 0; j < M->ncols; j++ )
12211 {
12212 for( i = 0; i < M->nrows; i++ )
12213 {
12214 sumx_re += M->data[j][i];
12215 sumx2 += M->data[j][i]*M->data[j][i];
12216 }
12217 }
12218 var = (n*sumx2 - sumx_re*sumx_re) / (n*(n-1.0));
12219 *value = sqrt(var);
12220 }
12221 else
12222 {
12223 for( j = 0; j < M->ncols; j++ )
12224 {
12225 for( i = 0; i < M->nrows; i++ )
12226 {
12227 sumx_re += M->cplx[j][i].re;
12228 sumx_im += M->cplx[j][i].im;
12229 sumx2 += M->cplx[j][i].re*M->cplx[j][i].re + M->cplx[j][i].im*M->cplx[j][i].im;
12230 }
12231 }
12232 sumx_re = sqrt( sumx_re*sumx_re + sumx_im*sumx_im );
12233 var = (n*sumx2 - sumx_re*sumx_re) / (n*(n-1.0));
12234 *value = sqrt(var);
12235 }
12236
12237
12238 return TRUE;
12239 }
12240
12241 BOOL MTX_ColumnVar( const MTX *M, const unsigned col, double *value )
12242 {
12243 if( !MTX_ColumnStdev( M, col, value ) )
12244 {
12245 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
12246 return FALSE;
12247 }
12248
12249 *value *= *value;
12250 return TRUE;
12251 }
12252
12253 BOOL MTX_RowVar( const MTX *M, const unsigned row, double *value )
12254 {
12255 if( !MTX_RowStdev( M, row, value ) )
12256 {
12257 MTX_ERROR_MSG( "MTX_RowStdev returned FALSE." );
12258 return FALSE;
12259 }
12260
12261 *value *= *value;
12262 return TRUE;
12263 }
12264
12265 BOOL MTX_Var( const MTX *M, double *value )
12266 {
12267 if( !MTX_Stdev( M, value ) )
12268 {
12269 MTX_ERROR_MSG( "MTX_Stdev returned FALSE." );
12270 return FALSE;
12271 }
12272
12273 *value *= *value;
12274 return TRUE;
12275 }
12276
12277 BOOL MTX_ColumnNorm( const MTX *M, const unsigned col, double *value )
12278 {
12279 unsigned i = 0;
12280
12281 if( MTX_isNull( M ) )
12282 {
12283 MTX_ERROR_MSG( "NULL Matrix" );
12284 return FALSE;
12285 }
12286
12287 if( col >= M->ncols )
12288 {
12289 MTX_ERROR_MSG( "if( col >= M->ncols )" );
12290 return FALSE;
12291 }
12292
12293 *value = 0;
12294 if( M->isReal )
12295 {
12296 for( i = 0; i < M->nrows; i++ )
12297 {
12298 *value += M->data[col][i] * M->data[col][i];
12299 }
12300 *value = sqrt(*value);
12301 }
12302 else
12303 {
12304 for( i = 0; i < M->nrows; i++ )
12305 {
12306 *value += M->cplx[col][i].re * M->cplx[col][i].re + M->cplx[col][i].im * M->cplx[col][i].im;
12307 }
12308 *value = sqrt(*value);
12309 }
12310 return TRUE;
12311 }
12312
12313 BOOL MTX_RowNorm( const MTX *M, const unsigned row, double *value )
12314 {
12315 MTX copyCol;
12316 MTX_Init( ©Col );
12317 if( !MTX_CopyRowIntoAColumnMatrix( M, row, ©Col ) )
12318 {
12319 MTX_ERROR_MSG( "MTX_CopyRowIntoAColumnMatrix returned FALSE." );
12320 MTX_Free( ©Col );
12321 return FALSE;
12322 }
12323
12324 if( !MTX_ColumnNorm( ©Col, 0, value ) )
12325 {
12326 MTX_ERROR_MSG( "MTX_ColumnNorm returned FALSE." );
12327 MTX_Free( ©Col );
12328 return FALSE;
12329 }
12330 MTX_Free( ©Col );
12331 return TRUE;
12332 }
12333
12334
12335 BOOL MTX_Norm( const MTX *M, double *value )
12336 {
12337 unsigned i = 0;
12338 unsigned j = 0;
12339
12340 *value = 0;
12341
12342 if( MTX_isNull( M ) )
12343 {
12344 MTX_ERROR_MSG( "NULL Matrix" );
12345 return FALSE;
12346 }
12347
12348
12349 *value = 0;
12350 if( M->isReal )
12351 {
12352 for( j = 0; j < M->ncols; j++ )
12353 {
12354 for( i = 0; i < M->nrows; i++ )
12355 {
12356 *value += M->data[j][i] * M->data[j][i];
12357 }
12358 }
12359 *value = sqrt(*value);
12360 }
12361 else
12362 {
12363 for( j = 0; j < M->ncols; j++ )
12364 {
12365 for( i = 0; i < M->nrows; i++ )
12366 {
12367 *value += M->cplx[j][i].re * M->cplx[j][i].re + M->cplx[j][i].im * M->cplx[j][i].im;
12368 }
12369 }
12370 *value = sqrt(*value);
12371 }
12372
12373
12374 return TRUE;
12375 }
12376
12377 BOOL MTX_ColumnRMS( const MTX *M, const unsigned col, double *value )
12378 {
12379 if( !MTX_ColumnNorm( M, col, value ) )
12380 {
12381 MTX_ERROR_MSG( "MTX_ColumnNorm returned FALSE." );
12382 return FALSE;
12383 }
12384
12385
12386 if( M->nrows == 0 )
12387 {
12388 MTX_ERROR_MSG( "if( M->nrows == 0 )" );
12389 return FALSE;
12390 }
12391
12392 *value /= sqrt( (double)(M->nrows) );
12393 return TRUE;
12394 }
12395
12396 BOOL MTX_RowRMS( const MTX *M, const unsigned row, double *value )
12397 {
12398 if( !MTX_RowNorm( M, row, value ) )
12399 {
12400 MTX_ERROR_MSG( "MTX_RowNorm returned FALSE." );
12401 return FALSE;
12402 }
12403
12404
12405 if( M->nrows == 0 )
12406 {
12407 MTX_ERROR_MSG( "if( M->nrows == 0 )" );
12408 return FALSE;
12409 }
12410
12411 *value /= sqrt( M->ncols );
12412 return TRUE;
12413 }
12414
12415 BOOL MTX_RMS( const MTX *M, double *value )
12416 {
12417 const int n = M->nrows*M->ncols;
12418 const double nd = n;
12419
12420 if( !MTX_Norm( M, value ) )
12421 {
12422 MTX_ERROR_MSG( "MTX_Norm returned FALSE." );
12423 return FALSE;
12424 }
12425
12426
12427 if( n == 0 )
12428 {
12429 MTX_ERROR_MSG( "if( n == 0 )" );
12430 return FALSE;
12431 }
12432
12433 *value /= sqrt( nd );
12434 return TRUE;
12435 }
12436
12437 BOOL MTX_ColumnSkewness( const MTX *M, const unsigned col, double *re, double* im )
12438 {
12439 unsigned i = 0;
12440
12441 double dtmp = 0.0;
12442
12443 double sum = 0.0,
12444 meanval_re = 0.0,
12445 meanval_im = 0.0,
12446 stdev = 0.0;
12447
12448 const double n = (double)M->nrows;
12449
12450 if( MTX_isNull( M ) )
12451 {
12452 MTX_ERROR_MSG( "NULL Matrix" );
12453 return FALSE;
12454 }
12455
12456 if( col >= M->ncols )
12457 {
12458 MTX_ERROR_MSG( "if( col >= M->ncols )" );
12459 return FALSE;
12460 }
12461
12462 if( M->nrows < 3 )
12463 {
12464 MTX_ERROR_MSG( "if( M->nrows < 3 )" );
12465 return FALSE;
12466 }
12467
12468 if( !MTX_ColumnMean( M, col, &meanval_re, &meanval_im ) )
12469 {
12470 MTX_ERROR_MSG( "MTX_ColumnMean returned FALSE." );
12471 return FALSE;
12472 }
12473
12474 *re = 0;
12475 *im = 0;
12476
12477 if( M->isReal )
12478 {
12479 if( !MTX_ColumnStdev( M, col, &stdev ) )
12480 {
12481 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
12482 return FALSE;
12483 }
12484
12485 for( i = 0; i < M->nrows; i++ )
12486 {
12487 dtmp = M->data[col][i] - meanval_re;
12488 sum += dtmp*dtmp*dtmp;
12489 }
12490 *re = n*sum / ((n-1.0)*(n-2.0)*stdev*stdev*stdev);
12491 }
12492 else
12493 {
12494
12495 double a;
12496 double b;
12497 double a2;
12498 double b2;
12499 stComplex cplxSum2;
12500 stComplex cplxSum3;
12501 cplxSum2.re = 0;
12502 cplxSum2.im = 0;
12503 cplxSum3.re = 0;
12504 cplxSum3.im = 0;
12505
12506
12507
12508 for( i = 0; i < M->nrows; i++ )
12509 {
12510 a = M->cplx[col][i].re - meanval_re;
12511 b = M->cplx[col][i].im - meanval_im;
12512 a2 = a*a;
12513 b2 = b*b;
12514
12515 cplxSum2.re += a2-b2;
12516 cplxSum2.im += 2*a*b;
12517
12518 cplxSum3.re += a2*a - 3.0*a*b2;
12519 cplxSum3.im += 3.0*a2*b - b2*b;
12520 }
12521
12522
12523 a = cplxSum2.re;
12524 b = cplxSum2.im;
12525 a2 = a*a;
12526 b2 = b*b;
12527 cplxSum2.re = a2*a - 3.0*a*b2;
12528 cplxSum2.im = 3.0*a2*b - b2*b;
12529 a = cplxSum2.re;
12530 b = cplxSum2.im;
12531
12532 dtmp = sqrt( a*a + b*b );
12533 cplxSum2.re = sqrt( (dtmp + a)/2.0 );
12534 if( b < 0 )
12535 cplxSum2.im = -1.0*sqrt( (dtmp - a)/2.0 );
12536 else
12537 cplxSum2.im = sqrt( (dtmp - a)/2.0 );
12538
12539
12540
12541
12542 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
12543
12544 if( dtmp == 0.0 )
12545 {
12546 MTX_ERROR_MSG( "Divide by zero not allowed." );
12547 return FALSE;
12548 }
12549
12550 a = (cplxSum3.re * cplxSum2.re + cplxSum3.im * cplxSum2.im )/dtmp;
12551 b = (cplxSum3.im * cplxSum2.re - cplxSum3.re * cplxSum2.im )/dtmp;
12552
12553 cplxSum3.re = a;
12554 cplxSum3.im = b;
12555
12556 dtmp = sqrt(n);
12557
12558 *re = dtmp*cplxSum3.re;
12559 *im = dtmp*cplxSum3.im;
12560 }
12561 return TRUE;
12562 }
12563
12564 BOOL MTX_RowSkewness( const MTX *M, const unsigned row, double *re, double *im )
12565 {
12566 unsigned i = 0;
12567
12568 double dtmp = 0.0;
12569
12570 double sum = 0.0,
12571 meanval_re = 0.0,
12572 meanval_im = 0.0,
12573 stdev = 0.0;
12574
12575 const double n = (double)M->ncols;
12576
12577 if( MTX_isNull( M ) )
12578 {
12579 MTX_ERROR_MSG( "NULL Matrix" );
12580 return FALSE;
12581 }
12582 if( row >= M->nrows )
12583 {
12584 MTX_ERROR_MSG( "if( row >= M->nrows )" );
12585 return FALSE;
12586 }
12587
12588 if( M->ncols < 3 )
12589 {
12590 MTX_ERROR_MSG( "if( M->ncols < 3 )" );
12591 return FALSE;
12592 }
12593
12594 if( !MTX_RowMean( M, row, &meanval_re, &meanval_im ) )
12595 {
12596 MTX_ERROR_MSG( "MTX_RowMean returned FALSE." );
12597 return FALSE;
12598 }
12599
12600 if( !MTX_RowStdev( M, row, &stdev ) )
12601 {
12602 MTX_ERROR_MSG( "MTX_RowStdev returned FALSE." );
12603 return FALSE;
12604 }
12605
12606 *re = 0;
12607 *im = 0;
12608
12609 if( M->isReal )
12610 {
12611 for( i = 0; i < M->ncols; i++ )
12612 {
12613 dtmp = M->data[i][row] - meanval_re;
12614 sum += dtmp*dtmp*dtmp;
12615 }
12616 *re = n*sum / ((n-1.0)*(n-2.0)*stdev*stdev*stdev);
12617 }
12618 else
12619 {
12620
12621 double a;
12622 double b;
12623 double a2;
12624 double b2;
12625 stComplex cplxSum2;
12626 stComplex cplxSum3;
12627 cplxSum2.re = 0;
12628 cplxSum2.im = 0;
12629 cplxSum3.re = 0;
12630 cplxSum3.im = 0;
12631
12632
12633
12634 for( i = 0; i < M->ncols; i++ )
12635 {
12636 a = M->cplx[i][row].re - meanval_re;
12637 b = M->cplx[i][row].im - meanval_im;
12638 a2 = a*a;
12639 b2 = b*b;
12640
12641 cplxSum2.re += a2-b2;
12642 cplxSum2.im += 2*a*b;
12643
12644 cplxSum3.re += a2*a - 3.0*a*b2;
12645 cplxSum3.im += 3.0*a2*b - b2*b;
12646 }
12647
12648
12649 a = cplxSum2.re;
12650 b = cplxSum2.im;
12651 a2 = a*a;
12652 b2 = b*b;
12653 cplxSum2.re = a2*a - 3.0*a*b2;
12654 cplxSum2.im = 3.0*a2*b - b2*b;
12655 a = cplxSum2.re;
12656 b = cplxSum2.im;
12657
12658 dtmp = sqrt( a*a + b*b );
12659 cplxSum2.re = sqrt( (dtmp + a)/2.0 );
12660 if( b < 0 )
12661 cplxSum2.im = -1.0*sqrt( (dtmp - a)/2.0 );
12662 else
12663 cplxSum2.im = sqrt( (dtmp - a)/2.0 );
12664
12665
12666
12667
12668 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
12669
12670 if( dtmp == 0.0 )
12671 {
12672 MTX_ERROR_MSG( "Divide by zero not allowed." );
12673 return FALSE;
12674 }
12675
12676 a = (cplxSum3.re * cplxSum2.re + cplxSum3.im * cplxSum2.im )/dtmp;
12677 b = (cplxSum3.im * cplxSum2.re - cplxSum3.re * cplxSum2.im )/dtmp;
12678
12679 cplxSum3.re = a;
12680 cplxSum3.im = b;
12681
12682 dtmp = sqrt(n);
12683
12684 *re = dtmp*cplxSum3.re;
12685 *im = dtmp*cplxSum3.im;
12686 }
12687 return TRUE;
12688 }
12689
12690
12691 BOOL MTX_Skewness( const MTX *M, double *re, double* im )
12692 {
12693 unsigned j = 0;
12694 unsigned i = 0;
12695 double dtmp = 0.0;
12696 double sum = 0.0;
12697 double meanval_re = 0.0;
12698 double meanval_im = 0.0;
12699 double stdev = 0.0;
12700
12701 const double n = (double)(M->nrows*M->ncols);
12702
12703 if( MTX_isNull( M ) )
12704 {
12705 MTX_ERROR_MSG( "NULL Matrix" );
12706 return FALSE;
12707 }
12708
12709 if( n < 3 )
12710 {
12711 MTX_ERROR_MSG( "if( n < 3 )" );
12712 return FALSE;
12713 }
12714
12715
12716
12717 if( !MTX_Mean( M, &meanval_re, &meanval_im ) )
12718 {
12719 MTX_ERROR_MSG( "MTX_Mean returned FALSE." );
12720 return FALSE;
12721 }
12722
12723 *re = 0;
12724 *im = 0;
12725
12726 if( M->isReal )
12727 {
12728 if( !MTX_Stdev( M, &stdev ) )
12729 {
12730 MTX_ERROR_MSG( "MTX_Stdev returned FALSE." );
12731 return FALSE;
12732 }
12733
12734 for( j = 0; j < M->ncols; j++ )
12735 {
12736 for( i = 0; i < M->nrows; i++ )
12737 {
12738 dtmp = M->data[j][i] - meanval_re;
12739 sum += dtmp*dtmp*dtmp;
12740 }
12741 }
12742 *re = n*sum / ((n-1.0)*(n-2.0)*stdev*stdev*stdev);
12743 }
12744 else
12745 {
12746
12747 double a;
12748 double b;
12749 double a2;
12750 double b2;
12751 stComplex cplxSum2;
12752 stComplex cplxSum3;
12753 cplxSum2.re = 0;
12754 cplxSum2.im = 0;
12755 cplxSum3.re = 0;
12756 cplxSum3.im = 0;
12757
12758
12759
12760 for( j = 0; j < M->ncols; j++ )
12761 {
12762 for( i = 0; i < M->nrows; i++ )
12763 {
12764 a = M->cplx[j][i].re - meanval_re;
12765 b = M->cplx[j][i].im - meanval_im;
12766 a2 = a*a;
12767 b2 = b*b;
12768
12769 cplxSum2.re += a2-b2;
12770 cplxSum2.im += 2*a*b;
12771
12772 cplxSum3.re += a2*a - 3.0*a*b2;
12773 cplxSum3.im += 3.0*a2*b - b2*b;
12774 }
12775 }
12776
12777
12778 a = cplxSum2.re;
12779 b = cplxSum2.im;
12780 a2 = a*a;
12781 b2 = b*b;
12782 cplxSum2.re = a2*a - 3.0*a*b2;
12783 cplxSum2.im = 3.0*a2*b - b2*b;
12784 a = cplxSum2.re;
12785 b = cplxSum2.im;
12786
12787 dtmp = sqrt( a*a + b*b );
12788 cplxSum2.re = sqrt( (dtmp + a)/2.0 );
12789 if( b < 0 )
12790 cplxSum2.im = -1.0*sqrt( (dtmp - a)/2.0 );
12791 else
12792 cplxSum2.im = sqrt( (dtmp - a)/2.0 );
12793
12794
12795
12796
12797 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
12798
12799 if( dtmp == 0.0 )
12800 {
12801 MTX_ERROR_MSG( "Divide by zero not allowed." );
12802 return FALSE;
12803 }
12804
12805 a = (cplxSum3.re * cplxSum2.re + cplxSum3.im * cplxSum2.im )/dtmp;
12806 b = (cplxSum3.im * cplxSum2.re - cplxSum3.re * cplxSum2.im )/dtmp;
12807
12808 cplxSum3.re = a;
12809 cplxSum3.im = b;
12810
12811 dtmp = sqrt(n);
12812
12813 *re = dtmp*cplxSum3.re;
12814 *im = dtmp*cplxSum3.im;
12815 }
12816
12817
12818 return TRUE;
12819 }
12820
12821 BOOL MTX_ColumnKurtosis( const MTX *M, const unsigned col, double *re, double *im )
12822 {
12823 unsigned i = 0;
12824
12825 double dtmp = 0.0;
12826
12827 double sum = 0.0,
12828 meanval_re = 0.0,
12829 meanval_im = 0.0,
12830 stdev = 0.0;
12831
12832 const double n = (double)M->nrows;
12833
12834 if( MTX_isNull( M ) )
12835 {
12836 MTX_ERROR_MSG( "NULL Matrix" );
12837 return FALSE;
12838 }
12839
12840 if( col >= M->ncols )
12841 {
12842 MTX_ERROR_MSG( "if( col >= M->ncols )" );
12843 return FALSE;
12844 }
12845
12846 if( M->nrows < 4 )
12847 {
12848 MTX_ERROR_MSG( "if( M->nrows < 4 )" );
12849 return FALSE;
12850 }
12851
12852 if( !MTX_ColumnMean( M, col, &meanval_re, &meanval_im ) )
12853 {
12854 MTX_ERROR_MSG( "MTX_ColumnMean returned FALSE." );
12855 return FALSE;
12856 }
12857
12858 if( M->isReal )
12859 {
12860 if( !MTX_ColumnStdev( M, col, &stdev ) )
12861 {
12862 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
12863 return FALSE;
12864 }
12865
12866 for( i = 0; i < M->nrows; i++ )
12867 {
12868 dtmp = M->data[col][i] - meanval_re;
12869 sum += dtmp*dtmp*dtmp*dtmp;
12870 }
12871 dtmp = 1.0 / (stdev*stdev*stdev*stdev);
12872 dtmp *= n*(n+1) / ((n-1.0)*(n-2.0)*(n-3.0));
12873 dtmp *= sum;
12874 dtmp -= 3.0*(n-1.0)*(n-1.0) / ((n-2.0)*(n-3.0));
12875 *re = dtmp;
12876 }
12877 else
12878 {
12879 double a;
12880 double b;
12881 double a2;
12882 double b2;
12883 stComplex cplxSum2;
12884 stComplex cplxSum4;
12885 cplxSum2.re = 0;
12886 cplxSum2.im = 0;
12887 cplxSum4.re = 0;
12888 cplxSum4.im = 0;
12889
12890
12891
12892
12893 for( i = 0; i < M->nrows; i++ )
12894 {
12895 a = M->cplx[col][i].re - meanval_re;
12896 b = M->cplx[col][i].im - meanval_im;
12897 a2 = a*a;
12898 b2 = b*b;
12899
12900 cplxSum2.re += a2-b2;
12901 cplxSum2.im += 2.0*a*b;
12902
12903 cplxSum4.re += a2*a2 - 6.0*a2*b2 + b2*b2;
12904 cplxSum4.im += 4.0*a2*a*b - 4.0*a*b2*b;
12905 }
12906
12907
12908 a = cplxSum2.re * cplxSum2.re - cplxSum2.im * cplxSum2.im;
12909 b = 2.0*cplxSum2.re * cplxSum2.im;
12910 cplxSum2.re = a;
12911 cplxSum2.im = b;
12912
12913
12914
12915 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
12916
12917 if( dtmp == 0.0 )
12918 {
12919 MTX_ERROR_MSG( "Divide by zero not allowed." );
12920 return FALSE;
12921 }
12922
12923 a = (cplxSum4.re * cplxSum2.re + cplxSum4.im * cplxSum2.im )/dtmp;
12924 b = (cplxSum4.im * cplxSum2.re - cplxSum4.re * cplxSum2.im )/dtmp;
12925
12926 cplxSum4.re = a;
12927 cplxSum4.im = b;
12928
12929 *re = n*cplxSum4.re;
12930 *im = n*cplxSum4.im;
12931 }
12932
12933 return TRUE;
12934 }
12935
12936 BOOL MTX_RowKurtosis( const MTX *M, const unsigned row, double *re, double *im )
12937 {
12938 unsigned j = 0;
12939
12940 double dtmp = 0.0;
12941
12942 double sum = 0.0,
12943 meanval_re = 0.0,
12944 meanval_im = 0.0,
12945 stdev = 0.0;
12946
12947 const double n = (double)M->ncols;
12948
12949 if( MTX_isNull( M ) )
12950 {
12951 MTX_ERROR_MSG( "NULL Matrix" );
12952 return FALSE;
12953 }
12954
12955 if( row >= M->nrows )
12956 {
12957 MTX_ERROR_MSG( "if( row >= M->nrows )" );
12958 return FALSE;
12959 }
12960
12961 if( M->ncols < 4 )
12962 {
12963 MTX_ERROR_MSG( "if( M->ncols < 4 )" );
12964 return FALSE;
12965 }
12966
12967 if( !MTX_RowMean( M, row, &meanval_re, &meanval_im ) )
12968 {
12969 MTX_ERROR_MSG( "MTX_RowMean returned FALSE." );
12970 return FALSE;
12971 }
12972
12973 if( M->isReal )
12974 {
12975 if( !MTX_RowStdev( M, row, &stdev ) )
12976 {
12977 MTX_ERROR_MSG( "MTX_RowStdev returned FALSE." );
12978 return FALSE;
12979 }
12980
12981 for( j = 0; j < M->ncols; j++ )
12982 {
12983 dtmp = M->data[j][row] - meanval_re;
12984 sum += dtmp*dtmp*dtmp*dtmp;
12985 }
12986 dtmp = 1.0 / (stdev*stdev*stdev*stdev);
12987 dtmp *= n*(n+1) / ((n-1.0)*(n-2.0)*(n-3.0));
12988 dtmp *= sum;
12989 dtmp -= 3.0*(n-1.0)*(n-1.0) / ((n-2.0)*(n-3.0));
12990 *re = dtmp;
12991 }
12992 else
12993 {
12994 double a;
12995 double b;
12996 double a2;
12997 double b2;
12998 stComplex cplxSum2;
12999 stComplex cplxSum4;
13000 cplxSum2.re = 0;
13001 cplxSum2.im = 0;
13002 cplxSum4.re = 0;
13003 cplxSum4.im = 0;
13004
13005
13006
13007
13008 for( j = 0; j < M->ncols; j++ )
13009 {
13010 a = M->cplx[j][row].re - meanval_re;
13011 b = M->cplx[j][row].im - meanval_im;
13012 a2 = a*a;
13013 b2 = b*b;
13014
13015 cplxSum2.re += a2-b2;
13016 cplxSum2.im += 2.0*a*b;
13017
13018 cplxSum4.re += a2*a2 - 6.0*a2*b2 + b2*b2;
13019 cplxSum4.im += 4.0*a2*a*b - 4.0*a*b2*b;
13020 }
13021
13022
13023 a = cplxSum2.re * cplxSum2.re - cplxSum2.im * cplxSum2.im;
13024 b = 2.0*cplxSum2.re * cplxSum2.im;
13025 cplxSum2.re = a;
13026 cplxSum2.im = b;
13027
13028
13029
13030 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
13031
13032 if( dtmp == 0.0 )
13033 {
13034 MTX_ERROR_MSG( "if( dtmp == 0.0 )" );
13035 return FALSE;
13036 }
13037
13038 a = (cplxSum4.re * cplxSum2.re + cplxSum4.im * cplxSum2.im )/dtmp;
13039 b = (cplxSum4.im * cplxSum2.re - cplxSum4.re * cplxSum2.im )/dtmp;
13040
13041 cplxSum4.re = a;
13042 cplxSum4.im = b;
13043
13044 *re = n*cplxSum4.re;
13045 *im = n*cplxSum4.im;
13046 }
13047
13048 return TRUE;
13049 }
13050
13051 BOOL MTX_Kurtosis( const MTX *M, double *re, double *im )
13052 {
13053 unsigned j = 0;
13054 unsigned i = 0;
13055 double dtmp = 0.0;
13056 double sum = 0.0;
13057 double meanval_re = 0.0;
13058 double meanval_im = 0.0;
13059 double stdev = 0.0;
13060
13061 const double n = (double)(M->nrows*M->ncols);
13062
13063 if( MTX_isNull( M ) )
13064 {
13065 MTX_ERROR_MSG( "NULL Matrix" );
13066 return FALSE;
13067 }
13068
13069 if( n < 4 )
13070 {
13071 MTX_ERROR_MSG( "if( n < 4 )" );
13072 return FALSE;
13073 }
13074
13075
13076 if( !MTX_Mean( M, &meanval_re, &meanval_im ) )
13077 {
13078 MTX_ERROR_MSG( "MTX_Mean returned FALSE." );
13079 return FALSE;
13080 }
13081
13082 if( M->isReal )
13083 {
13084 if( !MTX_Stdev( M, &stdev ) )
13085 {
13086 MTX_ERROR_MSG( "MTX_Stdev returned FALSE." );
13087 return FALSE;
13088 }
13089
13090 for( j = 0; j < M->ncols; j++ )
13091 {
13092 for( i = 0; i < M->nrows; i++ )
13093 {
13094 dtmp = M->data[j][i] - meanval_re;
13095 sum += dtmp*dtmp*dtmp*dtmp;
13096 }
13097 }
13098 dtmp = 1.0 / (stdev*stdev*stdev*stdev);
13099 dtmp *= n*(n+1) / ((n-1.0)*(n-2.0)*(n-3.0));
13100 dtmp *= sum;
13101 dtmp -= 3.0*(n-1.0)*(n-1.0) / ((n-2.0)*(n-3.0));
13102 *re = dtmp;
13103 }
13104 else
13105 {
13106 double a;
13107 double b;
13108 double a2;
13109 double b2;
13110 stComplex cplxSum2;
13111 stComplex cplxSum4;
13112 cplxSum2.re = 0;
13113 cplxSum2.im = 0;
13114 cplxSum4.re = 0;
13115 cplxSum4.im = 0;
13116
13117
13118
13119
13120 for( j = 0; j < M->ncols; j++ )
13121 {
13122 for( i = 0; i < M->nrows; i++ )
13123 {
13124 a = M->cplx[j][i].re - meanval_re;
13125 b = M->cplx[j][i].im - meanval_im;
13126 a2 = a*a;
13127 b2 = b*b;
13128
13129 cplxSum2.re += a2-b2;
13130 cplxSum2.im += 2.0*a*b;
13131
13132 cplxSum4.re += a2*a2 - 6.0*a2*b2 + b2*b2;
13133 cplxSum4.im += 4.0*a2*a*b - 4.0*a*b2*b;
13134 }
13135 }
13136
13137
13138 a = cplxSum2.re * cplxSum2.re - cplxSum2.im * cplxSum2.im;
13139 b = 2.0*cplxSum2.re * cplxSum2.im;
13140 cplxSum2.re = a;
13141 cplxSum2.im = b;
13142
13143
13144
13145 dtmp = cplxSum2.re*cplxSum2.re + cplxSum2.im*cplxSum2.im;
13146
13147 if( dtmp == 0.0 )
13148 {
13149 MTX_ERROR_MSG( "Divide by zero not allowed." );
13150 return FALSE;
13151 }
13152
13153 a = (cplxSum4.re * cplxSum2.re + cplxSum4.im * cplxSum2.im )/dtmp;
13154 b = (cplxSum4.im * cplxSum2.re - cplxSum4.re * cplxSum2.im )/dtmp;
13155
13156 cplxSum4.re = a;
13157 cplxSum4.im = b;
13158
13159 *re = n*cplxSum4.re;
13160 *im = n*cplxSum4.im;
13161 }
13162
13163
13164 return TRUE;
13165 }
13166
13167 BOOL MTX_Trace( const MTX *M, double *re, double *im )
13168 {
13169 unsigned i = 0;
13170
13171 if( !MTX_isSquare(M) )
13172 {
13173 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
13174 return FALSE;
13175 }
13176
13177 *re = 0.0;
13178 *im = 0.0;
13179
13180 if( M->isReal )
13181 {
13182 for( i = 0; i < M->nrows; i++ )
13183 *re += M->data[i][i];
13184 }
13185 else
13186 {
13187 for( i = 0; i < M->nrows; i++ )
13188 {
13189 *re += M->cplx[i][i].re;
13190 *im += M->cplx[i][i].im;
13191 }
13192 }
13193
13194 return TRUE;
13195 }
13196
13197 BOOL MTX_Diagonal( const MTX *M, MTX *D )
13198 {
13199 unsigned i = 0;
13200
13201 if( MTX_isNull( M ) )
13202 {
13203 MTX_ERROR_MSG( "NULL Matrix" );
13204 return FALSE;
13205 }
13206
13207 if( !MTX_Resize( D, M->nrows, 1, M->isReal ) )
13208 {
13209 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
13210 return FALSE;
13211 }
13212
13213 for( i = 0; i < M->nrows; i++ )
13214 {
13215 if( i < M->ncols )
13216 {
13217 if( M->isReal )
13218 {
13219 D->data[0][i] = M->data[i][i];
13220 }
13221 else
13222 {
13223 D->cplx[0][i].re = M->cplx[i][i].re;
13224 D->cplx[0][i].im = M->cplx[i][i].im;
13225 }
13226 }
13227 }
13228 return TRUE;
13229 }
13230
13231 BOOL MTX_FlipColumn( MTX *M, const unsigned col )
13232 {
13233 unsigned i = 0;
13234 double re = 0;
13235 double im = 0;
13236
13237 if( MTX_isNull( M ) )
13238 {
13239 MTX_ERROR_MSG( "NULL Matrix" );
13240 return FALSE;
13241 }
13242
13243 if( col >= M->ncols )
13244 {
13245 MTX_ERROR_MSG( "if( col >= M->ncols )" );
13246 return FALSE;
13247 }
13248
13249 if( M->isReal )
13250 {
13251 for( i = 0; i < (M->nrows/2); i++ )
13252 {
13253 re = M->data[col][i];
13254 M->data[col][i] = M->data[col][M->nrows - i - 1];
13255 M->data[col][M->nrows - i - 1] = re;
13256 }
13257 }
13258 else
13259 {
13260 for( i = 0; i < (M->nrows/2); i++ )
13261 {
13262 re = M->cplx[col][i].re;
13263 im = M->cplx[col][i].im;
13264 M->cplx[col][i].re = M->cplx[col][M->nrows - i - 1].re;
13265 M->cplx[col][i].im = M->cplx[col][M->nrows - i - 1].im;
13266 M->cplx[col][M->nrows - i - 1].re = re;
13267 M->cplx[col][M->nrows - i - 1].im = im;
13268 }
13269 }
13270 return TRUE;
13271 }
13272
13273 BOOL MTX_FlipRow( MTX *M, const unsigned row )
13274 {
13275 unsigned i = 0;
13276 double re = 0;
13277 double im = 0;
13278
13279 if( MTX_isNull( M ) )
13280 {
13281 MTX_ERROR_MSG( "NULL Matrix" );
13282 return FALSE;
13283 }
13284
13285 if( row >= M->nrows )
13286 {
13287 MTX_ERROR_MSG( "if( row >= M->nrows )" );
13288 return FALSE;
13289 }
13290
13291 if( M->isReal )
13292 {
13293 for( i = 0; i < (M->ncols/2); i++ )
13294 {
13295 re = M->data[i][row];
13296 M->data[i][row] = M->data[M->ncols - i - 1][row];
13297 M->data[M->ncols - i - 1][row] = re;
13298 }
13299 }
13300 else
13301 {
13302 for( i = 0; i < (M->ncols/2); i++ )
13303 {
13304 re = M->cplx[i][row].re;
13305 im = M->cplx[i][row].im;
13306 M->cplx[i][row].re = M->cplx[M->ncols - i - 1][row].re;
13307 M->cplx[i][row].im = M->cplx[M->ncols - i - 1][row].im;
13308 M->cplx[M->ncols - i - 1][row].re = re;
13309 M->cplx[M->ncols - i - 1][row].im = im;
13310 }
13311 }
13312 return TRUE;
13313 }
13314
13315 BOOL MTX_SortAscending( MTX *M )
13316 {
13317 unsigned j = 0;
13318
13319 if( MTX_isNull( M ) )
13320 {
13321 MTX_ERROR_MSG( "NULL Matrix" );
13322 return FALSE;
13323 }
13324
13325 if( M->isReal )
13326 {
13327 for( j = 0; j < M->ncols; j++ )
13328 {
13329 MTX_static_quicksort( M->data[j], 0, M->nrows-1 );
13330 }
13331 }
13332 else
13333 {
13334 MTX indexvec;
13335 MTX_Init( &indexvec );
13336
13337 for( j = 0; j < M->ncols; j++ )
13338 {
13339 if( !MTX_SortColumnIndexed( M, j, &indexvec ) )
13340 {
13341 MTX_ERROR_MSG( "MTX_SortColumnIndexed returned FALSE." );
13342 MTX_Free( &indexvec );
13343 return FALSE;
13344 }
13345 }
13346
13347 MTX_Free( &indexvec );
13348 }
13349
13350 return TRUE;
13351 }
13352
13353 BOOL MTX_SortDescending( MTX *M )
13354 {
13355 unsigned j = 0;
13356
13357 if( MTX_isNull( M ) )
13358 {
13359 MTX_ERROR_MSG( "NULL Matrix" );
13360 return FALSE;
13361 }
13362
13363 if( M->isReal )
13364 {
13365 for( j = 0; j < M->ncols; j++ )
13366 {
13367 MTX_static_quicksort( M->data[j], 0, M->nrows-1 );
13368 if( !MTX_FlipColumn( M, j ) )
13369 {
13370 MTX_ERROR_MSG( "MTX_FlipColumn returned FALSE." );
13371 return FALSE;
13372 }
13373 }
13374 }
13375 else
13376 {
13377 if( !MTX_SortAscending( M ) )
13378 {
13379 MTX_ERROR_MSG( "MTX_SortAscending returned FALSE." );
13380 return FALSE;
13381 }
13382
13383 for( j = 0; j < M->ncols; j++ )
13384 {
13385 if( !MTX_FlipColumn( M, j ) )
13386 {
13387 MTX_ERROR_MSG( "MTX_FlipColumn returned FALSE." );
13388 return FALSE;
13389 }
13390 }
13391 }
13392
13393 return TRUE;
13394 }
13395
13396 BOOL MTX_SortColumnAscending( MTX *M, const unsigned col )
13397 {
13398 if( MTX_isNull( M ) )
13399 {
13400 MTX_ERROR_MSG( "NULL Matrix" );
13401 return FALSE;
13402 }
13403
13404 if( col >= M->ncols )
13405 {
13406 MTX_ERROR_MSG( "if( col >= M->ncols )" );
13407 return FALSE;
13408 }
13409
13410 if( M->isReal )
13411 {
13412 MTX_static_quicksort( M->data[col], 0, M->nrows-1 );
13413 }
13414 else
13415 {
13416 MTX indexvec;
13417 MTX_Init( &indexvec );
13418
13419 if( !MTX_SortColumnIndexed( M, col, &indexvec ) )
13420 {
13421 MTX_ERROR_MSG( "MTX_SortColumnIndexed returned FALSE." );
13422 MTX_Free( &indexvec );
13423 return FALSE;
13424 }
13425
13426 MTX_Free( &indexvec );
13427 }
13428
13429 return TRUE;
13430 }
13431
13432 BOOL MTX_SortColumnDescending( MTX *M, const unsigned col )
13433 {
13434 if( MTX_isNull( M ) )
13435 {
13436 MTX_ERROR_MSG( "NULL Matrix" );
13437 return FALSE;
13438 }
13439
13440 if( col >= M->ncols )
13441 {
13442 MTX_ERROR_MSG( "if( col >= M->ncols )" );
13443 return FALSE;
13444 }
13445
13446 if( M->isReal )
13447 {
13448 MTX_static_quicksort( M->data[col], 0, M->nrows-1 );
13449 if( !MTX_FlipColumn( M, col ) )
13450 {
13451 MTX_ERROR_MSG( "MTX_FlipColumn returned FALSE." );
13452 return FALSE;
13453 }
13454 }
13455 else
13456 {
13457 if( !MTX_SortColumnAscending( M, col ) )
13458 {
13459 MTX_ERROR_MSG( "MTX_SortColumnAscending returned FALSE." );
13460 return FALSE;
13461 }
13462
13463 if( !MTX_FlipColumn( M, col ) )
13464 {
13465 MTX_ERROR_MSG( "MTX_FlipColumn returned FALSE." );
13466 return FALSE;
13467 }
13468 }
13469
13470 return TRUE;
13471 }
13472
13473 BOOL MTX_SortColumnIndexed( MTX *M, const unsigned col, MTX *index )
13474 {
13475 unsigned i = 0;
13476 int k;
13477
13478 if( MTX_isNull( M ) )
13479 {
13480 MTX_ERROR_MSG( "NULL Matrix" );
13481 return FALSE;
13482 }
13483
13484 if( col >= M->ncols )
13485 {
13486 MTX_ERROR_MSG( "if( col >= M->ncols )" );
13487 return FALSE;
13488 }
13489
13490 if( index->ncols != 1 || index->nrows != M->nrows || !(index->isReal) )
13491 {
13492 if( !MTX_Resize( index, M->nrows, 1, TRUE ) )
13493 {
13494 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
13495 return FALSE;
13496 }
13497 }
13498
13499 for( i = 0; i < M->nrows; i++ )
13500 index->data[0][i] = i;
13501
13502 if( M->isReal )
13503 {
13504 MTX_static_quicksort_indexed( M->data[col], index->data[0], 0, M->nrows-1 );
13505 }
13506 else
13507 {
13508 double re;
13509 double im;
13510 MTX colM;
13511 MTX mag;
13512
13513 MTX_Init( &colM );
13514 MTX_Init( &mag );
13515
13516
13517 if( !MTX_CopyColumn( M, col, &colM ) )
13518 {
13519 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
13520 MTX_Free( &colM );
13521 return FALSE;
13522 }
13523
13524
13525 if( !MTX_Magnitude( &colM, &mag ) )
13526 {
13527 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
13528 MTX_Free( &colM );
13529 MTX_Free( &mag );
13530 return FALSE;
13531 }
13532
13533
13534 MTX_static_quicksort_indexed( mag.data[0], index->data[0], 0, M->nrows-1 );
13535
13536
13537 if( !MTX_Copy( index, &colM ) )
13538 {
13539 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
13540 MTX_Free( &colM );
13541 MTX_Free( &mag );
13542 return FALSE;
13543 }
13544
13545
13546 for( i = 0; i < M->nrows; i++ )
13547 {
13548 k = (int)(colM.data[0][i]);
13549 if( k >= 0 )
13550 {
13551 colM.data[0][k] = -1.0;
13552 if( i == (unsigned)k )
13553 continue;
13554
13555 re = M->cplx[col][i].re;
13556 im = M->cplx[col][i].im;
13557 M->cplx[col][i].re = M->cplx[col][k].re;
13558 M->cplx[col][i].im = M->cplx[col][k].im;
13559 M->cplx[col][k].re = re;
13560 M->cplx[col][k].im = im;
13561 }
13562 }
13563
13564 MTX_Free( &colM );
13565 MTX_Free( &mag );
13566 }
13567
13568 return TRUE;
13569 }
13570
13571 BOOL MTX_SortByColumn( MTX *M, const unsigned col )
13572 {
13573 unsigned i = 0;
13574 unsigned j = 0;
13575 int k = 0;
13576 MTX indexvec;
13577 MTX vec;
13578
13579 MTX_Init( &indexvec );
13580 MTX_Init( &vec );
13581
13582 if( MTX_isNull( M ) )
13583 {
13584 MTX_ERROR_MSG( "NULL Matrix" );
13585 return FALSE;
13586 }
13587
13588 if( col >= M->ncols )
13589 {
13590 MTX_ERROR_MSG( "if( col >= M->ncols )" );
13591 return FALSE;
13592 }
13593
13594 if( !MTX_SortColumnIndexed( M, col, &indexvec ) )
13595 {
13596 MTX_ERROR_MSG( "MTX_SortColumnIndexed returned FALSE." );
13597 MTX_Free( &indexvec );
13598 return FALSE;
13599 }
13600
13601 for( j = 0; j < M->ncols; j++ )
13602 {
13603 if( j == col )
13604 continue;
13605
13606 if( !MTX_CopyColumn( M, j, &vec ) )
13607 {
13608 MTX_ERROR_MSG("MTX_Copy returned FALSE." );
13609 return FALSE;
13610 }
13611
13612 for( i = 0; i < M->nrows; i++ )
13613 {
13614 k = (int)(indexvec.data[0][i]);
13615 if( k >= 0 )
13616 {
13617 if( i == (unsigned)k )
13618 continue;
13619
13620 if( M->isReal )
13621 {
13622 M->data[j][i] = vec.data[0][k];
13623 }
13624 else
13625 {
13626 M->cplx[j][i].re = vec.cplx[0][k].re;
13627 M->cplx[j][i].im = vec.cplx[0][k].im;
13628 }
13629 }
13630 }
13631 }
13632
13633 MTX_Free( &indexvec );
13634 MTX_Free( &vec );
13635 return TRUE;
13636 }
13637
13638
13639
13640
13641
13642
13643
13644 void MTX_static_quicksort( double *a, unsigned start, unsigned end )
13645 {
13646 int split;
13647 if( start < end )
13648 {
13649 split = MTX_static_partition(a, start, end);
13650 MTX_static_quicksort(a, start, split);
13651 MTX_static_quicksort(a, split + 1, end);
13652 }
13653 }
13654
13655
13656 void MTX_static_swap_doubles( double *a, double *b )
13657 {
13658 double temp = *a;
13659 *a = *b;
13660 *b = temp;
13661 }
13662
13663
13664 int MTX_static_partition( double *a, unsigned start, unsigned end )
13665 {
13666 int right = end + 1;
13667 int left = start - 1;
13668 double pivot = a[start];
13669
13670 while( right > left )
13671 {
13672 do{ left++; } while(a[left] < pivot);
13673 do{ right--; } while(a[right] > pivot);
13674 MTX_static_swap_doubles( &(a[left]), (&a[right]) );
13675 }
13676 MTX_static_swap_doubles( &(a[left]), &(a[right]) );
13677 return right;
13678 }
13679
13680
13681 void MTX_static_quicksort_indexed( double *a, double *index, unsigned start, unsigned end )
13682 {
13683 int split;
13684 if( start < end )
13685 {
13686 split = MTX_static_partition_indexed( a, index, start, end );
13687 MTX_static_quicksort_indexed( a, index, start, split );
13688 MTX_static_quicksort_indexed( a, index, split + 1, end );
13689 }
13690 }
13691
13692
13693
13694 void MTX_static_swap_doubles_indexed( double *a, double *b, double *index_a, double *index_b )
13695 {
13696 double temp = *a;
13697 double temp_ind = *index_a;
13698 *a = *b;
13699 *index_a = *index_b;
13700 *b = temp;
13701 *index_b = temp_ind;
13702 }
13703
13704
13705 int MTX_static_partition_indexed( double *a, double *index, unsigned start, unsigned end )
13706 {
13707 int right = end + 1;
13708 int left = start - 1;
13709 double pivot = a[start];
13710 while( right > left )
13711 {
13712 do{ left++; } while(a[left] < pivot);
13713 do{ right--; } while(a[right] > pivot);
13714 MTX_static_swap_doubles_indexed( &(a[left]), &(a[right]), &(index[left]), &(index[right]) );
13715 }
13716 MTX_static_swap_doubles_indexed( &(a[left]), &(a[right]), &(index[left]), &(index[right]) );
13717 return right;
13718 }
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750 BOOL MTX_SaveCompressed( const MTX *M, const char *path )
13751 {
13752 unsigned i = 0;
13753 unsigned j = 0;
13754 unsigned k = 0;
13755 unsigned ncols = 0;
13756
13757 MTX MtxCol;
13758
13759 #ifdef MTX_DEBUG
13760 time_t t0, t1;
13761 clock_t c0, c1;
13762 unsigned total_length = 0;
13763 #endif
13764
13765 const unsigned nk = MTX_NK;
13766
13767
13768 unsigned char prevByte = 0;
13769 unsigned char currByte = 0;
13770 unsigned n = 0;
13771 unsigned p = 0;
13772
13773 unsigned char* bytes[MTX_NK];
13774 unsigned char* compressed[MTX_NK];
13775 unsigned char curr[MTX_NK];
13776
13777 char msg[512];
13778
13779 FILE* fid = NULL;
13780
13781 unsigned commentLength = 0;
13782 long filemark = 0;
13783
13784 double col_stdev = 0;
13785 size_t count = 0;
13786
13787 _MTX_STRUCT_FileHeader fileHeader;
13788 _MTX_STRUCT_CompressedColumnHeader columnHeader;
13789
13790
13791 MTX_Init( &MtxCol );
13792
13793 memset( &fileHeader, 0, sizeof(fileHeader) );
13794 memset( &columnHeader, 0, sizeof(columnHeader) );
13795
13796
13797
13798 #ifndef _CRT_SECURE_NO_DEPRECATE
13799 if( strcpy_s( fileHeader.id, 8, MTX_ID_COMPRESSED_01 ) != 0 )
13800 {
13801 MTX_ERROR_MSG( "strcpy_s returned an error condition." );
13802 return FALSE;
13803 }
13804 #else
13805 strcpy( fileHeader.id, MTX_ID_COMPRESSED_01 );
13806 #endif
13807
13808 if( M->comment != NULL )
13809 {
13810 fileHeader.comment = M->comment;
13811 commentLength = (unsigned int)strlen( fileHeader.comment );
13812 }
13813 fileHeader.headersize = MTX_ID_SIZE + 6*sizeof(unsigned int) + commentLength;
13814 fileHeader.isReal = M->isReal;
13815 fileHeader.nrows = M->nrows;
13816 fileHeader.ncols = M->ncols;
13817 fileHeader.filesize = 0;
13818 fileHeader.crc = 0;
13819
13820
13821 #ifndef _CRT_SECURE_NO_DEPRECATE
13822 if( fopen_s( &fid, path, "wb" ) != 0 )
13823 {
13824 MTX_ERROR_MSG( "fopen_s returned an error condition." );
13825 return FALSE;
13826 }
13827 #else
13828 fid = fopen( path, "wb" );
13829 #endif
13830 if( fid == NULL )
13831 {
13832 #ifndef _CRT_SECURE_NO_DEPRECATE
13833 if( sprintf_s( msg, 512, "Unable to open %s", path ) > 0 )
13834 MTX_ERROR_MSG( msg );
13835 #else
13836 if( sprintf( msg, "Unable to open %s", path ) > 0 )
13837 MTX_ERROR_MSG( msg );
13838 #endif
13839 return FALSE;
13840 }
13841
13842
13843
13844 for( k = 0; k < nk; k++ )
13845 {
13846 bytes[k] = (unsigned char*)malloc( M->nrows*sizeof(unsigned char) );
13847 if( bytes[k] == NULL )
13848 {
13849 MTX_ERROR_MSG( "malloc returned NULL." );
13850 fclose(fid);
13851 return FALSE;
13852 }
13853 compressed[k] = (unsigned char*)malloc( M->nrows*sizeof(unsigned char)*2 );
13854 if( compressed[k] == NULL )
13855 {
13856 MTX_ERROR_MSG( "malloc returned NULL." );
13857 fclose(fid);
13858 return FALSE;
13859 }
13860 }
13861
13862
13863
13864 count = fwrite( fileHeader.id, sizeof(char), MTX_ID_SIZE, fid );
13865 if( count != MTX_ID_SIZE )
13866 {
13867 MTX_ERROR_MSG( "fwrite returned an error condition." );
13868 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13869 return FALSE;
13870 }
13871
13872 count = fwrite( &fileHeader.headersize, sizeof(unsigned), 1, fid );
13873 if( count != 1 )
13874 {
13875 MTX_ERROR_MSG( "fwrite returned an error condition." );
13876 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13877 return FALSE;
13878 }
13879
13880 count = fwrite( &fileHeader.isReal, sizeof(unsigned), 1, fid );
13881 if( count != 1 )
13882 {
13883 MTX_ERROR_MSG( "fwrite returned an error condition." );
13884 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13885 return FALSE;
13886 }
13887
13888 count = fwrite( &M->nrows, sizeof(unsigned), 1, fid );
13889 if( count != 1 )
13890 {
13891 MTX_ERROR_MSG( "fwrite returned an error condition." );
13892 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13893 return FALSE;
13894 }
13895 count = fwrite( &M->ncols, sizeof(unsigned), 1, fid );
13896 if( count != 1 )
13897 {
13898 MTX_ERROR_MSG( "fwrite returned an error condition." );
13899 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13900 return FALSE;
13901 }
13902
13903
13904
13905
13906
13907 filemark = ftell( fid );
13908 count = fwrite( &fileHeader.filesize, sizeof(unsigned), 1, fid );
13909 if( count != 1 )
13910 {
13911 MTX_ERROR_MSG( "fwrite returned an error condition." );
13912 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13913 return FALSE;
13914 }
13915 count = fwrite( &fileHeader.crc, sizeof(unsigned), 1, fid );
13916 if( count != 1 )
13917 {
13918 MTX_ERROR_MSG( "fwrite returned an error condition." );
13919 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13920 return FALSE;
13921 }
13922
13923 if( commentLength )
13924 {
13925 count = fwrite( fileHeader.comment, sizeof(char), commentLength, fid );
13926 if( count != commentLength )
13927 {
13928 MTX_ERROR_MSG( "fwrite returned an error condition." );
13929 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13930 return FALSE;
13931 }
13932 }
13933
13934
13935 #ifdef MTX_DEBUG
13936 t0 = time(NULL);
13937 c0 = clock();
13938 #endif
13939
13940 if( M->isReal )
13941 ncols = M->ncols;
13942 else
13943 ncols = M->ncols*2;
13944
13945 for( j = 0; j < ncols; j++ )
13946 {
13947
13948 if( !M->isReal )
13949 {
13950 if( j == 0 || j%2 == 0 )
13951 {
13952 if( !MTX_RealColumn( M, j/2, &MtxCol ) )
13953 {
13954 MTX_ERROR_MSG( "MTX_RealColumn returned FALSE." );
13955 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13956 return FALSE;
13957 }
13958 }
13959 else
13960 {
13961 if( !MTX_ImagColumn( M, j/2, &MtxCol ) )
13962 {
13963 MTX_ERROR_MSG( "MTX_ImagColumn returned FALSE." );
13964 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13965 return FALSE;
13966 }
13967 }
13968 }
13969
13970
13971 for( k = 0; k < nk; k++ )
13972 {
13973 columnHeader.length[k] = 0;
13974 columnHeader.isCompressed[k] = 0;
13975 }
13976 columnHeader.totalLength = 0;
13977
13978
13979 col_stdev = 1.0;
13980 if( M->isReal )
13981 {
13982 if( !MTX_ColumnStdev( M, j, &col_stdev ) )
13983 {
13984 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
13985 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13986 return FALSE;
13987 }
13988 }
13989 else
13990 {
13991 if( !MTX_ColumnStdev( &MtxCol, 0, &col_stdev ) )
13992 {
13993 MTX_ERROR_MSG( "MTX_ColumnStdev returned FALSE." );
13994 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
13995 return FALSE;
13996 }
13997 }
13998
13999 if( col_stdev == 0.0 )
14000 {
14001
14002 count = fwrite( &(columnHeader.length[0]), sizeof(unsigned), 1, fid );
14003 if( count != 1 )
14004 {
14005 MTX_ERROR_MSG( "fwrite returned an error condition." );
14006 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14007 return FALSE;
14008 }
14009 MTX_static_updateCRC( (unsigned char*)(columnHeader.length), 4, &(fileHeader.crc) );
14010
14011
14012 if( M->isReal )
14013 {
14014 count = fwrite( &M->data[j][0], sizeof(double), 1, fid );
14015 if( count != 1 )
14016 {
14017 MTX_ERROR_MSG( "fwrite returned an error condition." );
14018 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14019 return FALSE;
14020 }
14021 }
14022 else
14023 {
14024 count = fwrite( &MtxCol.data[0][0], sizeof(double), 1, fid );
14025 if( count != 1 )
14026 {
14027 MTX_ERROR_MSG( "fwrite returned an error condition." );
14028 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14029 return FALSE;
14030 }
14031 }
14032
14033
14034 if( M->isReal )
14035 {
14036 memcpy( curr, &(M->data[j][0]), sizeof(double) );
14037 MTX_static_updateCRC( curr, 8, &(fileHeader.crc) );
14038 }
14039 else
14040 {
14041 memcpy( curr, &(MtxCol.data[0][0]), sizeof(double) );
14042 MTX_static_updateCRC( curr, 8, &(fileHeader.crc) );
14043 }
14044
14045 continue;
14046 }
14047
14048
14049 for( i = 0; i < M->nrows; i++ )
14050 {
14051 if( M->isReal )
14052 memcpy( curr, &(M->data[j][i]), sizeof(double) );
14053 else
14054 memcpy( curr, &(MtxCol.data[0][i]), sizeof(double) );
14055
14056 for( k = 0; k < nk; k++ )
14057 {
14058 bytes[k][i] = curr[k];
14059 }
14060 }
14061
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086
14087
14088
14089
14090
14091
14092
14093
14094 for( k = 0; k < nk; k++ )
14095 {
14096
14097
14098
14099 i = 0;
14100 n = 0;
14101 p = 0;
14102 prevByte = bytes[k][i];
14103 i++;
14104 compressed[k][p] = prevByte;
14105 p++;
14106
14107 while( i < M->nrows )
14108 {
14109 currByte = bytes[k][i];
14110 i++;
14111
14112 if( currByte == prevByte )
14113 {
14114 n++;
14115 if( n == 256 )
14116 {
14117 compressed[k][p] = prevByte;
14118 p++;
14119 compressed[k][p] = (unsigned char)(n-1);
14120 p++;
14121 n = 0;
14122
14123 prevByte = bytes[k][i];
14124 i++;
14125 compressed[k][p] = prevByte;
14126 p++;
14127 if( i == M->nrows )
14128 break;
14129 }
14130 }
14131 else
14132 {
14133 if( n > 0 )
14134 {
14135 compressed[k][p] = prevByte;
14136 p++;
14137 compressed[k][p] = (unsigned char)(n-1);
14138 p++;
14139 n = 0;
14140 }
14141 compressed[k][p] = currByte;
14142 p++;
14143 prevByte = currByte;
14144 }
14145 }
14146 if( n > 0 )
14147 {
14148 compressed[k][p] = prevByte;
14149 p++;
14150 compressed[k][p] = (unsigned char)(n-1);
14151 p++;
14152 n = 0;
14153 }
14154
14155 columnHeader.length[k] = p;
14156 columnHeader.totalLength += columnHeader.length[k];
14157 }
14158
14159
14160
14161
14162
14163
14164
14165
14166
14167
14168
14169
14170
14171
14172 #ifdef MTX_DEBUG
14173 total_length += columnHeader.totalLength;
14174 #endif
14175
14176
14177 for( k = 0; k < nk; k++ )
14178 {
14179 if( columnHeader.length[k] >= M->nrows )
14180 {
14181 columnHeader.length[k] = M->nrows;
14182 columnHeader.isCompressed[k] = 0;
14183 }
14184 else
14185 {
14186 columnHeader.isCompressed[k] = 1;
14187 }
14188 }
14189
14190
14191 for( k = 0; k < nk; k++ )
14192 {
14193 count = fwrite( &(columnHeader.length[k]), sizeof(unsigned), 1, fid );
14194 if( count != 1 )
14195 {
14196 MTX_ERROR_MSG( "fwrite returned an error condition." );
14197 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14198 return FALSE;
14199 }
14200 MTX_static_updateCRC( (unsigned char*)(&(columnHeader.length[k])), 4, &(fileHeader.crc) );
14201 }
14202
14203
14204 for( k = 0; k < nk; k++ )
14205 {
14206 count = fwrite( &(columnHeader.isCompressed[k]), sizeof(unsigned char), 1, fid );
14207 if( count != 1 )
14208 {
14209 MTX_ERROR_MSG( "fwrite returned an error condition." );
14210 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14211 return FALSE;
14212 }
14213 MTX_static_updateCRC( &(columnHeader.isCompressed[k]), 1, &(fileHeader.crc) );
14214 }
14215
14216
14217 for( k = 0; k < nk; k++ )
14218 {
14219 if( columnHeader.isCompressed[k] )
14220 {
14221 count = fwrite( compressed[k], sizeof(unsigned char), columnHeader.length[k], fid );
14222 }
14223 else
14224 {
14225 count = fwrite( bytes[k], sizeof(unsigned char), columnHeader.length[k], fid );
14226 }
14227 if( count != columnHeader.length[k] )
14228 {
14229 MTX_ERROR_MSG( "fwrite returned an error condition." );
14230 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14231 return FALSE;
14232 }
14233 if( columnHeader.isCompressed[k] )
14234 {
14235 MTX_static_updateCRC( compressed[k], columnHeader.length[k], &(fileHeader.crc) );
14236 }
14237 else
14238 {
14239 MTX_static_updateCRC( bytes[k], columnHeader.length[k], &(fileHeader.crc) );
14240 }
14241 }
14242 }
14243
14244
14245 fileHeader.filesize = ftell(fid);
14246 fseek( fid, 0, SEEK_SET );
14247 fileHeader.filesize -= ftell(fid);
14248
14249
14250 fseek( fid, filemark, SEEK_SET );
14251 count = fwrite( &fileHeader.filesize, sizeof(unsigned), 1, fid );
14252 if( count != 1 )
14253 {
14254 MTX_ERROR_MSG( "fwrite returned an error condition." );
14255 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14256 return FALSE;
14257 }
14258 count = fwrite( &fileHeader.crc, sizeof(unsigned), 1, fid );
14259 if( count != 1 )
14260 {
14261 MTX_ERROR_MSG( "fwrite returned an error condition." );
14262 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14263 return FALSE;
14264 }
14265
14266 #ifdef MTX_DEBUG
14267 t1 = time(NULL);
14268 c1 = clock();
14269 printf("\n%s compressed to: %.1lf (%%) of the original size.\n", path, 100.0*total_length/(M->nrows*M->ncols*8) );
14270
14271 printf("Compression (GDM's) RLE: %.2f (s)\n", (float) (c1 - c0)/CLOCKS_PER_SEC);
14272
14273 #endif
14274
14275
14276 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14277
14278 return TRUE;
14279 }
14280
14281
14282 unsigned MTX_static_CRC32(unsigned ulCRC)
14283 {
14284 #define CRC32_POLYNOMIAL 0xEDB88320L
14285 int k;
14286 for( k = 8 ; k > 0; k-- )
14287 {
14288 if( ulCRC & 1 )
14289 ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
14290 else
14291 ulCRC >>= 1;
14292 }
14293 return ulCRC;
14294 }
14295
14296
14297 void MTX_static_updateCRC( unsigned char *pBytes, const unsigned nBytes, unsigned *uiCRC )
14298 {
14299 unsigned tmp1;
14300 unsigned tmp2;
14301 unsigned char *CRCData = pBytes;
14302 unsigned byteCount = nBytes;
14303
14304 while( byteCount-- != 0 )
14305 {
14306 tmp1 = ( (*uiCRC) >> 8 ) & 0x00FFFFFFL;
14307 tmp2 = MTX_static_CRC32( ((unsigned) (*uiCRC) ^ *CRCData++ ) & 0xff );
14308 *uiCRC = tmp1 ^ tmp2;
14309 }
14310 }
14311
14312 void MTX_static_SaveAndLoadCleanUp( FILE *fid, unsigned char **bytes, unsigned char **compressed, const unsigned nk )
14313 {
14314 unsigned k;
14315 if( fid != NULL )
14316 fclose(fid);
14317
14318
14319 for( k = 0; k < nk; k++ )
14320 {
14321 if( bytes[k] != NULL )
14322 free( bytes[k] );
14323 if( compressed[k] != NULL )
14324 free( compressed[k] );
14325 }
14326 }
14327
14328
14329 BOOL MTX_GetCompressedFileAttributes(
14330 const char *path,
14331 unsigned* nrows,
14332 unsigned* ncols,
14333 BOOL* isReal
14334 )
14335 {
14336 FILE* fid = NULL;
14337 char msg[512];
14338
14339 int version = 0;
14340 size_t count = 0;
14341
14342 _MTX_STRUCT_FileHeader fileHeader;
14343
14344 #ifndef _CRT_SECURE_NO_DEPRECATE
14345 if( fopen_s( &fid, path, "rb" ) != 0 )
14346 {
14347 MTX_ERROR_MSG( "fopen_s returned an error condition." );
14348 return FALSE;
14349 }
14350 #else
14351 fid = fopen( path, "rb" );
14352 #endif
14353 if( !fid )
14354 {
14355 #ifndef _CRT_SECURE_NO_DEPRECATE
14356 if( sprintf_s( msg, 512, "Unable to open %s.", path ) > 0 )
14357 MTX_ERROR_MSG( msg );
14358 #else
14359 if( sprintf( msg, "Unable to open %s.", path ) > 0 )
14360 MTX_ERROR_MSG( msg );
14361 #endif
14362 return FALSE;
14363 }
14364
14365
14366 count = fread( fileHeader.id, sizeof(char), MTX_ID_SIZE, fid );
14367 if( count != MTX_ID_SIZE )
14368 {
14369 MTX_ERROR_MSG( "fread returned an error condition." );
14370 fclose(fid);
14371 return FALSE;
14372 }
14373
14374 if( strcmp( fileHeader.id, MTX_ID_COMPRESSED_01 ) == 0 ){ version = MTX_VERSION_NR_COMPRESSED_01; }
14375 else if( strcmp( fileHeader.id, MTX_ID_LEGACY_V01 ) == 0 ){ version = MTX_VERSION_NR_LEGACY_V01; }
14376 else if( strcmp( fileHeader.id, MTX_ID_LEGACY_V02 ) == 0 ){ version = MTX_VERSION_NR_LEGACY_V02; }
14377
14378 if( version == 0 )
14379 {
14380 MTX_ERROR_MSG( "Unsupported compressed Matrix version." );
14381 fclose(fid);
14382 return FALSE;
14383 }
14384
14385 if( version == MTX_VERSION_NR_LEGACY_V01 || version == MTX_VERSION_NR_LEGACY_V01 )
14386 {
14387
14388 MTX_ERROR_MSG( "Unsupported compressed Matrix version." );
14389 fclose(fid);
14390 *nrows = 0;
14391 *ncols = 0;
14392 return FALSE;
14393 }
14394
14395
14396 count = fread( &(fileHeader.headersize), sizeof(unsigned), 1, fid );
14397 if( count != 1 )
14398 {
14399 MTX_ERROR_MSG( "fread returned an error condition." );
14400 fclose(fid);
14401 return FALSE;
14402 }
14403
14404
14405 count = fread( &(fileHeader.isReal), sizeof(unsigned), 1, fid );
14406 if( count != 1 )
14407 {
14408 MTX_ERROR_MSG( "fread returned an error condition." );
14409 fclose(fid);
14410 return FALSE;
14411 }
14412
14413
14414 count = fread( &(fileHeader.nrows), sizeof(unsigned), 1, fid );
14415 if( count != 1 )
14416 {
14417 MTX_ERROR_MSG( "fread returned an error condition." );
14418 fclose(fid);
14419 return FALSE;
14420 }
14421 if( fileHeader.nrows == 0 )
14422 {
14423 MTX_ERROR_MSG( "if( fileHeader.nrows == 0 )" );
14424 fclose(fid);
14425 return FALSE;
14426 }
14427
14428 count = fread( &(fileHeader.ncols), sizeof(unsigned), 1, fid );
14429 if( count != 1 )
14430 {
14431 MTX_ERROR_MSG( "fread returned an error condition." );
14432 fclose(fid);
14433 return FALSE;
14434 }
14435 if( fileHeader.ncols == 0 )
14436 {
14437 MTX_ERROR_MSG( "if( fileHeader.ncols == 0 )" );
14438 fclose(fid);
14439 return FALSE;
14440 }
14441
14442 fclose(fid);
14443 *nrows = fileHeader.nrows;
14444 *ncols = fileHeader.ncols;
14445 *isReal = fileHeader.isReal;
14446 return TRUE;
14447 }
14448
14449
14450 BOOL MTX_ReadCompressed( MTX *M, const char *path )
14451 {
14452 unsigned i = 0;
14453 unsigned j = 0;
14454 unsigned k = 0;
14455 unsigned ncols = 0;
14456
14457 #ifdef MTX_DEBUG
14458 time_t t0, t1;
14459 clock_t c0, c1;
14460 #endif
14461
14462 const unsigned nk = MTX_NK;
14463
14464 unsigned char prevByte = 0;
14465 unsigned char currByte = 0;
14466 unsigned nRepeatBytes = 0;
14467 unsigned n = 0;
14468 unsigned p = 0;
14469
14470 unsigned char* bytes[MTX_NK];
14471 unsigned char* compressed[MTX_NK];
14472 unsigned char curr[MTX_NK];
14473 size_t count = 0;
14474
14475 char msg[512];
14476
14477 FILE* fid = NULL;
14478
14479 unsigned crc = 0;
14480 unsigned filesize = 0;
14481 unsigned commentLength = 0;
14482
14483 int version = 0;
14484
14485 double dtmp;
14486 unsigned doubleWords[2] = {0,0};
14487
14488 _MTX_STRUCT_CompressedColumnHeader columnHeader;
14489
14490 _MTX_STRUCT_FileHeader fileHeader;
14491
14492 MTX MtxRe;
14493 MTX MtxIm;
14494 MTX *MtxCol = NULL;
14495
14496
14497 MTX_Init( &MtxRe );
14498 MTX_Init( &MtxIm );
14499
14500 if( !MTX_DetermineFileSize( path, &filesize ) )
14501 {
14502 MTX_ERROR_MSG( "MTX_DetermineFileSize returned FALSE." );
14503 return FALSE;
14504 }
14505
14506 #ifndef _CRT_SECURE_NO_DEPRECATE
14507 if( fopen_s( &fid, path, "rb" ) != 0 )
14508 {
14509 MTX_ERROR_MSG( "fopen_s returned an error condition." );
14510 return FALSE;
14511 }
14512 #else
14513 fid = fopen( path, "rb" );
14514 #endif
14515 if( !fid )
14516 {
14517 #ifndef _CRT_SECURE_NO_DEPRECATE
14518 if( sprintf_s( msg, 512, "Unable to open %s.", path ) > 0 )
14519 MTX_ERROR_MSG( msg );
14520 #else
14521 if( sprintf( msg, "Unable to open %s.", path ) > 0 )
14522 MTX_ERROR_MSG( msg );
14523 #endif
14524 return FALSE;
14525 }
14526
14527
14528 count = fread( fileHeader.id, sizeof(char), MTX_ID_SIZE, fid );
14529 if( count != MTX_ID_SIZE )
14530 {
14531 MTX_ERROR_MSG( "fread returned an error condition." );
14532 fclose(fid);
14533 return FALSE;
14534 }
14535
14536 if( strcmp( fileHeader.id, MTX_ID_COMPRESSED_01 ) == 0 ){ version = MTX_VERSION_NR_COMPRESSED_01; }
14537 else if( strcmp( fileHeader.id, MTX_ID_LEGACY_V01 ) == 0 ){ version = MTX_VERSION_NR_LEGACY_V01; }
14538 else if( strcmp( fileHeader.id, MTX_ID_LEGACY_V02 ) == 0 ){ version = MTX_VERSION_NR_LEGACY_V02; }
14539
14540 if( version == 0 )
14541 {
14542 MTX_ERROR_MSG( "Unsupported compressed matrix version." );
14543 fclose(fid);
14544 return FALSE;
14545 }
14546
14547 if( version == MTX_VERSION_NR_LEGACY_V01 || version == MTX_VERSION_NR_LEGACY_V01 )
14548 {
14549 fclose(fid);
14550 return MTX_static_ReadCompressed_LegacyVersion( M, path );
14551 }
14552
14553
14554 count = fread( &(fileHeader.headersize), sizeof(unsigned), 1, fid );
14555 if( count != 1 )
14556 {
14557 MTX_ERROR_MSG( "fread returned an error condition." );
14558 fclose(fid);
14559 return FALSE;
14560 }
14561
14562
14563 count = fread( &(fileHeader.isReal), sizeof(unsigned), 1, fid );
14564 if( count != 1 )
14565 {
14566 MTX_ERROR_MSG( "fread returned an error condition." );
14567 fclose(fid);
14568 return FALSE;
14569 }
14570
14571
14572 count = fread( &(fileHeader.nrows), sizeof(unsigned), 1, fid );
14573 if( count != 1 )
14574 {
14575 MTX_ERROR_MSG( "fread returned an error condition." );
14576 fclose(fid);
14577 return FALSE;
14578 }
14579 if( fileHeader.nrows == 0 )
14580 {
14581 MTX_ERROR_MSG( "if( fileHeader.nrows == 0 )" );
14582 fclose(fid);
14583 return FALSE;
14584 }
14585
14586 count = fread( &(fileHeader.ncols), sizeof(unsigned), 1, fid );
14587 if( count != 1 )
14588 {
14589 MTX_ERROR_MSG( "fread returned an error condition." );
14590 fclose(fid);
14591 return FALSE;
14592 }
14593 if( fileHeader.ncols == 0 )
14594 {
14595 MTX_ERROR_MSG( "if( fileHeader.ncols == 0 )" );
14596 fclose(fid);
14597 return FALSE;
14598 }
14599
14600
14601 count = fread( &(fileHeader.filesize), sizeof(unsigned), 1, fid );
14602 if( count != 1 )
14603 {
14604 MTX_ERROR_MSG( "fread returned an error condition." );
14605 fclose(fid);
14606 return FALSE;
14607 }
14608
14609 if( filesize != fileHeader.filesize )
14610 {
14611 MTX_ERROR_MSG( "if( filesize != fileHeader.filesize )" );
14612 fclose(fid);
14613 return FALSE;
14614 }
14615
14616
14617 count = fread( &(fileHeader.crc), sizeof(unsigned), 1, fid );
14618 if( count != 1 )
14619 {
14620 MTX_ERROR_MSG( "fread returned an error condition." );
14621 fclose(fid);
14622 return FALSE;
14623 }
14624
14625
14626 commentLength = fileHeader.headersize - MTX_ID_SIZE - 6*sizeof(unsigned);
14627 if( commentLength != 0 && commentLength < MTX_MAX_COMMENT_LENGTH )
14628 {
14629 fileHeader.comment = (char*)malloc( sizeof(char)*(commentLength+1) );
14630 if( fileHeader.comment == NULL )
14631 {
14632 MTX_ERROR_MSG( "malloc returned NULL." );
14633 fclose(fid);
14634 return FALSE;
14635 }
14636 count = fread( fileHeader.comment, sizeof(unsigned char), commentLength, fid );
14637 if( count != commentLength )
14638 {
14639 MTX_ERROR_MSG( "fread returned an error condition." );
14640 fclose(fid);
14641 return FALSE;
14642 }
14643 M->comment = fileHeader.comment;
14644 }
14645 else
14646 {
14647 if( M->comment )
14648 free( M->comment );
14649 M->comment = NULL;
14650 }
14651
14652
14653 if( !fileHeader.isReal )
14654 {
14655 if( !MTX_Malloc( &MtxRe, fileHeader.nrows, 1, TRUE ) )
14656 {
14657 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
14658 return FALSE;
14659 }
14660 if( !MTX_Malloc( &MtxIm, fileHeader.nrows, 1, TRUE ) )
14661 {
14662 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
14663 MTX_Free( &MtxRe );
14664 MTX_Free( &MtxIm );
14665 return FALSE;
14666 }
14667 }
14668
14669
14670 if( M->nrows != fileHeader.nrows || M->ncols != fileHeader.ncols || (M->isReal != (int)fileHeader.isReal) )
14671 {
14672 if( !MTX_Resize( M, fileHeader.nrows, fileHeader.ncols, fileHeader.isReal ) )
14673 {
14674 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
14675 fclose(fid);
14676 MTX_Free( &MtxRe );
14677 MTX_Free( &MtxIm );
14678 return FALSE;
14679 }
14680 }
14681
14682
14683
14684 for( k = 0; k < nk; k++ )
14685 {
14686 bytes[k] = (unsigned char*)malloc( M->nrows*sizeof(unsigned char)*2 );
14687 if( !bytes[k] )
14688 {
14689 MTX_ERROR_MSG( "malloc returned NULL." );
14690 fclose(fid);
14691 MTX_Free( &MtxRe );
14692 MTX_Free( &MtxIm );
14693 return FALSE;
14694 }
14695 compressed[k] = (unsigned char*)malloc( M->nrows*sizeof(unsigned char)*2 );
14696 if( !compressed[k] )
14697 {
14698 MTX_ERROR_MSG( "malloc returned NULL." );
14699 fclose(fid);
14700 MTX_Free( &MtxRe );
14701 MTX_Free( &MtxIm );
14702 return FALSE;
14703 }
14704 }
14705
14706
14707
14708 #ifdef MTX_DEBUG
14709 t0 = time(NULL);
14710 c0 = clock();
14711 #endif
14712
14713 if( M->isReal )
14714 ncols = M->ncols;
14715 else
14716 ncols = M->ncols*2;
14717
14718 for( j = 0; j < ncols; j++ )
14719 {
14720 if( !M->isReal )
14721 {
14722 if( j == 0 || j%2 == 0 )
14723 {
14724 MtxCol = &MtxRe;
14725 }
14726 else
14727 {
14728 MtxCol = &MtxIm;
14729 }
14730 }
14731
14732
14733
14734 count = fread( &(columnHeader.length[0]), sizeof(unsigned), 1, fid );
14735 if( count != 1 )
14736 {
14737 MTX_ERROR_MSG( "fread returned an error condition." );
14738 MTX_Free( &MtxRe );
14739 MTX_Free( &MtxIm );
14740 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14741 return FALSE;
14742 }
14743 MTX_static_updateCRC( (unsigned char*)&(columnHeader.length[0]), 4, &crc );
14744 if( columnHeader.length[0] == 0 )
14745 {
14746 count = fread( &dtmp, sizeof(double), 1, fid );
14747 if( count != 1 )
14748 {
14749 MTX_ERROR_MSG( "fread returned an error condition." );
14750 MTX_Free( &MtxRe );
14751 MTX_Free( &MtxIm );
14752 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14753 return FALSE;
14754 }
14755 memcpy( curr, &dtmp, sizeof(double) );
14756 MTX_static_updateCRC( curr, 8, &crc );
14757
14758 if( M->isReal )
14759 {
14760 for( i = 0; i < M->nrows; i++ )
14761 M->data[j][i] = dtmp;
14762 }
14763 else
14764 {
14765 for( i = 0; i < M->nrows; i++ )
14766 {
14767 MtxCol->data[0][i] = dtmp;
14768 }
14769 if( j%2 != 0 && j != 0 )
14770 {
14771 if( !MTX_SetComplexColumn( M, j/2, &MtxRe, &MtxIm ) )
14772 {
14773 MTX_ERROR_MSG( "MTX_SetComplexColumn returned FALSE." );
14774 MTX_Free( &MtxRe );
14775 MTX_Free( &MtxIm );
14776 return FALSE;
14777 }
14778 }
14779 }
14780 continue;
14781 }
14782
14783
14784 for( k = 1; k < nk; k++ )
14785 {
14786 count = fread( &(columnHeader.length[k]), sizeof(unsigned), 1, fid );
14787 if( count != 1 )
14788 {
14789 MTX_ERROR_MSG( "fread returned an error condition." );
14790 MTX_Free( &MtxRe );
14791 MTX_Free( &MtxIm );
14792 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14793 return FALSE;
14794 }
14795 MTX_static_updateCRC( (unsigned char*)&(columnHeader.length[k]), 4, &crc );
14796 }
14797
14798
14799 for( k = 0; k < nk; k++ )
14800 {
14801 count = fread( &(columnHeader.isCompressed[k]), sizeof(unsigned char), 1, fid );
14802 if( count != 1 )
14803 {
14804 MTX_ERROR_MSG( "fread returned an error condition." );
14805 MTX_Free( &MtxRe );
14806 MTX_Free( &MtxIm );
14807 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14808 return FALSE;
14809 }
14810 MTX_static_updateCRC( &(columnHeader.isCompressed[k]), 1, &crc );
14811 }
14812
14813
14814 for( k = 0; k < nk; k++ )
14815 {
14816 if( columnHeader.isCompressed[k] )
14817 {
14818 count = fread( compressed[k], sizeof(unsigned char), columnHeader.length[k], fid );
14819 }
14820 else
14821 {
14822 count = fread( bytes[k], sizeof(unsigned char), columnHeader.length[k], fid );
14823 }
14824 if( count != columnHeader.length[k] )
14825 {
14826 MTX_ERROR_MSG( "if( count != columnHeader.length[k] )" );
14827 MTX_Free( &MtxRe );
14828 MTX_Free( &MtxIm );
14829 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14830 return FALSE;
14831 }
14832 if( columnHeader.isCompressed[k] )
14833 {
14834 MTX_static_updateCRC( compressed[k], columnHeader.length[k], &crc );
14835 }
14836 else
14837 {
14838 MTX_static_updateCRC( bytes[k], columnHeader.length[k], &crc );
14839 }
14840 }
14841
14842
14843
14844
14845
14846
14847 for( k = 0; k < nk; k++ )
14848 {
14849 if( columnHeader.isCompressed[k] )
14850 {
14851 n = 0;
14852 p = 0;
14853 prevByte = compressed[k][p]; p++;
14854 bytes[k][n] = prevByte; n++;
14855 while( p < columnHeader.length[k] )
14856 {
14857 currByte = compressed[k][p]; p++;
14858 bytes[k][n] = currByte; n++;
14859
14860 if( currByte == prevByte )
14861 {
14862 nRepeatBytes = compressed[k][p];
14863 p++;
14864
14865 nRepeatBytes = n+nRepeatBytes;
14866 for( n; n < nRepeatBytes; n++ )
14867 {
14868 if( n >= M->nrows )
14869 {
14870 MTX_ERROR_MSG( "if( n >= M->nrows ) - BAD DATA IN COMPRESSED MATRIX FILE." );
14871
14872 MTX_Free( &MtxRe );
14873 MTX_Free( &MtxIm );
14874 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14875 return FALSE;
14876 }
14877 bytes[k][n] = currByte;
14878 }
14879 if( p == columnHeader.length[k] )
14880 break;
14881 if( n >= M->nrows )
14882 {
14883 MTX_ERROR_MSG( "if( n >= M->nrows ) - BAD DATA IN COMPRESSED MATRIX FILE." );
14884
14885 MTX_Free( &MtxRe );
14886 MTX_Free( &MtxIm );
14887 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14888 return FALSE;
14889 }
14890 prevByte = compressed[k][p]; p++;
14891 bytes[k][n] = prevByte; n++;
14892 }
14893 else
14894 {
14895 prevByte = currByte;
14896 }
14897 }
14898
14899
14900 if( n != M->nrows )
14901 {
14902 MTX_ERROR_MSG( "if( n >= M->nrows ) - BAD DATA IN COMPRESSED MATRIX FILE." );
14903 MTX_Free( &MtxRe );
14904 MTX_Free( &MtxIm );
14905 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14906 return FALSE;
14907 }
14908 }
14909 }
14910
14911
14912 for( i = 0; i < M->nrows; i++ )
14913 {
14914 doubleWords[0] = bytes[3][i] << 24;
14915 doubleWords[0] |= bytes[2][i] << 16;
14916 doubleWords[0] |= bytes[1][i] << 8;
14917 doubleWords[0] |= bytes[0][i];
14918
14919 doubleWords[1] = bytes[7][i] << 24;
14920 doubleWords[1] |= bytes[6][i] << 16;
14921 doubleWords[1] |= bytes[5][i] << 8;
14922 doubleWords[1] |= bytes[4][i];
14923
14924 if( M->isReal )
14925 {
14926 memcpy( &(M->data[j][i]), doubleWords, sizeof(double) );
14927 }
14928 else
14929 {
14930 memcpy( &(MtxCol->data[0][i]), doubleWords, sizeof(double) );
14931 }
14932 }
14933
14934 if( !M->isReal )
14935 {
14936 if( j%2 != 0 && j != 0 )
14937 {
14938 if( !MTX_SetComplexColumn( M, j/2, &MtxRe, &MtxIm ) )
14939 {
14940 MTX_ERROR_MSG( "MTX_SetComplexColumn returned FALSE." );
14941 MTX_Free( &MtxRe );
14942 MTX_Free( &MtxIm );
14943 return FALSE;
14944 }
14945 }
14946 }
14947 }
14948
14949
14950 if( fileHeader.crc != crc )
14951 {
14952 MTX_ERROR_MSG( "if( fileHeader.crc != crc )" );
14953 MTX_Free( &MtxRe );
14954 MTX_Free( &MtxIm );
14955 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14956 return FALSE;
14957 }
14958
14959 #ifdef MTX_DEBUG
14960 t1 = time(NULL);
14961 c1 = clock();
14962 printf("File Loaded and decompression RLE in: %.2f (s) (GDM)\n", (float) (c1 - c0)/CLOCKS_PER_SEC);
14963 #endif
14964
14965
14966 MTX_Free( &MtxRe );
14967 MTX_Free( &MtxIm );
14968 MTX_static_SaveAndLoadCleanUp( fid, bytes, compressed, nk );
14969
14970 return TRUE;
14971 }
14972
14973
14974 BOOL MTX_static_ReadCompressed_LegacyVersion( MTX* M, const char *path )
14975 {
14976 unsigned i = 0;
14977 unsigned j = 0;
14978 int version = 0;
14979
14980 FILE* fid = NULL;
14981
14982 unsigned g = 0;
14983 unsigned p = 0;
14984 unsigned k = 0;
14985 unsigned char nrepeat = 0;
14986 unsigned char method = 0;
14987 double d = 0.0;
14988 const unsigned kCompressionByDouble = 1;
14989
14990 unsigned char* columnBuffer = NULL;
14991 unsigned char* compressedBuffer = NULL;
14992 unsigned char ucTmp[2];
14993 unsigned columnBufSize = 0;
14994 unsigned compressedSize = 0;
14995
14996 char msg[512];
14997
14998 size_t count = 0;
14999
15000 _MTX_STRUCT_FileHeader fileHeader;
15001
15002 fileHeader.nrows = 0;
15003 fileHeader.ncols = 0;
15004 fileHeader.filesize = 0;
15005 fileHeader.headersize = 0;
15006 fileHeader.crc = 0;
15007 fileHeader.comment = NULL;
15008
15009 #ifndef _CRT_SECURE_NO_DEPRECATE
15010 if( fopen_s( &fid, path, "rb" ) != 0 )
15011 {
15012 MTX_ERROR_MSG( "fopen_s returned an error condition." );
15013 return FALSE;
15014 }
15015 #else
15016 fid = fopen(path,"rb");
15017 #endif
15018 if( !fid )
15019 {
15020 #ifndef _CRT_SECURE_NO_DEPRECATE
15021 if( sprintf_s( msg, 512, "Unable to open %s.", path ) > 0 )
15022 MTX_ERROR_MSG( msg );
15023 #else
15024 if( sprintf( msg, "Unable to open %s.", path ) > 0 )
15025 MTX_ERROR_MSG( msg );
15026 #endif
15027 return FALSE;
15028 }
15029
15030
15031 count = fread( fileHeader.id, sizeof(char), MTX_ID_SIZE, fid );
15032 if( count != MTX_ID_SIZE )
15033 {
15034 MTX_ERROR_MSG( "fread returned an error condition." );
15035 fclose(fid);
15036 return FALSE;
15037 }
15038
15039 if( strcmp( fileHeader.id, MTX_ID_LEGACY_V01 ) == 0 )
15040 {
15041 version = MTX_VERSION_NR_LEGACY_V01;
15042 }
15043 else if( strcmp( fileHeader.id, MTX_ID_LEGACY_V02 ) == 0 )
15044 {
15045 version = MTX_VERSION_NR_LEGACY_V02;
15046 }
15047 else
15048 {
15049 MTX_ERROR_MSG( "Unsupported compressed matrix version." );
15050 fclose(fid);
15051 return FALSE;
15052 }
15053
15054 count = fread( &(fileHeader.nrows), sizeof(unsigned), 1, fid );
15055 if( count != 1 )
15056 {
15057 MTX_ERROR_MSG( "fread returned an error condition." );
15058 fclose(fid);
15059 return FALSE;
15060 }
15061 count = fread( &(fileHeader.ncols), sizeof(unsigned), 1, fid );
15062 if( count != 1 )
15063 {
15064 MTX_ERROR_MSG( "fread returned an error condition." );
15065 fclose(fid);
15066 return FALSE;
15067 }
15068
15069 if( fileHeader.nrows == 0 || fileHeader.ncols == 0 )
15070 {
15071 MTX_ERROR_MSG( "if( fileHeader.nrows == 0 || fileHeader.ncols == 0 )" );
15072 fclose(fid);
15073 return FALSE;
15074 }
15075
15076
15077 if( version == 2 )
15078 {
15079
15080
15081 for( j = 0; j < fileHeader.ncols; j++ )
15082 {
15083 count = fread( ucTmp, sizeof(unsigned char), 2, fid );
15084 if( count != 2 )
15085 {
15086 MTX_ERROR_MSG( "fread returned an error condition." );
15087 fclose(fid);
15088 return FALSE;
15089 }
15090 }
15091 }
15092
15093
15094 if( M->nrows != fileHeader.nrows || M->ncols != fileHeader.ncols )
15095 {
15096 if( !MTX_Resize( M, fileHeader.nrows, fileHeader.ncols, TRUE ) )
15097 {
15098 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
15099 fclose(fid);
15100 return FALSE;
15101 }
15102 }
15103
15104
15105
15106
15107
15108
15109
15110 columnBufSize = sizeof(double)*(M->nrows);
15111 columnBuffer = (unsigned char*)malloc( columnBufSize );
15112 if( columnBuffer == NULL )
15113 {
15114 MTX_ERROR_MSG( "malloc returned NULL." );
15115 fclose(fid);
15116 return FALSE;
15117 }
15118
15119 for( j = 0; j < M->ncols; j++ )
15120 {
15121
15122 count = fread( &compressedSize, sizeof(unsigned), 1, fid );
15123 if( count != 1 )
15124 {
15125 MTX_ERROR_MSG( "fread returned an error condition." );
15126 if( columnBuffer )
15127 free(columnBuffer);
15128 fclose(fid);
15129 return FALSE;
15130 }
15131
15132 if( compressedSize == columnBufSize )
15133 {
15134
15135 count = fread( M->data[j], sizeof(double), M->nrows, fid );
15136 if( count != M->nrows )
15137 {
15138 MTX_ERROR_MSG( "fread returned an error condition." );
15139 if( columnBuffer )
15140 free(columnBuffer);
15141 fclose(fid);
15142 return FALSE;
15143 }
15144 continue;
15145 }
15146
15147
15148 compressedBuffer = (unsigned char*)malloc( compressedSize );
15149 if( compressedBuffer == NULL )
15150 {
15151 MTX_ERROR_MSG( "malloc returned NULL." );
15152 if( columnBuffer )
15153 free(columnBuffer);
15154 fclose(fid);
15155 return FALSE;
15156 }
15157
15158 memcpy( &(compressedBuffer[0]), &compressedSize, sizeof(unsigned) );
15159
15160
15161 count = fread( &(compressedBuffer[sizeof(unsigned)]), 1, (compressedSize - sizeof(unsigned)), fid );
15162 if( count != (compressedSize - sizeof(unsigned)) )
15163 {
15164 MTX_ERROR_MSG( "fread returned an error condition." );
15165 if( compressedBuffer )
15166 free(compressedBuffer);
15167 if( columnBuffer )
15168 free(columnBuffer);
15169 fclose(fid);
15170 return FALSE;
15171 }
15172
15173
15174 memcpy( &method, &(compressedBuffer[sizeof(unsigned)]), 1 );
15175 if( method != kCompressionByDouble )
15176 {
15177 MTX_ERROR_MSG( "if( method != kCompressionByDouble )" );
15178 if( compressedBuffer )
15179 free(compressedBuffer);
15180 if( columnBuffer )
15181 free(columnBuffer);
15182 fclose(fid);
15183 return FALSE;
15184 }
15185
15186
15187 k = 0;
15188 for( g = sizeof(unsigned)+1; g < compressedSize-sizeof(double); g+=sizeof(double) )
15189 {
15190 nrepeat = compressedBuffer[g];
15191 g++;
15192 memcpy( &d, &(compressedBuffer[g]), sizeof(double) );
15193 for( p = 0; p < nrepeat; p++)
15194 {
15195 memcpy( &(columnBuffer[k]), &d, sizeof(double) );
15196 k+=sizeof(double);
15197 }
15198 }
15199
15200
15201 for( i = 0; i < M->nrows; i++ )
15202 memcpy( &(M->data[j][i]), &(columnBuffer[i*sizeof(double)]), sizeof(double) );
15203
15204
15205 free(compressedBuffer);
15206 compressedBuffer = NULL;
15207 compressedSize = 0;
15208 }
15209
15210
15211 free(columnBuffer);
15212
15213
15214 fclose(fid);
15215
15216 return TRUE;
15217 }
15218
15219 BOOL MTX_LoadAndSave( const char* infilepath, const char* outfilepath )
15220 {
15221 MTX M;
15222 MTX_Init( &M );
15223
15224 if( !MTX_ReadFromFile( &M, infilepath ) )
15225 {
15226 MTX_ERROR_MSG( "MTX_ReadFromFile returned FALSE." );
15227 MTX_Free( &M );
15228 return FALSE;
15229 }
15230
15231 if( !MTX_SaveCompressed( &M, outfilepath ) )
15232 {
15233 MTX_ERROR_MSG( "MTX_SaveCompressed returned FALSE." );
15234 MTX_Free( &M );
15235 return FALSE;
15236 }
15237
15238 MTX_Free( &M );
15239 return TRUE;
15240 }
15241
15242 BOOL MTX_LoadAndSaveQuick( const char* infilepath )
15243 {
15244 unsigned k;
15245 unsigned p;
15246 unsigned length;
15247 char outfilepath[1024];
15248 char *strptr = NULL;
15249
15250 MTX M;
15251 MTX_Init( &M );
15252
15253 if( !MTX_ReadFromFile( &M, infilepath ) )
15254 {
15255 MTX_ERROR_MSG( "MTX_ReadFromFile returned FALSE." );
15256 MTX_Free( &M );
15257 return FALSE;
15258 }
15259
15260 length = (unsigned int)strlen(infilepath);
15261 if( length >= 1024 )
15262 {
15263 MTX_ERROR_MSG( "if( length >= 1024 )" );
15264 MTX_Free( &M );
15265 return FALSE;
15266 }
15267
15268 #ifndef _CRT_SECURE_NO_DEPRECATE
15269 if( strcpy_s( outfilepath, 1024, infilepath ) != 0 )
15270 {
15271 MTX_ERROR_MSG( "strcpy_s returned an error condition." );
15272 MTX_Free( &M );
15273 return FALSE;
15274 }
15275 #else
15276 strcpy( outfilepath, infilepath );
15277 #endif
15278
15279 for( k = 0; k < length; k++ )
15280 {
15281 if( outfilepath[k] == '.' )
15282 {
15283 strptr = &(outfilepath[k]);
15284 p = k;
15285 }
15286 }
15287 #ifndef _CRT_SECURE_NO_DEPRECATE
15288 if( sprintf_s( strptr, length-p+1, ".mtx" ) < 0 )
15289 {
15290 MTX_ERROR_MSG( "sprintf_s returned failure." );
15291 MTX_Free( &M );
15292 return FALSE;
15293 }
15294 #else
15295 if( sprintf( strptr, ".mtx" ) < 0 )
15296 {
15297 MTX_ERROR_MSG( "sprintf returned failure." );
15298 return FALSE;
15299 }
15300 #endif
15301
15302
15303 if( !MTX_SaveCompressed( &M, outfilepath ) )
15304 {
15305 MTX_ERROR_MSG( "MTX_SaveCompressed returned FALSE." );
15306 MTX_Free( &M );
15307 return FALSE;
15308 }
15309
15310 MTX_Free( &M );
15311 return TRUE;
15312 }
15313
15314 BOOL MTX_TimeWindow(
15315 MTX* M,
15316 const unsigned timeColumn,
15317 const double startTime,
15318 const double duration,
15319 const double rolloverTime )
15320 {
15321 unsigned i = 0;
15322 unsigned j = 0;
15323 const double endTime = startTime + duration;
15324 unsigned index = 0;
15325 double time;
15326 double dt;
15327
15328 if( MTX_isNull( M ) )
15329 {
15330 MTX_ERROR_MSG( "NULL Matrix" );
15331 return FALSE;
15332 }
15333
15334 if( timeColumn >= M->ncols )
15335 {
15336 MTX_ERROR_MSG( "if( timeColumn >= M->ncols )" );
15337 return FALSE;
15338 }
15339
15340 i = 0;
15341 if( M->isReal )
15342 time = M->data[timeColumn][i];
15343 else
15344 time = M->cplx[timeColumn][i].re;
15345
15346 i++;
15347 if( time >= startTime && time <= endTime )
15348 {
15349
15350 index++;
15351 }
15352
15353 if( time < endTime )
15354 {
15355 while( i < M->nrows )
15356 {
15357 if( M->isReal )
15358 dt = M->data[timeColumn][i] - time;
15359 else
15360 dt = M->cplx[timeColumn][i].re - time;
15361
15362 if( dt < 0.0 )
15363 {
15364 if( rolloverTime == 0.0 )
15365 break;
15366 dt += rolloverTime;
15367 }
15368
15369 time += dt;
15370
15371 if( time > endTime )
15372 break;
15373
15374 if( time >= startTime && time <= endTime )
15375 {
15376
15377 if( index != i )
15378 {
15379 for( j = 0; j < M->ncols; j++ )
15380 {
15381 if( M->isReal )
15382 {
15383 M->data[j][index] = M->data[j][i];
15384 }
15385 else
15386 {
15387 M->cplx[j][index].re = M->cplx[j][i].re;
15388 M->cplx[j][index].im = M->cplx[j][i].im;
15389 }
15390 }
15391 }
15392 index++;
15393 }
15394 i++;
15395 }
15396 }
15397
15398 if( index == 0 )
15399 {
15400 MTX_Free( M );
15401 }
15402 else
15403 {
15404
15405 if( !MTX_Redim( M, index, M->ncols ) )
15406 {
15407 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
15408 return FALSE;
15409 }
15410 }
15411
15412 return TRUE;
15413 }
15414
15415 BOOL MTX_TimeLimit(
15416 MTX* M,
15417 const unsigned timeColumn,
15418 const double startTime,
15419 const double endTime )
15420 {
15421 double duration = endTime - startTime;
15422
15423 if( duration < 0 )
15424 {
15425 MTX_ERROR_MSG( "if( duration < 0 )" );
15426 return FALSE;
15427 }
15428
15429 return MTX_TimeWindow( M, timeColumn, startTime, duration, 0.0 );
15430 }
15431
15432 BOOL MTX_TimeMatch(
15433 MTX *A,
15434 const unsigned timeColumnA,
15435 MTX *B,
15436 const unsigned timeColumnB,
15437 const unsigned precision,
15438 const double rolloverTime )
15439 {
15440 unsigned index = 0;
15441 unsigned indexA = 0;
15442 unsigned indexB = 0;
15443 unsigned col;
15444
15445 double time1;
15446 double time2;
15447 double time1_prev;
15448 double time2_prev;
15449 double ctime1;
15450 double ctime2;
15451 double dt;
15452
15453 if( MTX_isNull( A ) )
15454 {
15455 MTX_ERROR_MSG( "NULL Matrix" );
15456 return FALSE;
15457 }
15458 if( MTX_isNull( B ) )
15459 {
15460 MTX_ERROR_MSG( "NULL Matrix" );
15461 return FALSE;
15462 }
15463
15464 if( timeColumnA >= A->ncols || timeColumnB >= B->ncols )
15465 {
15466 MTX_ERROR_MSG( "if( timeColumnA >= A->ncols || timeColumnB >= B->ncols )" );
15467 return FALSE;
15468 }
15469
15470 if( A->isReal )
15471 time1 = A->data[timeColumnA][indexA];
15472 else
15473 time1 = A->cplx[timeColumnA][indexA].re;
15474
15475 MTX_static_round_value( &time1, precision );
15476 ctime1 = time1;
15477
15478 if( B->isReal )
15479 time2 = B->data[timeColumnB][indexB];
15480 else
15481 time2 = B->cplx[timeColumnB][indexB].re;
15482
15483 MTX_static_round_value( &time2, precision );
15484 ctime2 = time2;
15485
15486 while( indexA < A->nrows && indexB < B->nrows )
15487 {
15488 if( ctime1 == ctime2 )
15489 {
15490
15491 if( index != indexA )
15492 {
15493 for( col = 0; col < A->ncols; col++ )
15494 {
15495 if( A->isReal )
15496 {
15497 A->data[col][index] = A->data[col][indexA];
15498 }
15499 else
15500 {
15501 A->cplx[col][index].re = A->cplx[col][indexA].re;
15502 A->cplx[col][index].im = A->cplx[col][indexA].im;
15503 }
15504 }
15505 }
15506
15507
15508 if( index != indexB )
15509 {
15510 for( col = 0; col < B->ncols; col++ )
15511 {
15512 if( B->isReal )
15513 {
15514 B->data[col][index] = B->data[col][indexB];
15515 }
15516 else
15517 {
15518 B->cplx[col][index].re = B->cplx[col][indexB].re;
15519 B->cplx[col][index].im = B->cplx[col][indexB].im;
15520 }
15521 }
15522 }
15523 index++;
15524 indexA++;
15525 indexB++;
15526
15527 time1_prev = time1;
15528 if( A->isReal )
15529 time1 = A->data[timeColumnA][indexA];
15530 else
15531 time1 = A->cplx[timeColumnA][indexA].re;
15532
15533 MTX_static_round_value( &time1, precision );
15534 dt = time1 - time1_prev;
15535 if( dt < 0.0 )
15536 {
15537 if( rolloverTime == 0.0 )
15538 break;
15539 dt += rolloverTime;
15540 }
15541 ctime1 += dt;
15542
15543 time2_prev = time2;
15544 if( B->isReal )
15545 time2 = B->data[timeColumnB][indexB];
15546 else
15547 time2 = B->cplx[timeColumnB][indexB].re;
15548
15549 MTX_static_round_value( &time2, precision );
15550 dt = time2 - time2_prev;
15551 if( dt < 0.0 )
15552 {
15553 if( rolloverTime == 0.0 )
15554 break;
15555 dt += rolloverTime;
15556 }
15557 ctime2 += dt;
15558 }
15559 else if( ctime1 < ctime2 )
15560 {
15561 indexA++;
15562
15563 time1_prev = time1;
15564 if( A->isReal )
15565 time1 = A->data[timeColumnA][indexA];
15566 else
15567 time1 = A->cplx[timeColumnA][indexA].re;
15568
15569 MTX_static_round_value( &time1, precision );
15570 dt = time1 - time1_prev;
15571 if( dt < 0.0 )
15572 {
15573 if( rolloverTime == 0.0 )
15574 break;
15575 dt += rolloverTime;
15576 }
15577 ctime1 += dt;
15578 }
15579 else
15580 {
15581 indexB++;
15582
15583 time2_prev = time2;
15584 if( B->isReal )
15585 time2 = B->data[timeColumnB][indexB];
15586 else
15587 time2 = B->cplx[timeColumnB][indexB].re;
15588
15589 MTX_static_round_value( &time2, precision );
15590 dt = time2 - time2_prev;
15591 if( dt < 0.0 )
15592 {
15593 if( rolloverTime == 0.0 )
15594 break;
15595 dt += rolloverTime;
15596 }
15597 ctime2 += dt;
15598 }
15599 }
15600
15601
15602 if( index == 0 )
15603 {
15604 MTX_Free( A );
15605 MTX_Free( B );
15606 return TRUE;
15607 }
15608
15609
15610 if( !MTX_Redim( A, index, A->ncols ) )
15611 {
15612 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
15613 return FALSE;
15614 }
15615 if( !MTX_Redim( B, index, B->ncols ) )
15616 {
15617 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
15618 return FALSE;
15619 }
15620
15621 return TRUE;
15622 }
15623
15624 BOOL MTX_Interpolate(
15625 MTX *A,
15626 const unsigned timeColumnA,
15627 MTX *B,
15628 const unsigned timeColumnB,
15629 const double maxInterpolationInterval,
15630 const double rolloverTime )
15631 {
15632 unsigned j = 0;
15633
15634 unsigned index = 0,
15635 indexA = 0,
15636 indexB = 0;
15637
15638 double time = 0.0,
15639 prev = 0.0,
15640 next = 0.0,
15641 interval = 0.0,
15642 slope = 0.0,
15643 slope_im = 0.0;
15644
15645 indexA = 0;
15646 indexB = 1;
15647 while( indexA < A->nrows && indexB < B->nrows )
15648 {
15649 if( A->isReal )
15650 time = A->data[timeColumnA][indexA];
15651 else
15652 time = A->cplx[timeColumnA][indexA].re;
15653
15654 if( B->isReal )
15655 prev = B->data[timeColumnB][indexB-1];
15656 else
15657 prev = B->cplx[timeColumnB][indexB-1].re;
15658
15659 if( B->isReal )
15660 next = B->data[timeColumnB][indexB];
15661 else
15662 next = B->cplx[timeColumnB][indexB].re;
15663
15664 interval = next - prev;
15665 if( interval < 0 )
15666 {
15667 if( rolloverTime == 0.0 )
15668 break;
15669 interval += rolloverTime;
15670 next += rolloverTime;
15671 }
15672
15673 if( time >= prev &&
15674 time <= next )
15675 {
15676 if( interval > maxInterpolationInterval )
15677 {
15678 indexB++;
15679 continue;
15680 }
15681
15682 if( index != indexA )
15683 {
15684 if( A->isReal )
15685 {
15686 A->data[timeColumnA][index] = time;
15687 }
15688 else
15689 {
15690 A->cplx[timeColumnA][index].re = time;
15691 }
15692
15693
15694 for( j = 0; j < A->ncols; j++ )
15695 {
15696 if( A->isReal )
15697 {
15698 A->data[j][index] = A->data[j][indexA];
15699 }
15700 else
15701 {
15702 A->cplx[j][index].re = A->cplx[j][indexA].re;
15703 A->cplx[j][index].im = A->cplx[j][indexA].im;
15704 }
15705 }
15706 }
15707
15708
15709 for( j = 0; j < B->ncols; j++ )
15710 {
15711 if( j == timeColumnB )
15712 {
15713 if( B->isReal )
15714 B->data[timeColumnB][index] = time;
15715 else
15716 B->cplx[timeColumnB][index].re = time;
15717
15718 continue;
15719 }
15720 if( B->isReal )
15721 {
15722 slope = (B->data[j][indexB] - B->data[j][indexB-1]) / interval;
15723 B->data[j][index] = slope * (time-prev) + B->data[j][indexB-1];
15724 }
15725 else
15726 {
15727 slope = (B->cplx[j][indexB].re - B->cplx[j][indexB-1].re) / interval;
15728 slope_im = (B->cplx[j][indexB].im - B->cplx[j][indexB-1].im) / interval;
15729
15730 B->cplx[j][index].re = slope * (time-prev) + B->cplx[j][indexB-1].re;
15731 B->cplx[j][index].im = slope_im * (time-prev) + B->cplx[j][indexB-1].im;
15732 }
15733 }
15734 index++;
15735 indexA++;
15736 indexB++;
15737 continue;
15738 }
15739
15740 if( time < prev )
15741 indexA++;
15742 else if( time > next )
15743 indexB++;
15744 }
15745 if( !MTX_Redim( A, index, A->ncols ) )
15746 {
15747 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
15748 return FALSE;
15749 }
15750 if( !MTX_Redim( B, index, B->ncols ) )
15751 {
15752 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
15753 return FALSE;
15754 }
15755
15756 return TRUE;
15757 }
15758
15759
15760 BOOL MTX_InvertInPlaceClosedForm( MTX *M )
15761 {
15762 unsigned n;
15763 double dtmp;
15764
15765 if( MTX_isNull( M ) )
15766 {
15767 MTX_ERROR_MSG( "NULL Matrix" );
15768 return FALSE;
15769 }
15770 if( !MTX_isSquare( M ) )
15771 {
15772 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
15773 return FALSE;
15774 }
15775 n = M->nrows;
15776 if( n > 3 )
15777 {
15778 MTX_ERROR_MSG( "if( M->nrows > 3 )" );
15779 return FALSE;
15780 }
15781
15782 if( M->isReal )
15783 {
15784
15785
15786
15787 if( n == 1 )
15788 {
15789
15790 M->data[0][0] = 1.0/M->data[0][0];
15791 return TRUE;
15792 }
15793
15794 if( n == 2 )
15795 {
15796
15797
15798 double invdet;
15799 invdet = M->data[0][0] * M->data[1][1] - M->data[1][0] * M->data[0][1];
15800
15801
15802 invdet = 1.0/invdet;
15803
15804 dtmp = M->data[0][0];
15805 M->data[0][0] = invdet * M->data[1][1];
15806 M->data[1][1] = invdet * dtmp;
15807 M->data[1][0] *= -invdet;
15808 M->data[0][1] *= -invdet;
15809
15810 return TRUE;
15811 }
15812
15813 if( n == 3 )
15814 {
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831 double invdet;
15832 double r,s,t,u,v,w,x,y,z;
15833 double vzyw;
15834 double xwuz;
15835 double uyxv;
15836
15837 r = M->data[0][0]; s = M->data[1][0]; t = M->data[2][0];
15838 u = M->data[0][1]; v = M->data[1][1]; w = M->data[2][1];
15839 x = M->data[0][2]; y = M->data[1][2]; z = M->data[2][2];
15840
15841
15842 vzyw = v*z - y*w;
15843 xwuz = x*w - u*z;
15844 uyxv = u*y - x*v;
15845
15846 invdet = r*vzyw + s*xwuz + t*uyxv;
15847
15848
15849 invdet = 1.0/invdet;
15850
15851 M->data[0][0] = invdet*vzyw; M->data[1][0] = invdet*(t*y-z*s); M->data[2][0] = invdet*(s*w-v*t);
15852 M->data[0][1] = invdet*xwuz; M->data[1][1] = invdet*(r*z-x*t); M->data[2][1] = invdet*(u*t-r*w);
15853 M->data[0][2] = invdet*uyxv; M->data[1][2] = invdet*(x*s-r*y); M->data[2][2] = invdet*(r*v-u*s);
15854
15855 return TRUE;
15856 }
15857 }
15858 else
15859 {
15860
15861
15862
15863 if( n == 1 )
15864 {
15865
15866 dtmp = M->cplx[0][0].re*M->cplx[0][0].re + M->cplx[0][0].im*M->cplx[0][0].im;
15867 M->cplx[0][0].re = M->cplx[0][0].re / dtmp;
15868 M->cplx[0][0].im = -M->cplx[0][0].im / dtmp;
15869 return TRUE;
15870 }
15871
15872 if( n == 2 )
15873 {
15874
15875
15876
15877 stComplex invdet;
15878 stComplex tmpcplx;
15879
15880
15881 if( !MTX_Det( M, &tmpcplx.re, &tmpcplx.im ) )
15882 {
15883 MTX_ERROR_MSG( "MTX_Det returned FALSE." );
15884 return FALSE;
15885 }
15886
15887 dtmp = tmpcplx.re*tmpcplx.re + tmpcplx.im*tmpcplx.im;
15888 invdet.re = tmpcplx.re / dtmp;
15889 invdet.im = -tmpcplx.im / dtmp;
15890
15891
15892 tmpcplx.re = M->cplx[0][0].re;
15893 tmpcplx.im = M->cplx[0][0].im;
15894 M->cplx[0][0].re = M->cplx[1][1].re;
15895 M->cplx[0][0].im = M->cplx[1][1].im;
15896 M->cplx[1][1].re = tmpcplx.re;
15897 M->cplx[1][1].re = tmpcplx.im;
15898 M->cplx[1][0].re *= -1.0;
15899 M->cplx[1][0].im *= -1.0;
15900 M->cplx[0][1].re *= -1.0;
15901 M->cplx[0][1].im *= -1.0;
15902
15903
15904 if( !MTX_Multiply_ScalarComplex( M, invdet.re, invdet.im ) )
15905 {
15906 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
15907 return FALSE;
15908 }
15909
15910 return TRUE;
15911 }
15912
15913 if( n == 3 )
15914 {
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927
15928
15929
15930
15931 stComplex invdet;
15932 stComplex r,s,t,u,v,w,x,y,z;
15933 stComplex vzyw;
15934 stComplex xwuz;
15935 stComplex uyxv;
15936 stComplex cplxA;
15937 stComplex cplxB;
15938
15939 r.re = M->cplx[0][0].re; s.re = M->cplx[1][0].re; t.re = M->cplx[2][0].re;
15940 u.re = M->cplx[0][1].re; v.re = M->cplx[1][1].re; w.re = M->cplx[2][1].re;
15941 x.re = M->cplx[0][2].re; y.re = M->cplx[1][2].re; z.re = M->cplx[2][2].re;
15942
15943 r.im = M->cplx[0][0].im; s.im = M->cplx[1][0].im; t.im = M->cplx[2][0].im;
15944 u.im = M->cplx[0][1].im; v.im = M->cplx[1][1].im; w.im = M->cplx[2][1].im;
15945 x.im = M->cplx[0][2].im; y.im = M->cplx[1][2].im; z.im = M->cplx[2][2].im;
15946
15947
15948
15949
15950 MTX_static_quick_complex_mult_ab( &v.re, &v.im, &z.re, &z.im, &cplxA.re, &cplxA.im );
15951 MTX_static_quick_complex_mult_ab( &y.re, &y.im, &w.re, &w.im, &cplxB.re, &cplxB.im );
15952 vzyw.re = cplxA.re - cplxB.re;
15953 vzyw.im = cplxA.im - cplxB.im;
15954
15955
15956 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &w.re, &w.im, &cplxA.re, &cplxA.im );
15957 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &z.re, &z.im, &cplxB.re, &cplxB.im );
15958 xwuz.re = cplxA.re - cplxB.re;
15959 xwuz.im = cplxA.im - cplxB.im;
15960
15961
15962 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &y.re, &y.im, &cplxA.re, &cplxA.im );
15963 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &v.re, &v.im, &cplxB.re, &cplxB.im );
15964 uyxv.re = cplxA.re - cplxB.re;
15965 uyxv.im = cplxA.im - cplxB.im;
15966
15967 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &vzyw.re, &vzyw.im, &cplxA.re, &cplxA.im );
15968 MTX_static_quick_complex_mult_ab( &s.re, &s.im, &xwuz.re, &xwuz.im, &cplxB.re, &cplxB.im );
15969 MTX_static_quick_complex_mult_ab( &t.re, &t.im, &uyxv.re, &uyxv.im, &invdet.re, &invdet.im );
15970
15971
15972 invdet.re += cplxA.re + cplxB.re;
15973 invdet.im += cplxA.im + cplxB.im;
15974
15975
15976 dtmp = invdet.re*invdet.re + invdet.im*invdet.im;
15977 invdet.re = invdet.re/dtmp;
15978 invdet.im = -invdet.im/dtmp;
15979
15980 M->cplx[0][0].re = vzyw.re;
15981 M->cplx[0][1].re = xwuz.re;
15982 M->cplx[0][2].re = uyxv.re;
15983
15984 M->cplx[0][0].im = vzyw.im;
15985 M->cplx[0][1].im = xwuz.im;
15986 M->cplx[0][2].im = uyxv.im;
15987
15988
15989 MTX_static_quick_complex_mult_ab( &t.re, &t.im, &y.re, &y.im, &cplxA.re, &cplxA.im );
15990 MTX_static_quick_complex_mult_ab( &z.re, &z.im, &s.re, &s.im, &cplxB.re, &cplxB.im );
15991 M->cplx[1][0].re = cplxA.re - cplxB.re;
15992 M->cplx[1][0].im = cplxA.im - cplxB.im;
15993
15994
15995 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &z.re, &z.im, &cplxA.re, &cplxA.im );
15996 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &t.re, &t.im, &cplxB.re, &cplxB.im );
15997 M->cplx[1][1].re = cplxA.re - cplxB.re;
15998 M->cplx[1][1].im = cplxA.im - cplxB.im;
15999
16000
16001 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &s.re, &s.im, &cplxA.re, &cplxA.im );
16002 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &y.re, &y.im, &cplxB.re, &cplxB.im );
16003 M->cplx[1][2].re = cplxA.re - cplxB.re;
16004 M->cplx[1][2].im = cplxA.im - cplxB.im;
16005
16006
16007 MTX_static_quick_complex_mult_ab( &s.re, &s.im, &w.re, &w.im, &cplxA.re, &cplxA.im );
16008 MTX_static_quick_complex_mult_ab( &v.re, &v.im, &t.re, &t.im, &cplxB.re, &cplxB.im );
16009 M->cplx[2][0].re = cplxA.re - cplxB.re;
16010 M->cplx[2][0].im = cplxA.im - cplxB.im;
16011
16012
16013 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &t.re, &t.im, &cplxA.re, &cplxA.im );
16014 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &w.re, &w.im, &cplxB.re, &cplxB.im );
16015 M->cplx[2][1].re = cplxA.re - cplxB.re;
16016 M->cplx[2][1].im = cplxA.im - cplxB.im;
16017
16018
16019 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &v.re, &v.im, &cplxA.re, &cplxA.im );
16020 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &s.re, &s.im, &cplxB.re, &cplxB.im );
16021 M->cplx[2][2].re = cplxA.re - cplxB.re;
16022 M->cplx[2][2].im = cplxA.im - cplxB.im;
16023
16024 if( !MTX_Multiply_ScalarComplex( M, invdet.re, invdet.im ) )
16025 {
16026 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
16027 return FALSE;
16028 }
16029
16030 return TRUE;
16031 }
16032 }
16033
16034 MTX_ERROR_MSG( "Unexpected." );
16035 return FALSE;
16036 }
16037
16038
16039 BOOL MTX_InvertClosedForm( const MTX *src, MTX *dst )
16040 {
16041 unsigned n;
16042 double dtmp;
16043
16044 if( dst == NULL )
16045 {
16046 MTX_ERROR_MSG( "NULL input matrix." );
16047 return FALSE;
16048 }
16049 if( MTX_isNull( src ) )
16050 {
16051 MTX_ERROR_MSG( "NULL Matrix" );
16052 return FALSE;
16053 }
16054 n = src->nrows;
16055 if( !MTX_isSquare( src ) )
16056 {
16057 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
16058 return FALSE;
16059 }
16060 if( src->nrows > 3 )
16061 {
16062 MTX_ERROR_MSG( "if( src->nrows > 3 )" );
16063 return FALSE;
16064 }
16065 if( !MTX_Malloc( dst, src->nrows, src->ncols, src->isReal ) )
16066 {
16067 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
16068 return FALSE;
16069 }
16070
16071 if( src->isReal )
16072 {
16073
16074
16075
16076 if( n == 1 )
16077 {
16078
16079 dst->data[0][0] = 1.0/src->data[0][0];
16080 return TRUE;
16081 }
16082
16083 if( n == 2 )
16084 {
16085
16086
16087
16088 double invdet;
16089 invdet = src->data[0][0] * src->data[1][1] - src->data[1][0] * src->data[0][1];
16090
16091
16092 invdet = 1.0/invdet;
16093
16094 dst->data[0][0] = invdet * src->data[1][1];
16095 dst->data[1][1] = invdet * src->data[0][0];
16096 dst->data[1][0] = -invdet * src->data[1][0];
16097 dst->data[0][1] = -invdet * src->data[0][1];
16098
16099 return TRUE;
16100 }
16101
16102 if( n == 3 )
16103 {
16104
16105
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120 double invdet;
16121 double r,s,t,u,v,w,x,y,z;
16122 double vzyw;
16123 double xwuz;
16124 double uyxv;
16125
16126 r = src->data[0][0]; s = src->data[1][0]; t = src->data[2][0];
16127 u = src->data[0][1]; v = src->data[1][1]; w = src->data[2][1];
16128 x = src->data[0][2]; y = src->data[1][2]; z = src->data[2][2];
16129
16130
16131 vzyw = v*z - y*w;
16132 xwuz = x*w - u*z;
16133 uyxv = u*y - x*v;
16134
16135 invdet = r*vzyw + s*xwuz + t*uyxv;
16136
16137
16138 invdet = 1.0/invdet;
16139
16140 dst->data[0][0] = invdet*vzyw; dst->data[1][0] = invdet*(t*y-z*s); dst->data[2][0] = invdet*(s*w-v*t);
16141 dst->data[0][1] = invdet*xwuz; dst->data[1][1] = invdet*(r*z-x*t); dst->data[2][1] = invdet*(u*t-r*w);
16142 dst->data[0][2] = invdet*uyxv; dst->data[1][2] = invdet*(x*s-r*y); dst->data[2][2] = invdet*(r*v-u*s);
16143
16144 return TRUE;
16145 }
16146 }
16147 else
16148 {
16149
16150
16151
16152 if( n == 1 )
16153 {
16154
16155 dtmp = src->cplx[0][0].re*src->cplx[0][0].re + src->cplx[0][0].im*src->cplx[0][0].im;
16156 dst->cplx[0][0].re = src->cplx[0][0].re / dtmp;
16157 dst->cplx[0][0].im = -src->cplx[0][0].im / dtmp;
16158 return TRUE;
16159 }
16160
16161 if( n == 2 )
16162 {
16163
16164
16165
16166 stComplex invdet;
16167 stComplex tmpcplx;
16168
16169
16170 if( !MTX_Det( src, &tmpcplx.re, &tmpcplx.im ) )
16171 {
16172 MTX_ERROR_MSG( "MTX_Det returned FALSE." );
16173 return FALSE;
16174 }
16175
16176 dtmp = tmpcplx.re*tmpcplx.re + tmpcplx.im*tmpcplx.im;
16177 invdet.re = tmpcplx.re / dtmp;
16178 invdet.im = -tmpcplx.im / dtmp;
16179
16180
16181 dst->cplx[0][0].re = src->cplx[1][1].re;
16182 dst->cplx[0][0].im = src->cplx[1][1].im;
16183 dst->cplx[1][1].re = src->cplx[0][0].re;
16184 dst->cplx[1][1].re = src->cplx[0][0].im;
16185 dst->cplx[1][0].re = -src->cplx[1][0].re;
16186 dst->cplx[1][0].im = -src->cplx[1][0].im;
16187 dst->cplx[0][1].re = -src->cplx[0][1].re;
16188 dst->cplx[0][1].im = -src->cplx[0][1].im;
16189
16190
16191 if( !MTX_Multiply_ScalarComplex( dst, invdet.re, invdet.im ) )
16192 {
16193 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
16194 return FALSE;
16195 }
16196
16197 return TRUE;
16198 }
16199
16200 if( n == 3 )
16201 {
16202
16203
16204
16205
16206
16207
16208
16209
16210
16211
16212
16213
16214
16215
16216
16217
16218 stComplex invdet;
16219 stComplex r,s,t,u,v,w,x,y,z;
16220 stComplex vzyw;
16221 stComplex xwuz;
16222 stComplex uyxv;
16223 stComplex cplxA;
16224 stComplex cplxB;
16225
16226 r.re = src->cplx[0][0].re; s.re = src->cplx[1][0].re; t.re = src->cplx[2][0].re;
16227 u.re = src->cplx[0][1].re; v.re = src->cplx[1][1].re; w.re = src->cplx[2][1].re;
16228 x.re = src->cplx[0][2].re; y.re = src->cplx[1][2].re; z.re = src->cplx[2][2].re;
16229
16230 r.im = src->cplx[0][0].im; s.im = src->cplx[1][0].im; t.im = src->cplx[2][0].im;
16231 u.im = src->cplx[0][1].im; v.im = src->cplx[1][1].im; w.im = src->cplx[2][1].im;
16232 x.im = src->cplx[0][2].im; y.im = src->cplx[1][2].im; z.im = src->cplx[2][2].im;
16233
16234
16235
16236
16237 MTX_static_quick_complex_mult_ab( &v.re, &v.im, &z.re, &z.im, &cplxA.re, &cplxA.im );
16238 MTX_static_quick_complex_mult_ab( &y.re, &y.im, &w.re, &w.im, &cplxB.re, &cplxB.im );
16239 vzyw.re = cplxA.re - cplxB.re;
16240 vzyw.im = cplxA.im - cplxB.im;
16241
16242
16243 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &w.re, &w.im, &cplxA.re, &cplxA.im );
16244 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &z.re, &z.im, &cplxB.re, &cplxB.im );
16245 xwuz.re = cplxA.re - cplxB.re;
16246 xwuz.im = cplxA.im - cplxB.im;
16247
16248
16249 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &y.re, &y.im, &cplxA.re, &cplxA.im );
16250 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &v.re, &v.im, &cplxB.re, &cplxB.im );
16251 uyxv.re = cplxA.re - cplxB.re;
16252 uyxv.im = cplxA.im - cplxB.im;
16253
16254 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &vzyw.re, &vzyw.im, &cplxA.re, &cplxA.im );
16255 MTX_static_quick_complex_mult_ab( &s.re, &s.im, &xwuz.re, &xwuz.im, &cplxB.re, &cplxB.im );
16256 MTX_static_quick_complex_mult_ab( &t.re, &t.im, &uyxv.re, &uyxv.im, &invdet.re, &invdet.im );
16257
16258
16259 invdet.re += cplxA.re + cplxB.re;
16260 invdet.im += cplxA.im + cplxB.im;
16261
16262
16263 dtmp = invdet.re*invdet.re + invdet.im*invdet.im;
16264 invdet.re = invdet.re/dtmp;
16265 invdet.im = -invdet.im/dtmp;
16266
16267 dst->cplx[0][0].re = vzyw.re;
16268 dst->cplx[0][1].re = xwuz.re;
16269 dst->cplx[0][2].re = uyxv.re;
16270
16271 dst->cplx[0][0].im = vzyw.im;
16272 dst->cplx[0][1].im = xwuz.im;
16273 dst->cplx[0][2].im = uyxv.im;
16274
16275
16276 MTX_static_quick_complex_mult_ab( &t.re, &t.im, &y.re, &y.im, &cplxA.re, &cplxA.im );
16277 MTX_static_quick_complex_mult_ab( &z.re, &z.im, &s.re, &s.im, &cplxB.re, &cplxB.im );
16278 dst->cplx[1][0].re = cplxA.re - cplxB.re;
16279 dst->cplx[1][0].im = cplxA.im - cplxB.im;
16280
16281
16282 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &z.re, &z.im, &cplxA.re, &cplxA.im );
16283 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &t.re, &t.im, &cplxB.re, &cplxB.im );
16284 dst->cplx[1][1].re = cplxA.re - cplxB.re;
16285 dst->cplx[1][1].im = cplxA.im - cplxB.im;
16286
16287
16288 MTX_static_quick_complex_mult_ab( &x.re, &x.im, &s.re, &s.im, &cplxA.re, &cplxA.im );
16289 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &y.re, &y.im, &cplxB.re, &cplxB.im );
16290 dst->cplx[1][2].re = cplxA.re - cplxB.re;
16291 dst->cplx[1][2].im = cplxA.im - cplxB.im;
16292
16293
16294 MTX_static_quick_complex_mult_ab( &s.re, &s.im, &w.re, &w.im, &cplxA.re, &cplxA.im );
16295 MTX_static_quick_complex_mult_ab( &v.re, &v.im, &t.re, &t.im, &cplxB.re, &cplxB.im );
16296 dst->cplx[2][0].re = cplxA.re - cplxB.re;
16297 dst->cplx[2][0].im = cplxA.im - cplxB.im;
16298
16299
16300 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &t.re, &t.im, &cplxA.re, &cplxA.im );
16301 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &w.re, &w.im, &cplxB.re, &cplxB.im );
16302 dst->cplx[2][1].re = cplxA.re - cplxB.re;
16303 dst->cplx[2][1].im = cplxA.im - cplxB.im;
16304
16305
16306 MTX_static_quick_complex_mult_ab( &r.re, &r.im, &v.re, &v.im, &cplxA.re, &cplxA.im );
16307 MTX_static_quick_complex_mult_ab( &u.re, &u.im, &s.re, &s.im, &cplxB.re, &cplxB.im );
16308 dst->cplx[2][2].re = cplxA.re - cplxB.re;
16309 dst->cplx[2][2].im = cplxA.im - cplxB.im;
16310
16311 if( !MTX_Multiply_ScalarComplex( dst, invdet.re, invdet.im ) )
16312 {
16313 MTX_ERROR_MSG( "MTX_Multiply_ScalarComplex returned FALSE." );
16314 return FALSE;
16315 }
16316
16317 return TRUE;
16318 }
16319 }
16320
16321 MTX_ERROR_MSG( "Unexpected." );
16322 return FALSE;
16323 }
16324
16325
16326
16327
16328
16329 BOOL MTX_InvertInPlace( MTX *M )
16330 {
16331 unsigned i = 0;
16332 unsigned j = 0;
16333 unsigned k = 0;
16334 BOOL isPositiveDefinite = TRUE;
16335 unsigned n;
16336 double **ptrptrData;
16337 double val;
16338 double dtmp;
16339 double maxdif;
16340 MTX copyM;
16341
16342
16343 MTX_Init( ©M );
16344
16345 if( MTX_isNull( M ) )
16346 {
16347 MTX_ERROR_MSG( "NULL Matrix" );
16348 return FALSE;
16349 }
16350 n = M->nrows;
16351 if( !MTX_isSquare( M ) )
16352 {
16353 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
16354 return FALSE;
16355 }
16356 if( n == 0 )
16357 {
16358 MTX_ERROR_MSG( "if( n == 0 )" );
16359 return FALSE;
16360 }
16361
16362
16363 if( n < 4 )
16364 {
16365 return MTX_InvertInPlaceClosedForm( M );
16366 }
16367
16368 if( M->isReal )
16369 {
16370
16371 for( j = 0; j < n; j++ )
16372 {
16373
16374 if( M->data[j][j] <= 0.0 )
16375 {
16376 isPositiveDefinite = FALSE;
16377 break;
16378 }
16379 }
16380 if( !isPositiveDefinite )
16381 {
16382
16383 return MTX_InvertInPlaceRobust( M );
16384 }
16385
16386
16387 for( i = 0; i < n; i++ )
16388 {
16389 for( j = i+1; j < n; j++ )
16390 {
16391 val = M->data[j][i];
16392 maxdif = fabs( val )*1e-14;
16393
16394
16395
16396
16397 dtmp = fabs( val - M->data[i][j] );
16398 if( dtmp > maxdif )
16399 {
16400
16401
16402
16403 isPositiveDefinite = FALSE;
16404 break;
16405 }
16406 }
16407 if( !isPositiveDefinite )
16408 break;
16409 }
16410 if( !isPositiveDefinite )
16411 {
16412
16413 return MTX_InvertInPlaceRobust( M );
16414 }
16415
16416
16417 if( !MTX_Copy( M, ©M ) )
16418 {
16419 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
16420 MTX_Free( ©M );
16421 return FALSE;
16422 }
16423
16424
16425 for( j = 0; j < n; j++ )
16426 {
16427 for( k = 0; k < j; k++ )
16428 {
16429 val = M->data[k][j];
16430 M->data[j][j] -= val * val;
16431 }
16432
16433 val = M->data[j][j];
16434 if( val < 0.0 )
16435 {
16436
16437 if( !MTX_InvertInPlaceRobust( ©M ) )
16438 {
16439 MTX_ERROR_MSG( "MTX_InvertInPlaceRobust returned FALSE." );
16440 MTX_Free(©M);
16441 return FALSE;
16442 }
16443
16444
16445 ptrptrData = M->data;
16446 M->data = copyM.data;
16447 copyM.data = ptrptrData;
16448 MTX_Free( ©M );
16449 return TRUE;
16450 }
16451
16452 M->data[j][j] = sqrt( val );
16453
16454 for( i = j + 1; i < n; i++ )
16455 {
16456 for( k = 0; k < j; k++ )
16457 M->data[j][i] -= M->data[k][i] * M->data[k][j];
16458
16459 val = M->data[j][j];
16460 if( fabs(val) < 1.0E-20 )
16461 {
16462
16463 if( !MTX_InvertInPlaceRobust( ©M ) )
16464 {
16465 MTX_ERROR_MSG( "MTX_InvertInPlaceRobust returned FALSE." );
16466 MTX_Free(©M);
16467 return FALSE;
16468 }
16469
16470
16471 ptrptrData = M->data;
16472 M->data = copyM.data;
16473 copyM.data = ptrptrData;
16474 MTX_Free( ©M );
16475 return TRUE;
16476 }
16477
16478 M->data[j][i] /= val;
16479 }
16480 }
16481
16482
16483 for( j = 0; j < n; j++ )
16484 {
16485 M->data[j][j] = 1.0 / M->data[j][j];
16486
16487 for( i = j + 1; i < n; i++ )
16488 {
16489 M->data[j][i] *= -M->data[j][j] / M->data[i][i];
16490
16491 val = M->data[i][i];
16492 for( k = j + 1; k < i; k++ )
16493 M->data[j][i] -= M->data[k][i] * M->data[j][k] / val;
16494 }
16495 }
16496
16497
16498 for( j = 0; j < n; j++ )
16499 {
16500 for( i = j; i < n; i++ )
16501 {
16502 M->data[j][i] *= M->data[i][i];
16503
16504 for( k = i + 1; k < n; k++ )
16505 M->data[j][i] += M->data[i][k] * M->data[j][k];
16506 }
16507 }
16508
16509
16510 for( i = 1; i < n; i++ )
16511 {
16512 for( j = 0; j < i; j++ )
16513 M->data[i][j] = M->data[j][i];
16514 }
16515
16516 MTX_Free(©M);
16517 }
16518 else
16519 {
16520
16521 return MTX_InvertInPlaceRobust( M );
16522 }
16523 return TRUE;
16524 }
16525
16526
16527
16528 BOOL MTX_Invert( const MTX *src, MTX *dst )
16529 {
16530 unsigned i = 0;
16531 unsigned j = 0;
16532 unsigned k = 0;
16533 BOOL isPositiveDefinite = TRUE;
16534 unsigned n;
16535 double val;
16536 double dtmp;
16537 double maxdif;
16538
16539 if( dst == NULL )
16540 {
16541 MTX_ERROR_MSG( "NULL input matrix." );
16542 return FALSE;
16543 }
16544 if( MTX_isNull( src ) )
16545 {
16546 MTX_ERROR_MSG( "NULL Matrix" );
16547 return FALSE;
16548 }
16549 n = src->nrows;
16550 if( !MTX_isSquare( src ) )
16551 {
16552 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
16553 return FALSE;
16554 }
16555 if( n == 0 )
16556 {
16557 MTX_ERROR_MSG( "if( n == 0 )" );
16558 return FALSE;
16559 }
16560
16561
16562 if( n < 4 )
16563 {
16564 return MTX_InvertClosedForm( src, dst );
16565 }
16566
16567
16568 if( !MTX_Copy( src, dst ) )
16569 {
16570 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
16571 return FALSE;
16572 }
16573
16574 if( src->isReal )
16575 {
16576
16577 for( j = 0; j < n; j++ )
16578 {
16579
16580 if( src->data[j][j] <= 0.0 )
16581 {
16582 isPositiveDefinite = FALSE;
16583 break;
16584 }
16585 }
16586 if( !isPositiveDefinite )
16587 {
16588
16589 return MTX_InvertInPlaceRobust( dst );
16590 }
16591
16592
16593 for( i = 0; i < n; i++ )
16594 {
16595 for( j = i+1; j < n; j++ )
16596 {
16597 val = src->data[j][i];
16598 maxdif = fabs( val )*1e-14;
16599
16600
16601
16602
16603 dtmp = fabs( val - src->data[i][j] );
16604 if( dtmp > maxdif )
16605 {
16606
16607
16608
16609 isPositiveDefinite = FALSE;
16610 break;
16611 }
16612 }
16613 if( !isPositiveDefinite )
16614 break;
16615 }
16616 if( !isPositiveDefinite )
16617 {
16618
16619 return MTX_InvertInPlaceRobust( dst );
16620 }
16621
16622
16623 for( j = 0; j < n; j++ )
16624 {
16625 for( k = 0; k < j; k++ )
16626 {
16627 val = dst->data[k][j];
16628 dst->data[j][j] -= val*val;
16629 }
16630
16631 val = dst->data[j][j];
16632 if( val < 0.0 )
16633 {
16634
16635 if( !MTX_Copy( src, dst ) )
16636 {
16637 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
16638 return FALSE;
16639 }
16640 if( !MTX_InvertInPlaceRobust( dst ) )
16641 {
16642 MTX_ERROR_MSG( "MTX_InvertInPlaceRobust returned FALSE." );
16643 return FALSE;
16644 }
16645 return TRUE;
16646 }
16647
16648 dst->data[j][j] = sqrt( val );
16649
16650 for( i = j + 1; i < n; i++ )
16651 {
16652 for( k = 0; k < j; k++ )
16653 dst->data[j][i] -= dst->data[k][i] * dst->data[k][j];
16654
16655 val = dst->data[j][j];
16656 if( fabs(val) < 1.0E-20 )
16657 {
16658
16659 if( !MTX_Copy( src, dst ) )
16660 {
16661 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
16662 return FALSE;
16663 }
16664 if( !MTX_InvertInPlaceRobust( dst ) )
16665 {
16666 MTX_ERROR_MSG( "MTX_InvertInPlaceRobust returned FALSE." );
16667 return FALSE;
16668 }
16669 return TRUE;
16670 }
16671
16672 dst->data[j][i] /= val;
16673 }
16674 }
16675
16676
16677 for( j = 0; j < n; j++ )
16678 {
16679 dst->data[j][j] = 1.0 / dst->data[j][j];
16680
16681 for( i = j + 1; i < n; i++ )
16682 {
16683 dst->data[j][i] *= -dst->data[j][j] / dst->data[i][i];
16684
16685 val = dst->data[i][i];
16686 for( k = j + 1; k < i; k++ )
16687 dst->data[j][i] -= dst->data[k][i] * dst->data[j][k] / val;
16688 }
16689 }
16690
16691
16692 for( j = 0; j < n; j++ )
16693 {
16694 for( i = j; i < n; i++ )
16695 {
16696 dst->data[j][i] *= dst->data[i][i];
16697
16698 for( k = i + 1; k < n; k++ )
16699 dst->data[j][i] += dst->data[i][k] * dst->data[j][k];
16700 }
16701 }
16702
16703
16704 for( i = 1; i < n; i++ )
16705 {
16706 for( j = 0; j < i; j++ )
16707 dst->data[i][j] = dst->data[j][i];
16708 }
16709 }
16710 else
16711 {
16712
16713 return MTX_InvertInPlaceRobust( dst );
16714 }
16715 return TRUE;
16716 }
16717
16718
16719 BOOL MTX_InvertInPlaceRobust( MTX *M )
16720 {
16721 unsigned i = 0;
16722 const unsigned n = M->nrows;
16723 BOOL isFullRank = FALSE;
16724 unsigned *index = NULL;
16725 MTX A;
16726 MTX ColumnI;
16727 MTX X;
16728
16729
16730
16731 MTX_Init( &A);
16732
16733 if( MTX_isNull( M ) )
16734 {
16735 MTX_ERROR_MSG( "NULL Matrix" );
16736 return FALSE;
16737 }
16738 if( !MTX_isSquare( M ) )
16739 {
16740 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
16741 return FALSE;
16742 }
16743 if( n == 0 )
16744 {
16745 MTX_ERROR_MSG( "if( n == 0 )" );
16746 return FALSE;
16747 }
16748
16749
16750 if( n < 4 )
16751 {
16752 return MTX_InvertInPlaceClosedForm( M );
16753 }
16754
16755
16756 if( !MTX_Copy( M, &A) )
16757 {
16758 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
16759 MTX_Free( &A );
16760 return FALSE;
16761 }
16762
16763 index = (unsigned*)calloc( n, sizeof(unsigned) );
16764 if( !index )
16765 {
16766 MTX_ERROR_MSG( "calloc returned NULL." );
16767 MTX_Free( &A );
16768 return FALSE;
16769 }
16770
16771
16772 if( !MTX_static_Factorize( &isFullRank, n, index, &A ) )
16773 {
16774 MTX_ERROR_MSG( "MTX_static_Factorize returned FALSE." );
16775 MTX_Free( &A );
16776 if( index )
16777 free(index);
16778 return FALSE;
16779 }
16780 if( !isFullRank )
16781 {
16782 MTX_Free( &A );
16783 if( index )
16784 free(index);
16785 return FALSE;
16786 }
16787
16788 MTX_Init( &ColumnI );
16789 MTX_Init( &X );
16790
16791
16792
16793 X.nrows = n;
16794 X.ncols = 1;
16795
16796 if( M->isReal )
16797 {
16798 X.isReal = TRUE;
16799 if( !MTX_Calloc( &ColumnI, n, 1, TRUE ) )
16800 {
16801 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
16802 MTX_Free( &A );
16803 MTX_Free( &ColumnI );
16804 if(index)
16805 free(index);
16806 return FALSE;
16807 }
16808
16809 for( i = 0; i < n; i++ )
16810 {
16811
16812 X.data = &(M->data[i]);
16813
16814 if( i != 0 )
16815 ColumnI.data[0][i-1] = 0.0;
16816 ColumnI.data[0][i] = 1.0;
16817
16818 if( !MTX_static_SolveByGaussianElimination( &ColumnI, &X, &A, index ) )
16819 {
16820 MTX_ERROR_MSG( "MTX_static_SolveByGaussianElimination returned FALSE." );
16821 MTX_Free( &A );
16822 MTX_Free( &ColumnI );
16823 if(index)
16824 free(index);
16825 return FALSE;
16826 }
16827 }
16828 }
16829 else
16830 {
16831 X.isReal = FALSE;
16832 if( !MTX_Calloc( &ColumnI, n, 1, FALSE ) )
16833 {
16834 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
16835 MTX_Free( &A );
16836 MTX_Free( &ColumnI );
16837 if(index)
16838 free(index);
16839 return FALSE;
16840 }
16841
16842 for( i = 0; i < n; i++ )
16843 {
16844
16845 X.cplx = &(M->cplx[i]);
16846
16847 if( i != 0 )
16848 {
16849 ColumnI.cplx[0][i-1].re = 0.0;
16850 ColumnI.cplx[0][i-1].im = 0.0;
16851 }
16852 ColumnI.cplx[0][i].re = 1.0;
16853 ColumnI.cplx[0][i].im = 0.0;
16854
16855 if( !MTX_static_SolveByGaussianElimination( &ColumnI, &X, &A, index ) )
16856 {
16857 MTX_ERROR_MSG( "MTX_static_SolveByGaussianElimination returned FALSE." );
16858 MTX_Free( &A );
16859 MTX_Free( &ColumnI );
16860 if(index)
16861 free(index);
16862 return FALSE;
16863 }
16864 }
16865 }
16866
16867 if(index)
16868 free(index);
16869
16870 MTX_Free( &A );
16871 MTX_Free( &ColumnI );
16872
16873 return TRUE;
16874 }
16875
16876 BOOL MTX_static_Factorize( BOOL *isFullRank, const unsigned n, unsigned* index, MTX *A )
16877 {
16878
16879
16880 unsigned i = 0;
16881 unsigned j = 0;
16882 unsigned k = 0;
16883 unsigned tempi = 0;
16884 double *scale;
16885
16886 double r = 0.0;
16887 double rmax = 0.0;
16888 double xmult = 0.0;
16889
16890 stComplex cplx_xmult = {0.0,0.0};
16891 stComplex cplx = {0.0,0.0};
16892
16893 BOOL isFullRankTmp = FALSE;
16894
16895 if( MTX_isNull( A ) )
16896 {
16897 MTX_ERROR_MSG( "NULL Matrix" );
16898 return FALSE;
16899 }
16900 if( !MTX_isSquare( A ) )
16901 {
16902 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
16903 return FALSE;
16904 }
16905
16906 if( n == 0 )
16907 {
16908 MTX_ERROR_MSG( "if( n == 0 )" );
16909 return FALSE;
16910 }
16911
16912 scale = (double*)malloc( sizeof(double)*n );
16913 if( !scale )
16914 {
16915 MTX_ERROR_MSG( "malloc returned NULL." );
16916 return FALSE;
16917 }
16918
16919
16920
16921 for( i = 0; i < n; i++ )
16922 {
16923 if( !MTX_MaxAbsRowIndex( A, i, &(scale[i]), &k ) )
16924 {
16925 MTX_ERROR_MSG( "MTX_MaxAbsRowIndex returned FALSE." );
16926 if( scale )
16927 free(scale);
16928 return FALSE;
16929 }
16930 index[i] = i;
16931 }
16932
16933 if( A->isReal )
16934 {
16935
16936
16937 for( k = 0; k < n - 1; k++ )
16938 {
16939
16940 rmax = 0;
16941 j = 0;
16942 for( i = k; i < n; i++ )
16943 {
16944 r = fabs( A->data[k][index[i]] ) / scale[index[i]];
16945 if( r > rmax )
16946 {
16947 rmax = r;
16948 j = i;
16949 }
16950 }
16951
16952 tempi = index[j];
16953 index[j] = index[k];
16954 index[k] = tempi;
16955
16956 for( i = k + 1; i < n; i++ )
16957 {
16958 xmult = A->data[k][index[i]] / A->data[k][index[k]];
16959 A->data[k][index[i]] = xmult;
16960
16961 isFullRankTmp = FALSE;
16962 for( j = k + 1; j < n; j++ )
16963 {
16964 A->data[j][index[i]] = A->data[j][index[i]] - xmult*(A->data[j][index[k]]);
16965
16966
16967 if( A->data[j][index[i]] != 0.0 )
16968 isFullRankTmp = TRUE;
16969 }
16970 if( !isFullRankTmp )
16971 {
16972 *isFullRank = FALSE;
16973 if( scale )
16974 free(scale);
16975 return TRUE;
16976 }
16977 }
16978 }
16979 }
16980 else
16981 {
16982
16983
16984 for( k = 0; k < n - 1; k++ )
16985 {
16986
16987 rmax = 0;
16988 j = 0;
16989 for( i = k; i < n; i++ )
16990 {
16991 r = sqrt( A->cplx[k][index[i]].re*A->cplx[k][index[i]].re + A->cplx[k][index[i]].im*A->cplx[k][index[i]].im );
16992 r = r / scale[index[i]];
16993 if( r > rmax )
16994 {
16995 rmax = r;
16996 j = i;
16997 }
16998 }
16999
17000 tempi = index[j];
17001 index[j] = index[k];
17002 index[k] = tempi;
17003
17004 for( i = k + 1; i < n; i++ )
17005 {
17006 MTX_static_quick_complex_divide(
17007 &(A->cplx[k][index[i]].re),
17008 &(A->cplx[k][index[i]].im),
17009 &(A->cplx[k][index[k]].re),
17010 &(A->cplx[k][index[k]].im),
17011 &cplx_xmult.re,
17012 &cplx_xmult.im );
17013
17014 A->cplx[k][index[i]] = cplx_xmult;
17015
17016 isFullRankTmp = FALSE;
17017 for( j = k + 1; j < n; j++ )
17018 {
17019 MTX_static_quick_complex_mult_ab(
17020 &cplx_xmult.re,
17021 &cplx_xmult.im,
17022 &(A->cplx[j][index[k]].re),
17023 &(A->cplx[j][index[k]].im),
17024 &cplx.re,
17025 &cplx.im );
17026
17027 A->cplx[j][index[i]].re = A->cplx[j][index[i]].re - cplx.re;
17028 A->cplx[j][index[i]].im = A->cplx[j][index[i]].im - cplx.im;
17029
17030
17031 if( A->cplx[j][index[i]].re != 0.0 || A->cplx[j][index[i]].im != 0.0 )
17032 isFullRankTmp = TRUE;
17033 }
17034 if( !isFullRankTmp )
17035 {
17036 *isFullRank = FALSE;
17037 if( scale )
17038 free(scale);
17039 return TRUE;
17040 }
17041 }
17042 }
17043 }
17044
17045 if( scale )
17046 free(scale);
17047
17048 *isFullRank = TRUE;
17049 return TRUE;
17050 }
17051
17052
17053 BOOL MTX_static_SolveByGaussianElimination(
17054 const MTX *b,
17055 MTX *X,
17056 const MTX *A,
17057 unsigned *index )
17058 {
17059 int i = 0;
17060 int j = 0;
17061 int k = 0;
17062 double sum = 0.0;
17063 const int n = A->nrows;
17064 MTX B;
17065 stComplex cplx = {0.0,0.0};
17066 stComplex sum_cplx = {0.0,0.0};
17067
17068
17069 MTX_Init( &B);
17070
17071 if( !MTX_Copy( b, &B ) )
17072 {
17073 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
17074 MTX_Free( &B );
17075 return FALSE;
17076 }
17077
17078 if( A->isReal )
17079 {
17080 for( k = 0; k < n - 1; k++ )
17081 {
17082 for( i = k + 1; i < n; i++ )
17083 {
17084 B.data[0][index[i]] = B.data[0][index[i]] - A->data[k][index[i]]*B.data[0][index[k]];
17085 }
17086 }
17087 X->data[0][n-1] = B.data[0][index[n-1]] / A->data[n-1][index[n-1]];
17088
17089 for( i = n - 2; i >= 0; i-- )
17090 {
17091 sum = B.data[0][index[i]];
17092 for( j = i + 1; j < n; j++ )
17093 {
17094 sum = sum - A->data[j][index[i]]*X->data[0][j];
17095 }
17096 X->data[0][i] = sum / A->data[i][index[i]];
17097 }
17098 }
17099 else
17100 {
17101 for( k = 0; k < n - 1; k++ )
17102 {
17103 for( i = k + 1; i < n; i++ )
17104 {
17105 MTX_static_quick_complex_mult_ab(
17106 &(A->cplx[k][index[i]].re),
17107 &(A->cplx[k][index[i]].im),
17108 &(B.cplx[0][index[k]].re),
17109 &(B.cplx[0][index[k]].im),
17110 &cplx.re,
17111 &cplx.im );
17112
17113 B.cplx[0][index[i]].re = B.cplx[0][index[i]].re - cplx.re;
17114 B.cplx[0][index[i]].im = B.cplx[0][index[i]].im - cplx.im;
17115 }
17116 }
17117
17118 MTX_static_quick_complex_divide(
17119 &(B.cplx[0][index[n-1]].re),
17120 &(B.cplx[0][index[n-1]].im),
17121 &(A->cplx[n-1][index[n-1]].re),
17122 &(A->cplx[n-1][index[n-1]].im),
17123 &(X->cplx[0][n-1].re),
17124 &(X->cplx[0][n-1].im) );
17125
17126 for( i = n - 2; i >= 0; i-- )
17127 {
17128 sum_cplx.re = B.cplx[0][index[i]].re;
17129 sum_cplx.im = B.cplx[0][index[i]].im;
17130
17131 for( j = i + 1; j < n; j++ )
17132 {
17133 MTX_static_quick_complex_mult_ab(
17134 &(A->cplx[j][index[i]].re),
17135 &(A->cplx[j][index[i]].im),
17136 &(X->cplx[0][j].re),
17137 &(X->cplx[0][j].im),
17138 &cplx.re,
17139 &cplx.im );
17140
17141 sum_cplx.re = sum_cplx.re - cplx.re;
17142 sum_cplx.im = sum_cplx.im - cplx.im;
17143 }
17144
17145 MTX_static_quick_complex_divide(
17146 &sum_cplx.re,
17147 &sum_cplx.im,
17148 &(A->cplx[i][index[i]].re),
17149 &(A->cplx[i][index[i]].im),
17150 &(X->cplx[0][i].re),
17151 &(X->cplx[0][i].im) );
17152 }
17153 }
17154
17155 MTX_Free( &B );
17156 return TRUE;
17157 }
17158
17159 BOOL MTX_ColumnMovAvg( const MTX *src, const unsigned col, const unsigned nlead, const unsigned nlag, MTX *dst )
17160 {
17161 unsigned i = 0;
17162 unsigned k = 0;
17163 unsigned count = 0;
17164
17165 double sum = 0.0;
17166 double sum_im = 0.0;
17167
17168 if( MTX_isNull( src ) )
17169 {
17170 MTX_ERROR_MSG( "NULL Matrix" );
17171 return FALSE;
17172 }
17173
17174 if( col >= src->ncols )
17175 {
17176 MTX_ERROR_MSG( "if( col >= src->ncols )" );
17177 return FALSE;
17178 }
17179
17180 if( nlead+nlag > src->nrows )
17181 {
17182 MTX_ERROR_MSG( "if( nlead+nlag > src->nrows )" );
17183 return FALSE;
17184 }
17185
17186
17187 if( dst->isReal != src->isReal )
17188 {
17189 if( !MTX_Resize( dst, src->nrows, 1, src->isReal ) )
17190 {
17191 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17192 return FALSE;
17193 }
17194 }
17195 else if( dst->nrows != src->nrows || dst->ncols != 1 )
17196 {
17197 if( !MTX_Resize( dst, src->nrows, 1, src->isReal ) )
17198 {
17199 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17200 return FALSE;
17201 }
17202 }
17203
17204 if( src->isReal )
17205 {
17206 for( i = 0; i < src->nrows; i++ )
17207 {
17208 sum = src->data[col][i];
17209 count = 1;
17210 for( k = 1; k <= nlead; k++ )
17211 {
17212 if( i >= k )
17213 {
17214 sum += src->data[col][i-k];
17215 count++;
17216 }
17217 }
17218 for( k = 1; k <= nlag; k++ )
17219 {
17220 if( i < src->nrows-k )
17221 {
17222 sum += src->data[col][i+k];
17223 count++;
17224 }
17225 }
17226 dst->data[0][i] = sum / ((double)(count));
17227 }
17228 }
17229 else
17230 {
17231 for( i = 0; i < src->nrows; i++ )
17232 {
17233 sum = src->cplx[col][i].re;
17234 sum_im = src->cplx[col][i].im;
17235 count = 1;
17236 for( k = 1; k <= nlead; k++ )
17237 {
17238 if( i >= k )
17239 {
17240 sum += src->cplx[col][i-k].re;
17241 sum_im += src->cplx[col][i-k].im;
17242 count++;
17243 }
17244 }
17245 for( k = 1; k <= nlag; k++ )
17246 {
17247 if( i < src->nrows-k )
17248 {
17249 sum += src->cplx[col][i+k].re;
17250 sum_im += src->cplx[col][i+k].im;
17251 count++;
17252 }
17253 }
17254 dst->cplx[0][i].re = sum / ((double)(count));
17255 dst->cplx[0][i].im = sum / ((double)(count));
17256 }
17257 }
17258
17259 return TRUE;
17260 }
17261
17262
17263 BOOL MTX_MovAvg( const MTX *src, const unsigned nlead, const unsigned nlag, MTX *dst )
17264 {
17265 unsigned j = 0;
17266
17267 MTX column;
17268
17269 if( MTX_isNull( src ) )
17270 {
17271 MTX_ERROR_MSG( "NULL Matrix" );
17272 return FALSE;
17273 }
17274
17275 MTX_Init( &column );
17276
17277 if( src->isReal != dst->isReal )
17278 {
17279 if( !MTX_Redim( dst, src->nrows, src->ncols ) )
17280 {
17281 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
17282 return FALSE;
17283 }
17284 }
17285 else if( !MTX_isSameSize( src, dst ) )
17286 {
17287 if( !MTX_Redim( dst, src->nrows, src->ncols ) )
17288 {
17289 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
17290 return FALSE;
17291 }
17292 }
17293
17294
17295 column.isReal = dst->isReal;
17296 column.nrows = dst->nrows;
17297 column.ncols = 1;
17298
17299 for( j = 0; j < src->ncols; j++ )
17300 {
17301 if( dst->isReal )
17302 column.data = &(dst->data[j]);
17303 else
17304 column.data = &(dst->data[j]);
17305
17306 if( !MTX_ColumnMovAvg( src, j, nlead, nlag, &column ) )
17307 {
17308 MTX_ERROR_MSG( "MTX_ColumnMovAvg returned FALSE." );
17309 return FALSE;
17310 }
17311 }
17312
17313
17314
17315 return TRUE;
17316 }
17317
17318
17319
17320
17321
17322 BOOL MTX_ATAInverse( const MTX *A, MTX *InvATA )
17323 {
17324 unsigned i = 0;
17325 unsigned j = 0;
17326 unsigned k = 0;
17327 MTX colA;
17328
17329 if( MTX_isNull( A ) )
17330 {
17331 MTX_ERROR_MSG( "NULL Matrix" );
17332 return FALSE;
17333 }
17334
17335
17336 if( MTX_isNull( InvATA ) )
17337 {
17338 if( !MTX_Resize( InvATA, A->ncols, A->ncols, A->isReal ) )
17339 {
17340 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17341 return FALSE;
17342 }
17343 }
17344 else if( InvATA->nrows != A->ncols || InvATA->ncols != A->ncols )
17345 {
17346 if( !MTX_Resize( InvATA, A->ncols, A->ncols, A->isReal ) )
17347 {
17348 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17349 return FALSE;
17350 }
17351 }
17352
17353
17354 MTX_Init( &colA );
17355
17356 for( i = 0; i < A->ncols; i++ )
17357 {
17358 for( j = 0; j < A->ncols; j++ )
17359 {
17360 if( i > j )
17361 {
17362 InvATA->data[j][i] = InvATA->data[i][j];
17363 }
17364 else
17365 {
17366 InvATA->data[j][i] = 0;
17367 for( k = 0; k < A->nrows; k++ )
17368 {
17369 InvATA->data[j][i] += A->data[i][k] * A->data[j][k];
17370 }
17371 }
17372 }
17373 }
17374
17375 return MTX_InvertInPlace( InvATA );
17376 }
17377
17378
17379 BOOL MTX_LowerTriangularInverseInplace( MTX *src )
17380 {
17381 unsigned i = 0;
17382 unsigned j = 0;
17383 unsigned k = 0;
17384
17385 if( MTX_isNull( src ) )
17386 {
17387 MTX_ERROR_MSG( "NULL Matrix" );
17388 return FALSE;
17389 }
17390
17391 if( !MTX_isSquare( src ) )
17392 {
17393 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
17394 return FALSE;
17395 }
17396
17397
17398 for( j = 0; j < src->nrows; j++ )
17399 {
17400 if( src->data[j][j] == 0.0 )
17401 {
17402 MTX_ERROR_MSG( "if( src->data[j][j] == 0.0 )" );
17403 return FALSE;
17404 }
17405
17406 src->data[j][j] = 1.0 / src->data[j][j];
17407
17408 for( i = j + 1; i < src->nrows; i++ )
17409 {
17410 if( src->data[i][i] == 0.0 )
17411 {
17412 MTX_ERROR_MSG( "if( src->data[j][j] == 0.0 )" );
17413 return FALSE;
17414 }
17415
17416 src->data[j][i] *= -src->data[j][j] / src->data[i][i];
17417
17418 for( k = j + 1; k < i; k++ )
17419 src->data[j][i] -= src->data[k][i] * src->data[j][k] / src->data[i][i];
17420 }
17421 }
17422 return TRUE;
17423 }
17424
17425
17426 void MTX_static_quick_complex_mult_ab(
17427 const double* a_re,
17428 const double* a_im,
17429 const double* b_re,
17430 const double* b_im,
17431 double *re,
17432 double *im )
17433 {
17434 *re = (*a_re)*(*b_re) - (*a_im)*(*b_im);
17435 *im = (*a_re)*(*b_im) + (*a_im)*(*b_re);
17436 }
17437
17438
17439 void MTX_static_quick_complex_mult_abc(
17440 const double* a_re,
17441 const double* a_im,
17442 const double* b_re,
17443 const double* b_im,
17444 const double* c_re,
17445 const double* c_im,
17446 double *re,
17447 double *im )
17448 {
17449 double r,i;
17450
17451 r = (*a_re)*(*b_re) - (*a_im)*(*b_im);
17452 i = (*a_re)*(*b_im) + (*a_im)*(*b_re);
17453
17454 *re = r*(*c_re) - i*(*c_im);
17455 *im = r*(*c_im) + i*(*c_re);
17456 }
17457
17458 void MTX_static_quick_complex_divide(
17459 const double* a_re,
17460 const double* a_im,
17461 const double* b_re,
17462 const double* b_im,
17463 double *re,
17464 double *im )
17465 {
17466 double dtmp;
17467 dtmp = (*b_re)*(*b_re) + (*b_im)*(*b_im);
17468 *re = ((*a_re) * (*b_re) + (*a_im) * (*b_im) ) / dtmp;
17469 *im = ((*a_im) * (*b_re) - (*a_re) * (*b_im) ) / dtmp;
17470 }
17471
17472
17473
17474 void MTX_static_Det_cleanup( unsigned *index, double *scale, MTX *U, MTX *magMtx )
17475 {
17476 if( index )
17477 {
17478 free( index );
17479 index = NULL;
17480 }
17481 if( scale )
17482 {
17483 free( scale );
17484 scale = NULL;
17485 }
17486 if( U != NULL )
17487 {
17488 MTX_Free( U );
17489 }
17490 if( magMtx != NULL )
17491 {
17492 MTX_Free( magMtx );
17493 }
17494 }
17495
17496
17497
17498 BOOL MTX_Det( const MTX *M, double *re, double *im )
17499 {
17500 unsigned n;
17501 double tmpre;
17502 double tmpim;
17503 int s;
17504
17505 unsigned *index = NULL;
17506 double *scale = NULL;
17507
17508 MTX U;
17509 MTX magMtx;
17510
17511 MTX_Init( &U );
17512 MTX_Init( &magMtx );
17513
17514 if( MTX_isNull( M ) )
17515 {
17516 MTX_ERROR_MSG( "NULL Matrix" );
17517 return FALSE;
17518 }
17519 if( !MTX_isSquare( M ) )
17520 {
17521 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
17522 return FALSE;
17523 }
17524
17525 n = M->nrows;
17526
17527 *re = 0.0;
17528 *im = 0.0;
17529
17530
17531
17532 if( n == 1 )
17533 {
17534 if( M->isReal )
17535 {
17536 *re = M->data[0][0];
17537 }
17538 else
17539 {
17540 *re = M->cplx[0][0].re;
17541 *im = M->cplx[0][0].im;
17542 }
17543 return TRUE;
17544 }
17545 else if( n == 2 )
17546 {
17547 if( M->isReal )
17548 {
17549 *re = M->data[0][0]*M->data[1][1] - M->data[0][1]*M->data[1][0];
17550 }
17551 else
17552 {
17553 *re = M->cplx[0][0].re*M->cplx[1][1].re - M->cplx[0][0].im*M->cplx[1][1].im;
17554 *im = M->cplx[0][0].re*M->cplx[1][1].im + M->cplx[0][0].im*M->cplx[1][1].re;
17555
17556 *re -= M->cplx[0][1].re*M->cplx[1][0].re - M->cplx[0][1].im*M->cplx[1][0].im;
17557 *im -= M->cplx[0][1].re*M->cplx[1][0].im + M->cplx[0][1].im*M->cplx[1][0].re;
17558 }
17559 return TRUE;
17560 }
17561
17562
17563
17564
17565 if( n == 3)
17566 {
17567
17568
17569
17570
17571 if( M->isReal )
17572 {
17573 *re = M->data[0][0]*M->data[1][1]*M->data[2][2] +
17574 M->data[2][0]*M->data[0][1]*M->data[1][2] +
17575 M->data[1][0]*M->data[2][1]*M->data[0][2] -
17576 M->data[2][0]*M->data[1][1]*M->data[0][2] -
17577 M->data[0][0]*M->data[2][1]*M->data[1][2] -
17578 M->data[1][0]*M->data[0][1]*M->data[2][2];
17579 }
17580 else
17581 {
17582 MTX_static_quick_complex_mult_abc(
17583 &(M->cplx[0][0].re), &(M->cplx[0][0].im),
17584 &(M->cplx[1][1].re), &(M->cplx[1][1].im),
17585 &(M->cplx[2][2].re), &(M->cplx[2][2].im),
17586 &tmpre, &tmpim );
17587 *re = tmpre;
17588 *im = tmpim;
17589
17590 MTX_static_quick_complex_mult_abc(
17591 &(M->cplx[2][0].re), &(M->cplx[2][0].im),
17592 &(M->cplx[0][1].re), &(M->cplx[0][1].im),
17593 &(M->cplx[1][2].re), &(M->cplx[1][2].im),
17594 &tmpre, &tmpim );
17595 *re += tmpre;
17596 *im += tmpim;
17597
17598 MTX_static_quick_complex_mult_abc(
17599 &(M->cplx[1][0].re), &(M->cplx[1][0].im),
17600 &(M->cplx[2][1].re), &(M->cplx[2][1].im),
17601 &(M->cplx[0][2].re), &(M->cplx[0][2].im),
17602 &tmpre, &tmpim );
17603 *re += tmpre;
17604 *im += tmpim;
17605
17606 MTX_static_quick_complex_mult_abc(
17607 &(M->cplx[2][0].re), &(M->cplx[2][0].im),
17608 &(M->cplx[1][1].re), &(M->cplx[1][1].im),
17609 &(M->cplx[0][2].re), &(M->cplx[0][2].im),
17610 &tmpre, &tmpim );
17611 *re -= tmpre;
17612 *im -= tmpim;
17613
17614 MTX_static_quick_complex_mult_abc(
17615 &(M->cplx[0][0].re), &(M->cplx[0][0].im),
17616 &(M->cplx[2][1].re), &(M->cplx[2][1].im),
17617 &(M->cplx[1][2].re), &(M->cplx[1][2].im),
17618 &tmpre, &tmpim );
17619 *re -= tmpre;
17620 *im -= tmpim;
17621
17622 MTX_static_quick_complex_mult_abc(
17623 &(M->cplx[1][0].re), &(M->cplx[1][0].im),
17624 &(M->cplx[0][1].re), &(M->cplx[0][1].im),
17625 &(M->cplx[2][2].re), &(M->cplx[2][2].im),
17626 &tmpre, &tmpim );
17627 *re -= tmpre;
17628 *im -= tmpim;
17629 }
17630 return TRUE;
17631 }
17632 else
17633 {
17634 stComplex det;
17635 stComplex xmult;
17636
17637 unsigned i;
17638 unsigned j;
17639 unsigned k;
17640 unsigned tempi;
17641
17642 double r = 0.0,
17643 rmax = 0.0,
17644 smax = 0.0,
17645 tempd = 0.0;
17646
17647 BOOL isFullRankTmp = FALSE;
17648 BOOL isFullRank = TRUE;
17649
17650
17651
17652
17653
17654
17655
17656
17657 if( !MTX_Copy( M, &U ) )
17658 {
17659 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
17660 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17661 return FALSE;
17662 }
17663
17664 index = (unsigned*)malloc( sizeof(unsigned)*n );
17665 if( !index )
17666 {
17667 MTX_ERROR_MSG( "malloc returned NULL." );
17668 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17669 return FALSE;
17670 }
17671
17672 scale = (double*)malloc( sizeof(double)*n );
17673 if( !index )
17674 {
17675 MTX_ERROR_MSG( "malloc returned NULL." );
17676 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17677 return FALSE;
17678 }
17679
17680
17681 if( M->isReal )
17682 {
17683
17684
17685
17686
17687
17688 for( i = 0; i < n; i++ )
17689 {
17690 index[i] = i;
17691 smax = 0;
17692 for( j = 0; j < n; j++ )
17693 {
17694 tempd = fabs( U.data[j][i] );
17695 if( smax < tempd )
17696 {
17697 smax = tempd;
17698 }
17699 }
17700 scale[i] = smax;
17701 if( scale[i] == 0.0 )
17702 {
17703 *re = 0.0;
17704 *im = 0.0;
17705
17706 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17707
17708 return TRUE;
17709 }
17710 }
17711
17712
17713
17714 for( k = 0; k < n - 1; k++ )
17715 {
17716
17717 j = 0;
17718 rmax = 0;
17719 for( i = k; i < n; i++ )
17720 {
17721 r = fabs( U.data[k][index[i]] ) / scale[index[i]];
17722
17723 if( r >= rmax )
17724 {
17725 rmax = r;
17726 j = i;
17727 }
17728 }
17729
17730 tempi = index[j];
17731 index[j] = index[k];
17732 index[k] = tempi;
17733
17734 for( i = k + 1; i < n; i++ )
17735 {
17736 xmult.re = U.data[k][index[i]] / U.data[k][index[k]];
17737
17738 isFullRankTmp = FALSE;
17739 for( j = k + 1; j < n; j++ )
17740 {
17741 U.data[j][index[i]] = U.data[j][index[i]] - xmult.re*U.data[j][index[k]];
17742
17743
17744 if( U.data[j][index[i]] != 0 )
17745 isFullRankTmp = TRUE;
17746 }
17747 if( !isFullRankTmp )
17748 {
17749 *re = 0.0;
17750 *im = 0.0;
17751
17752 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17753
17754 return TRUE;
17755 }
17756 }
17757 }
17758
17759
17760
17761
17762 det.re = 1;
17763 det.im = 0;
17764 for( j = 0; j < n; j++ )
17765 {
17766 det.re *= U.data[j][index[j]];
17767 }
17768
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780 s = 1;
17781 for( j = 0; j < n-1; j++ )
17782 {
17783 if( index[j]%2!=0 )
17784 s *= -1;
17785 for( i=j+1; i < n; i++ )
17786 {
17787 if( index[i] > j )
17788 index[i]--;
17789 }
17790 }
17791 det.re *= s;
17792
17793 *re = det.re;
17794
17795 }
17796 else
17797 {
17798
17799 if( !MTX_Magnitude( M, &magMtx ) )
17800 {
17801 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
17802 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17803 return FALSE;
17804 }
17805
17806
17807
17808
17809
17810
17811 for( i = 0; i < n; i++ )
17812 {
17813 index[i] = i;
17814 smax = 0;
17815 for( j = 0; j < n; j++ )
17816 {
17817 if( smax < magMtx.data[j][i] )
17818 {
17819 smax = magMtx.data[j][i];
17820 }
17821 }
17822 scale[i] = smax;
17823 if( scale[i] == 0.0 )
17824 {
17825 *re = 0.0;
17826 *im = 0.0;
17827
17828 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17829
17830 return TRUE;
17831 }
17832 }
17833
17834
17835
17836 for( k = 0; k < n - 1; k++ )
17837 {
17838
17839 j = 0;
17840 rmax = 0;
17841 for( i = k; i < n; i++ )
17842 {
17843 r = magMtx.data[k][index[i]] / scale[index[i]];
17844
17845 if( r >= rmax )
17846 {
17847 rmax = r;
17848 j = i;
17849 }
17850 }
17851
17852 tempi = index[j];
17853 index[j] = index[k];
17854 index[k] = tempi;
17855
17856 for( i = k + 1; i < n; i++ )
17857 {
17858
17859 MTX_static_quick_complex_divide(
17860 &(U.cplx[k][index[i]].re),
17861 &(U.cplx[k][index[i]].im),
17862 &(U.cplx[k][index[k]].re),
17863 &(U.cplx[k][index[k]].im),
17864 &(xmult.re),
17865 &(xmult.im)
17866 );
17867
17868 isFullRankTmp = FALSE;
17869 for( j = k + 1; j < n; j++ )
17870 {
17871
17872 tmpre = xmult.re * U.cplx[j][index[k]].re - xmult.im * U.cplx[j][index[k]].im;
17873 tmpim = xmult.re * U.cplx[j][index[k]].im + xmult.im * U.cplx[j][index[k]].re;
17874
17875 U.cplx[j][index[i]].re = U.cplx[j][index[i]].re - tmpre;
17876 U.cplx[j][index[i]].im = U.cplx[j][index[i]].im - tmpim;
17877
17878
17879 if( U.cplx[j][index[i]].re != 0 )
17880 isFullRankTmp = TRUE;
17881 if( U.cplx[j][index[i]].im != 0 )
17882 isFullRankTmp = TRUE;
17883 }
17884 if( !isFullRankTmp )
17885 {
17886 *re = 0.0;
17887 *im = 0.0;
17888
17889 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17890 return TRUE;
17891 }
17892 }
17893 }
17894
17895
17896 j = 0;
17897 det.re = U.cplx[j][index[j]].re;
17898 det.im = U.cplx[j][index[j]].im;
17899 for( j = 1; j < n; j++ )
17900 {
17901 tmpre = det.re * U.cplx[j][index[j]].re - det.im * U.cplx[j][index[j]].im;
17902 tmpim = det.re * U.cplx[j][index[j]].im + det.im * U.cplx[j][index[j]].re;
17903
17904 det.re = tmpre;
17905 det.im = tmpim;
17906 }
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918
17919 s = 1;
17920 for( j = 0; j < n-1; j++ )
17921 {
17922 if( index[j]%2!=0 )
17923 s *= -1;
17924 for( i=j+1; i < n; i++ )
17925 {
17926 if( index[i] > j )
17927 index[i]--;
17928 }
17929 }
17930 det.re *= s;
17931 det.im *= s;
17932
17933
17934 *re = det.re;
17935 *im = det.im;
17936 }
17937
17938 MTX_static_Det_cleanup( index, scale, &U, &magMtx );
17939
17940 isFullRank = TRUE;
17941 }
17942
17943 return TRUE;
17944 }
17945
17946 BOOL MTX_LUFactorization( const MTX *src, BOOL *IsFullRank, MTX *P, MTX *L, MTX *U )
17947 {
17948
17949
17950
17951
17952 unsigned n;
17953 unsigned i = 0;
17954 unsigned j = 0;
17955 unsigned k = 0;
17956 unsigned tempi = 0;
17957 unsigned *index = NULL;
17958 double *scale = NULL;
17959 double r = 0.0,
17960 rmax = 0.0,
17961 smax = 0.0,
17962 tempd = 0.0;
17963
17964 stComplex xmult;
17965
17966 BOOL isFullRankTmp = FALSE;
17967
17968
17969 if( MTX_isNull( src ) )
17970 {
17971 MTX_ERROR_MSG( "NULL Matrix" );
17972 return FALSE;
17973 }
17974
17975 if( !MTX_isSquare( src ) )
17976 {
17977 MTX_ERROR_MSG( "MTX_isSquare returned FALSE." );
17978 return FALSE;
17979 }
17980
17981 n = src->nrows;
17982
17983
17984 if( P->nrows != n || P->ncols != n || !P->isReal )
17985 {
17986 if( !MTX_Resize( P, n, n, TRUE ) )
17987 {
17988 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17989 return FALSE;
17990 }
17991 }
17992 if( L->nrows != n || L->ncols != n || (L->isReal != src->isReal) )
17993 {
17994 if( !MTX_Resize( L, n, n, src->isReal ) )
17995 {
17996 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
17997 return FALSE;
17998 }
17999 }
18000 if( U->nrows != n || U->ncols != n || (U->isReal != src->isReal) )
18001 {
18002 if( !MTX_Resize( U, n, n, src->isReal ) )
18003 {
18004 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
18005 return FALSE;
18006 }
18007 }
18008
18009 if( !MTX_Zero( P ) )
18010 {
18011 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18012 return FALSE;
18013 }
18014 if( !MTX_Zero( L ) )
18015 {
18016 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18017 return FALSE;
18018 }
18019
18020 if( !MTX_Copy( src, U ) )
18021 {
18022 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
18023 return FALSE;
18024 }
18025
18026 index = (unsigned*)malloc( sizeof(unsigned)*n );
18027 if( !index )
18028 {
18029 MTX_ERROR_MSG( "malloc returned NULL." );
18030 return FALSE;
18031 }
18032
18033 scale = (double*)malloc( sizeof(double)*n );
18034 if( !scale )
18035 {
18036 MTX_ERROR_MSG( "malloc returned NULL." );
18037 if( index )
18038 free( index );
18039 return FALSE;
18040 }
18041
18042 if( src->isReal )
18043 {
18044
18045
18046
18047
18048
18049 for( i = 0; i < n; i++ )
18050 {
18051 index[i] = i;
18052 smax = 0;
18053 for( j = 0; j < n; j++ )
18054 {
18055 tempd = fabs( U->data[j][i] );
18056 if( smax < tempd )
18057 {
18058 smax = tempd;
18059 }
18060 }
18061 scale[i] = smax;
18062 if( scale[i] == 0.0 )
18063 {
18064 *IsFullRank = FALSE;
18065 if(index)
18066 free(index);
18067 if(scale)
18068 free(scale);
18069 if( !MTX_Zero(L) )
18070 {
18071 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18072 return FALSE;
18073 }
18074 if( !MTX_Zero(U) )
18075 {
18076 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18077 return FALSE;
18078 }
18079
18080 return TRUE;
18081 }
18082 }
18083
18084
18085
18086 for( k = 0; k < n - 1; k++ )
18087 {
18088
18089 j = 0;
18090 rmax = 0;
18091 for( i = k; i < n; i++ )
18092 {
18093 r = fabs( U->data[k][index[i]] ) / scale[index[i]];
18094
18095 if( r >= rmax )
18096 {
18097 rmax = r;
18098 j = i;
18099 }
18100 }
18101
18102 tempi = index[j];
18103 index[j] = index[k];
18104 index[k] = tempi;
18105
18106 for( i = k + 1; i < n; i++ )
18107 {
18108 xmult.re = U->data[k][index[i]] / U->data[k][index[k]];
18109 L->data[k][index[i]] = xmult.re;
18110
18111 isFullRankTmp = FALSE;
18112 for( j = k + 1; j < n; j++ )
18113 {
18114 U->data[j][index[i]] = U->data[j][index[i]] - xmult.re*U->data[j][index[k]];
18115
18116
18117 if( U->data[j][index[i]] != 0 )
18118 isFullRankTmp = TRUE;
18119 }
18120 if( !isFullRankTmp )
18121 {
18122 *IsFullRank = FALSE;
18123 if(index)
18124 free(index);
18125 if(scale)
18126 free(scale);
18127 if( !MTX_Zero(L) )
18128 {
18129 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18130 return FALSE;
18131 }
18132 if( !MTX_Zero(U) )
18133 {
18134 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18135 return FALSE;
18136 }
18137
18138 return TRUE;
18139 }
18140 U->data[k][index[i]] = 0.0;
18141 }
18142 }
18143 }
18144 else
18145 {
18146 double tmpre;
18147 double tmpim;
18148 MTX magMtx;
18149 MTX_Init( &magMtx );
18150
18151
18152 if( !MTX_Magnitude( src, &magMtx ) )
18153 {
18154 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
18155 MTX_Free( &magMtx );
18156 if(index)
18157 free(index);
18158 if(scale)
18159 free(scale);
18160 return FALSE;
18161 }
18162
18163
18164
18165
18166
18167
18168 for( i = 0; i < n; i++ )
18169 {
18170 index[i] = i;
18171 smax = 0;
18172 for( j = 0; j < n; j++ )
18173 {
18174 if( smax < magMtx.data[j][i] )
18175 {
18176 smax = magMtx.data[j][i];
18177 }
18178 }
18179 scale[i] = smax;
18180 if( scale[i] == 0.0 )
18181 {
18182 *IsFullRank = FALSE;
18183
18184 if(index)
18185 free(index);
18186 if(scale)
18187 free(scale);
18188 MTX_Free(&magMtx);
18189
18190 if( !MTX_Zero(L) )
18191 {
18192 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18193 return FALSE;
18194 }
18195 if( !MTX_Zero(U) )
18196 {
18197 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18198 return FALSE;
18199 }
18200 return TRUE;
18201 }
18202 }
18203
18204
18205
18206 for( k = 0; k < n - 1; k++ )
18207 {
18208
18209 j = 0;
18210 rmax = 0;
18211 for( i = k; i < n; i++ )
18212 {
18213 r = magMtx.data[k][index[i]] / scale[index[i]];
18214
18215 if( r >= rmax )
18216 {
18217 rmax = r;
18218 j = i;
18219 }
18220 }
18221
18222 tempi = index[j];
18223 index[j] = index[k];
18224 index[k] = tempi;
18225
18226 for( i = k + 1; i < n; i++ )
18227 {
18228
18229 MTX_static_quick_complex_divide(
18230 &(U->cplx[k][index[i]].re),
18231 &(U->cplx[k][index[i]].im),
18232 &(U->cplx[k][index[k]].re),
18233 &(U->cplx[k][index[k]].im),
18234 &(xmult.re),
18235 &(xmult.im)
18236 );
18237 L->cplx[k][index[i]].re = xmult.re;
18238 L->cplx[k][index[i]].im = xmult.im;
18239
18240 isFullRankTmp = FALSE;
18241 for( j = k + 1; j < n; j++ )
18242 {
18243
18244 tmpre = xmult.re * U->cplx[j][index[k]].re - xmult.im * U->cplx[j][index[k]].im;
18245 tmpim = xmult.re * U->cplx[j][index[k]].im + xmult.im * U->cplx[j][index[k]].re;
18246
18247 U->cplx[j][index[i]].re = U->cplx[j][index[i]].re - tmpre;
18248 U->cplx[j][index[i]].im = U->cplx[j][index[i]].im - tmpim;
18249
18250
18251 if( U->cplx[j][index[i]].re != 0 )
18252 isFullRankTmp = TRUE;
18253 if( U->cplx[j][index[i]].im != 0 )
18254 isFullRankTmp = TRUE;
18255 }
18256 if( !isFullRankTmp )
18257 {
18258 *IsFullRank = FALSE;
18259
18260 if(index)
18261 free(index);
18262 if(scale)
18263 free(scale);
18264 MTX_Free(&magMtx);
18265
18266 if( !MTX_Zero(L) )
18267 {
18268 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18269 return FALSE;
18270 }
18271 if( !MTX_Zero(U) )
18272 {
18273 MTX_ERROR_MSG( "MTX_Zero returned FALSE." );
18274 return FALSE;
18275 }
18276
18277 return TRUE;
18278 }
18279 U->cplx[k][index[i]].re = 0.0;
18280 U->cplx[k][index[i]].im = 0.0;
18281 }
18282 }
18283
18284 MTX_Free(&magMtx);
18285 }
18286
18287 for( j = 0; j < n; j++ )
18288 {
18289 P->data[index[j]][j] = 1.0;
18290
18291 if( L->isReal )
18292 L->data[j][index[j]] = 1.0;
18293 else
18294 L->cplx[j][index[j]].re = 1.0;
18295 }
18296
18297 if(index)
18298 free(index);
18299
18300 if(scale)
18301 free(scale);
18302
18303 if( !MTX_PreMultiply_Inplace( L, P ) )
18304 {
18305 MTX_ERROR_MSG( "MTX_PreMultiply_Inplace returned FALSE." );
18306 return FALSE;
18307 }
18308
18309 if( !MTX_PreMultiply_Inplace( U, P ) )
18310 {
18311 MTX_ERROR_MSG( "MTX_PreMultiply_Inplace returned FALSE." );
18312 return FALSE;
18313 }
18314
18315 *IsFullRank = TRUE;
18316
18317 return TRUE;
18318 }
18319
18320 BOOL MTX_IndexedValues( const MTX *src, const MTX *row_index, const MTX *col_index, MTX *dst )
18321 {
18322 unsigned i = 0;
18323 unsigned j = 0;
18324 unsigned row = 0;
18325 unsigned col = 0;
18326
18327 if( MTX_isNull( row_index ) )
18328 {
18329 MTX_ERROR_MSG( "NULL Matrix" );
18330 return FALSE;
18331 }
18332
18333 if( MTX_isNull( col_index ) )
18334 {
18335 MTX_ERROR_MSG( "NULL Matrix" );
18336 return FALSE;
18337 }
18338
18339 if( dst->isReal != src->isReal || dst->nrows != row_index->nrows || dst->ncols != col_index->nrows )
18340 {
18341 if( !MTX_Malloc( dst, row_index->nrows, col_index->nrows, src->isReal ) )
18342 {
18343 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
18344 return FALSE;
18345 }
18346 }
18347
18348 for( j = 0; j < col_index->nrows; j++ )
18349 {
18350 for( i = 0; i < row_index->nrows; i++ )
18351 {
18352 if( col_index->data[0][j] < 0 )
18353 {
18354 MTX_ERROR_MSG( "if( col_index->data[0][j] < 0 )" );
18355 return FALSE;
18356 }
18357 col = (unsigned) col_index->data[0][j];
18358 if( col >= src->ncols )
18359 {
18360 MTX_ERROR_MSG( "if( col >= src->ncols )" );
18361 return FALSE;
18362 }
18363
18364 if( row_index->data[0][i] < 0 )
18365 {
18366 MTX_ERROR_MSG( "if( row_index->data[0][i] < 0 )" );
18367 return FALSE;
18368 }
18369 row = (unsigned) row_index->data[0][i];
18370 if( row >= src->nrows )
18371 {
18372 MTX_ERROR_MSG( "if( row >= src->nrows )" );
18373 return FALSE;
18374 }
18375
18376 if( dst->isReal )
18377 {
18378 dst->data[j][i] = src->data[col][row];
18379 }
18380 else
18381 {
18382 dst->cplx[j][i].re = src->cplx[col][row].re;
18383 dst->cplx[j][i].im = src->cplx[col][row].im;
18384 }
18385 }
18386 }
18387
18388 return TRUE;
18389 }
18390
18391
18392 BOOL MTX_SetIndexedValues( MTX *dst, const MTX *row_index, const MTX *col_index, const MTX *src )
18393 {
18394 unsigned i = 0;
18395 unsigned j = 0;
18396 unsigned row = 0;
18397 unsigned col = 0;
18398 unsigned maxrow = 0;
18399 unsigned maxcol = 0;
18400 double maxrow_d = 0.0;
18401 double maxcol_d = 0.0;
18402 double dumd;
18403
18404 if( MTX_isNull( row_index ) )
18405 {
18406 MTX_ERROR_MSG( "NULL Matrix" );
18407 return FALSE;
18408 }
18409
18410 if( MTX_isNull( col_index ) )
18411 {
18412 MTX_ERROR_MSG( "NULL Matrix" );
18413 return FALSE;
18414 }
18415
18416 if( MTX_isNull( src ) )
18417 {
18418 MTX_ERROR_MSG( "NULL Matrix" );
18419 return FALSE;
18420 }
18421
18422
18423 if( row_index->nrows != src->nrows )
18424 {
18425 MTX_ERROR_MSG( "if( row_index->nrows != src->nrows )" );
18426 return FALSE;
18427 }
18428 if( col_index->nrows != src->ncols )
18429 {
18430 MTX_ERROR_MSG( "if( col_index->nrows != src->ncols )" );
18431 return FALSE;
18432 }
18433
18434
18435 if( !MTX_MaxColumn( row_index, 0, &maxrow_d, &dumd ) )
18436 {
18437 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
18438 return FALSE;
18439 }
18440 if( maxrow_d < 0.0 )
18441 {
18442 MTX_ERROR_MSG( "if( maxrow_d < 0.0 )" );
18443 return FALSE;
18444 }
18445 maxrow = (unsigned) maxrow_d;
18446 if( !MTX_MaxColumn( col_index, 0, &maxcol_d, &dumd ) )
18447 {
18448 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
18449 return FALSE;
18450 }
18451 if( maxcol_d < 0 )
18452 {
18453 MTX_ERROR_MSG( "if( maxcol_d < 0 )" );
18454 return FALSE;
18455 }
18456 maxcol = (unsigned) maxcol_d;
18457 if( maxrow >= dst->nrows )
18458 {
18459 if( maxcol >= dst->ncols )
18460 {
18461 if( !MTX_Redim( dst, maxrow+1, maxcol+1 ) )
18462 {
18463 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
18464 return FALSE;
18465 }
18466 }
18467 else
18468 {
18469 if( !MTX_Redim( dst, maxrow+1, dst->ncols ) )
18470 {
18471 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
18472 return FALSE;
18473 }
18474 }
18475 }
18476 else
18477 {
18478 if( maxcol >= dst->ncols )
18479 {
18480 if( !MTX_Redim( dst, dst->nrows, maxcol+1 ) )
18481 {
18482 MTX_ERROR_MSG( "MTX_Redim returned FALSE." );
18483 return FALSE;
18484 }
18485 }
18486 }
18487
18488 if( !src->isReal && dst->isReal )
18489 {
18490 if( !MTX_ConvertRealToComplex( dst ) )
18491 {
18492 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
18493 return FALSE;
18494 }
18495 }
18496
18497 for( j = 0; j < col_index->nrows; j++ )
18498 {
18499 for( i = 0; i < row_index->nrows; i++ )
18500 {
18501 if( col_index->data[0][j] < 0 )
18502 {
18503 MTX_ERROR_MSG( "if( col_index->data[0][j] < 0 )" );
18504 return FALSE;
18505 }
18506 col = (unsigned) col_index->data[0][j];
18507 if( col >= dst->ncols )
18508 {
18509 MTX_ERROR_MSG( "if( col >= dst->ncols )" );
18510 return FALSE;
18511 }
18512
18513 if( row_index->data[0][i] < 0 )
18514 {
18515 MTX_ERROR_MSG( "if( row_index->data[0][i] < 0 )" );
18516 return FALSE;
18517 }
18518 row = (unsigned) row_index->data[0][i];
18519 if( row >= dst->nrows )
18520 {
18521 MTX_ERROR_MSG( "if( row >= dst->nrows )" );
18522 return FALSE;
18523 }
18524
18525 if( dst->isReal )
18526 {
18527 dst->data[col][row] = src->data[j][i];
18528 }
18529 else
18530 {
18531 if( src->isReal )
18532 {
18533 dst->cplx[col][row].re = src->data[j][i];
18534 dst->cplx[col][row].im = 0.0;
18535 }
18536 else
18537 {
18538 dst->cplx[col][row].re = src->cplx[j][i].re;
18539 dst->cplx[col][row].im = src->cplx[j][i].im;
18540 }
18541 }
18542 }
18543 }
18544
18545 return TRUE;
18546 }
18547
18548 BOOL MTX_FFT2( const MTX *src, MTX *dst )
18549 {
18550 MTX M;
18551 MTX W;
18552 MTX_Init( &M );
18553 MTX_Init( &W );
18554
18555 if( MTX_isNull( src ) )
18556 {
18557 MTX_ERROR_MSG( "src is a NULL matrix." );
18558 return FALSE;
18559 }
18560 if( dst == NULL )
18561 {
18562 MTX_ERROR_MSG( "dst is NULL." );
18563 return FALSE;
18564 }
18565
18566 if( !MTX_FFT( src, dst ) )
18567 {
18568 MTX_ERROR_MSG( "MTX_FFT returned FALSE." );
18569 MTX_Free( &M );
18570 MTX_Free( &W );
18571 return FALSE;
18572 }
18573 if( !MTX_Transpose( dst, &M ) )
18574 {
18575 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18576 MTX_Free( &M );
18577 MTX_Free( &W );
18578 return FALSE;
18579 }
18580 if( !MTX_FFT( &M, &W ) )
18581 {
18582 MTX_ERROR_MSG( "MTX_FFT returned FALSE." );
18583 MTX_Free( &M );
18584 MTX_Free( &W );
18585 return FALSE;
18586 }
18587 if( !MTX_Transpose( &W, dst ) )
18588 {
18589 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18590 MTX_Free( &M );
18591 MTX_Free( &W );
18592 return FALSE;
18593 }
18594 MTX_Free( &M );
18595 MTX_Free( &W );
18596 return TRUE;
18597 }
18598
18599 BOOL MTX_FFT2_Inplace( MTX *src )
18600 {
18601 MTX M;
18602 MTX W;
18603 MTX_Init( &M );
18604 MTX_Init( &W );
18605
18606 if( MTX_isNull( src ) )
18607 {
18608 MTX_ERROR_MSG( "src is a NULL matrix." );
18609 return FALSE;
18610 }
18611
18612 if( !MTX_FFT_Inplace( src ) )
18613 {
18614 MTX_ERROR_MSG( "MTX_FFT returned FALSE." );
18615 MTX_Free( &M );
18616 MTX_Free( &W );
18617 return FALSE;
18618 }
18619 if( !MTX_Transpose( src, &M ) )
18620 {
18621 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18622 MTX_Free( &M );
18623 MTX_Free( &W );
18624 return FALSE;
18625 }
18626 if( !MTX_FFT( &M, &W ) )
18627 {
18628 MTX_ERROR_MSG( "MTX_FFT returned FALSE." );
18629 MTX_Free( &M );
18630 MTX_Free( &W );
18631 return FALSE;
18632 }
18633 if( !MTX_Transpose( &W, src ) )
18634 {
18635 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18636 MTX_Free( &M );
18637 MTX_Free( &W );
18638 return FALSE;
18639 }
18640 MTX_Free( &M );
18641 MTX_Free( &W );
18642 return TRUE;
18643 }
18644
18645
18646 BOOL MTX_IFFT2( const MTX *src, MTX *dst )
18647 {
18648 MTX M;
18649 MTX W;
18650 MTX_Init( &M );
18651 MTX_Init( &W );
18652
18653 if( MTX_isNull( src ) )
18654 {
18655 MTX_ERROR_MSG( "src is a NULL matrix." );
18656 return FALSE;
18657 }
18658 if( dst == NULL )
18659 {
18660 MTX_ERROR_MSG( "dst is NULL." );
18661 return FALSE;
18662 }
18663
18664 if( !MTX_IFFT( src, dst ) )
18665 {
18666 MTX_ERROR_MSG( "MTX_IFFT returned FALSE." );
18667 MTX_Free( &M );
18668 MTX_Free( &W );
18669 return FALSE;
18670 }
18671 if( !MTX_Transpose( dst, &M ) )
18672 {
18673 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18674 MTX_Free( &M );
18675 MTX_Free( &W );
18676 return FALSE;
18677 }
18678 if( !MTX_IFFT( &M, &W ) )
18679 {
18680 MTX_ERROR_MSG( "MTX_IFFT returned FALSE." );
18681 MTX_Free( &M );
18682 MTX_Free( &W );
18683 return FALSE;
18684 }
18685 if( !MTX_Transpose( &W, dst ) )
18686 {
18687 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18688 MTX_Free( &M );
18689 MTX_Free( &W );
18690 return FALSE;
18691 }
18692 MTX_Free( &M );
18693 MTX_Free( &W );
18694 return TRUE;
18695 }
18696
18697
18698 BOOL MTX_IFFT2_Inplace( MTX *src )
18699 {
18700 MTX M;
18701 MTX W;
18702 MTX_Init( &M );
18703 MTX_Init( &W );
18704
18705 if( MTX_isNull( src ) )
18706 {
18707 MTX_ERROR_MSG( "src is a NULL matrix." );
18708 return FALSE;
18709 }
18710
18711 if( !MTX_IFFT_Inplace( src ) )
18712 {
18713 MTX_ERROR_MSG( "MTX_IFFT returned FALSE." );
18714 MTX_Free( &M );
18715 MTX_Free( &W );
18716 return FALSE;
18717 }
18718 if( !MTX_Transpose( src, &M ) )
18719 {
18720 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18721 MTX_Free( &M );
18722 MTX_Free( &W );
18723 return FALSE;
18724 }
18725 if( !MTX_IFFT( &M, &W ) )
18726 {
18727 MTX_ERROR_MSG( "MTX_IFFT returned FALSE." );
18728 MTX_Free( &M );
18729 MTX_Free( &W );
18730 return FALSE;
18731 }
18732 if( !MTX_Transpose( &W, src ) )
18733 {
18734 MTX_ERROR_MSG( "MTX_Transpose returned FALSE." );
18735 MTX_Free( &M );
18736 MTX_Free( &W );
18737 return FALSE;
18738 }
18739 MTX_Free( &M );
18740 MTX_Free( &W );
18741 return TRUE;
18742 }
18743
18744
18745 BOOL MTX_FFT( const MTX *src, MTX *dst )
18746 {
18747 return MTX_static_fft( src, dst, TRUE );
18748 }
18749
18750 BOOL MTX_IFFT( const MTX *src, MTX *dst )
18751 {
18752 return MTX_static_fft( src, dst, FALSE );
18753 }
18754
18755 BOOL MTX_FFT_Inplace( MTX *src )
18756 {
18757 return MTX_static_fft_inplace( src, TRUE );
18758 }
18759
18760 BOOL MTX_IFFT_Inplace( MTX *src )
18761 {
18762 return MTX_static_fft_inplace( src, FALSE );
18763 }
18764
18765
18766
18767
18768
18769
18770 BOOL MTX_static_fft(
18771 const MTX *src,
18772 MTX *dst,
18773 BOOL isFwd
18774 )
18775 {
18776
18777 if( !MTX_Copy( src, dst ) )
18778 {
18779 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
18780 return FALSE;
18781 }
18782
18783
18784 return MTX_static_fft_inplace( dst, isFwd );
18785
18786 }
18787
18788
18789
18790
18791
18792
18793 BOOL MTX_static_fft_inplace(
18794 MTX *src,
18795 BOOL isFwd
18796 )
18797 {
18798 unsigned j = 0;
18799 double length = 0.0;
18800
18801
18802
18803 kiss_fft_cfg fft_config;
18804
18805
18806
18807 kiss_fft_cpx *pKissComplexData = NULL;
18808
18809
18810 length = src->nrows;
18811
18812
18813
18814 if( src->isReal )
18815 {
18816 if( !MTX_ConvertRealToComplex( src ) )
18817 {
18818 MTX_ERROR_MSG( "MTX_ConvertRealToComplex returned FALSE." );
18819 return FALSE;
18820 }
18821 }
18822
18823
18824 if( length == 1 )
18825 {
18826 return TRUE;
18827 }
18828
18829
18830
18831 if( isFwd )
18832 {
18833
18834 fft_config = kiss_fft_alloc( (unsigned)length, 0, 0, 0 );
18835 }
18836 else
18837 {
18838
18839 fft_config = kiss_fft_alloc( (unsigned)length, 1, 0, 0 );
18840 }
18841 if( fft_config == NULL )
18842 {
18843 MTX_ERROR_MSG( "if( fft_config == NULL )" );
18844 return FALSE;
18845 }
18846
18847
18848 for( j = 0; j < src->ncols; j++ )
18849 {
18850
18851
18852 pKissComplexData = (kiss_fft_cpx *)src->cplx[j];
18853
18854
18855 kiss_fft( fft_config, pKissComplexData, pKissComplexData );
18856 }
18857
18858 if( !isFwd )
18859 {
18860
18861 if( !MTX_Multiply_Scalar( src, 1.0/length ) )
18862 {
18863 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
18864 return FALSE;
18865 }
18866 }
18867
18868
18869 if( fft_config )
18870 {
18871 kiss_fft_free( fft_config );
18872 fft_config = NULL;
18873 }
18874
18875
18876 return TRUE;
18877 }
18878
18879
18880 BOOL MTX_sin( MTX *src )
18881 {
18882 unsigned i = 0;
18883 unsigned j = 0;
18884 double re;
18885 double im;
18886
18887 if( MTX_isNull( src ) )
18888 {
18889 MTX_ERROR_MSG( "NULL Matrix" );
18890 return FALSE;
18891 }
18892
18893
18894 if( src->isReal )
18895 {
18896 for( j = 0; j < src->ncols; j++ )
18897 {
18898 for( i = 0; i < src->nrows; i++ )
18899 {
18900 src->data[j][i] = sin( src->data[j][i] );
18901 }
18902 }
18903 }
18904 else
18905 {
18906 for( j = 0; j < src->ncols; j++ )
18907 {
18908 for( i = 0; i < src->nrows; i++ )
18909 {
18910 re = src->cplx[j][i].re;
18911 im = src->cplx[j][i].im;
18912 src->cplx[j][i].re = sin(re)*cosh(im);
18913 src->cplx[j][i].im = cos(re)*sinh(im);
18914 }
18915 }
18916 }
18917 return TRUE;
18918
18919 }
18920
18921 BOOL MTX_sinc( MTX *src )
18922 {
18923 unsigned i = 0;
18924 unsigned j = 0;
18925 MTX copysrc;
18926 double re = 0.0;
18927 double im = 0.0;
18928
18929 MTX_Init( ©src );
18930
18931 if( MTX_isNull( src ) )
18932 {
18933 MTX_ERROR_MSG( "NULL Matrix" );
18934 return FALSE;
18935 }
18936
18937 if( !MTX_Multiply_Scalar( src, PI ) )
18938 {
18939 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
18940 return FALSE;
18941 }
18942
18943
18944
18945 if( !MTX_Copy( src, ©src ) )
18946 {
18947 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
18948 return FALSE;
18949 }
18950
18951
18952 if( !MTX_sin( src ) )
18953 {
18954 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
18955 MTX_Free( ©src );
18956 return FALSE;
18957 }
18958
18959 if( src->isReal )
18960 {
18961 for( j = 0; j < src->ncols; j++ )
18962 {
18963 for( i = 0; i < src->nrows; i++ )
18964 {
18965 if( copysrc.data[j][i] == 0.0 )
18966 src->data[j][i] = 1.0;
18967 else
18968 src->data[j][i] /= copysrc.data[j][i];
18969 }
18970 }
18971 }
18972 else
18973 {
18974 for( j = 0; j < src->ncols; j++ )
18975 {
18976 for( i = 0; i < src->nrows; i++ )
18977 {
18978 if( copysrc.cplx[j][i].re == 0.0 && copysrc.cplx[j][i].im == 0.0 )
18979 {
18980 src->cplx[j][i].re = 1.0;
18981 src->cplx[j][i].im = 0.0;
18982 }
18983 else
18984 {
18985 MTX_static_quick_complex_divide( &src->cplx[j][i].re, &src->cplx[j][i].im, ©src.cplx[j][i].re, ©src.cplx[j][i].im, &re, &im );
18986 src->cplx[j][i].re = re;
18987 src->cplx[j][i].im = im;
18988 }
18989 }
18990 }
18991 }
18992
18993 MTX_Free(©src);
18994 return TRUE;
18995 }
18996
18997 BOOL MTX_sinh( MTX *src )
18998 {
18999 unsigned i = 0;
19000 unsigned j = 0;
19001
19002
19003 if( MTX_isNull( src ) )
19004 {
19005 MTX_ERROR_MSG( "NULL Matrix" );
19006 return FALSE;
19007 }
19008
19009
19010 if( src->isReal )
19011 {
19012 for( j = 0; j < src->ncols; j++ )
19013 {
19014 for( i = 0; i < src->nrows; i++ )
19015 {
19016 src->data[j][i] = sinh( src->data[j][i] );
19017 }
19018 }
19019 }
19020 else
19021 {
19022
19023 MTX epX;
19024 MTX emX;
19025
19026 MTX_Init( &epX );
19027 MTX_Init( &emX );
19028
19029 if( !MTX_Copy( src, &epX ) )
19030 {
19031 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19032 MTX_Free(&epX);
19033 return FALSE;
19034 }
19035 if( !MTX_Copy( src, &emX ) )
19036 {
19037 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19038 MTX_Free(&epX);
19039 MTX_Free(&emX);
19040 return FALSE;
19041 }
19042 if( !MTX_Negate( &emX ) )
19043 {
19044 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
19045 MTX_Free(&epX);
19046 MTX_Free(&emX);
19047 return FALSE;
19048 }
19049
19050 if( !MTX_Exp( &epX ) )
19051 {
19052 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
19053 MTX_Free(&epX);
19054 MTX_Free(&emX);
19055 return FALSE;
19056 }
19057 if( !MTX_Exp( &emX ) )
19058 {
19059 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
19060 MTX_Free(&epX);
19061 MTX_Free(&emX);
19062 return FALSE;
19063 }
19064
19065 if( !MTX_Subtract( src, &epX, &emX ) )
19066 {
19067 MTX_ERROR_MSG( "MTX_Subtract returned FALSE." );
19068 MTX_Free(&epX);
19069 MTX_Free(&emX);
19070 return FALSE;
19071 }
19072 if( !MTX_Multiply_Scalar( src, 0.5 ) )
19073 {
19074 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
19075 MTX_Free(&epX);
19076 MTX_Free(&emX);
19077 return FALSE;
19078 }
19079
19080 MTX_Free(&epX);
19081 MTX_Free(&emX);
19082 }
19083 return TRUE;
19084 }
19085
19086 BOOL MTX_asinh( MTX *src )
19087 {
19088
19089 MTX sqrtOnePlusX2;
19090 MTX_Init( &sqrtOnePlusX2 );
19091
19092 if( MTX_isNull( src ) )
19093 {
19094 MTX_ERROR_MSG( "NULL Matrix" );
19095 return FALSE;
19096 }
19097
19098
19099 if( !MTX_Copy(src,&sqrtOnePlusX2) )
19100 {
19101 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19102 MTX_Free(&sqrtOnePlusX2);
19103 return FALSE;
19104 }
19105 if( !MTX_Sqr(&sqrtOnePlusX2) )
19106 {
19107 MTX_ERROR_MSG( "MTX_Sqr returned FALSE." );
19108 MTX_Free(&sqrtOnePlusX2);
19109 return FALSE;
19110 }
19111 if( !MTX_Increment(&sqrtOnePlusX2) )
19112 {
19113 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
19114 MTX_Free(&sqrtOnePlusX2);
19115 return FALSE;
19116 }
19117 if( !MTX_Sqrt(&sqrtOnePlusX2) )
19118 {
19119 MTX_ERROR_MSG( "MTX_Sqrt returned FALSE." );
19120 MTX_Free(&sqrtOnePlusX2);
19121 return FALSE;
19122 }
19123 if( !MTX_Add_Inplace( src, &sqrtOnePlusX2 ) )
19124 {
19125 MTX_ERROR_MSG( "MTX_Add_Inplace returned FALSE." );
19126 MTX_Free(&sqrtOnePlusX2);
19127 return FALSE;
19128 }
19129 if( !MTX_Ln( src ) )
19130 {
19131 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
19132 MTX_Free(&sqrtOnePlusX2);
19133 return FALSE;
19134 }
19135
19136 MTX_Free(&sqrtOnePlusX2);
19137 return TRUE;
19138 }
19139
19140
19141 BOOL MTX_cos( MTX *src )
19142 {
19143 unsigned i = 0;
19144 unsigned j = 0;
19145 double re;
19146 double im;
19147
19148 if( MTX_isNull( src ) )
19149 {
19150 MTX_ERROR_MSG( "NULL Matrix" );
19151 return FALSE;
19152 }
19153
19154
19155 if( src->isReal )
19156 {
19157 for( j = 0; j < src->ncols; j++ )
19158 {
19159 for( i = 0; i < src->nrows; i++ )
19160 {
19161 src->data[j][i] = cos( src->data[j][i] );
19162 }
19163 }
19164 }
19165 else
19166 {
19167 for( j = 0; j < src->ncols; j++ )
19168 {
19169 for( i = 0; i < src->nrows; i++ )
19170 {
19171 re = src->cplx[j][i].re;
19172 im = src->cplx[j][i].im;
19173 src->cplx[j][i].re = cos(re)*cosh(im);
19174 src->cplx[j][i].im = -sin(re)*sinh(im);
19175 }
19176 }
19177 }
19178 return TRUE;
19179
19180 }
19181
19182 BOOL MTX_cosh( MTX *src )
19183 {
19184 unsigned i = 0;
19185 unsigned j = 0;
19186
19187 if( MTX_isNull( src ) )
19188 {
19189 MTX_ERROR_MSG( "NULL Matrix" );
19190 return FALSE;
19191 }
19192
19193 if( src->isReal )
19194 {
19195 for( j = 0; j < src->ncols; j++ )
19196 {
19197 for( i = 0; i < src->nrows; i++ )
19198 {
19199 src->data[j][i] = cosh( src->data[j][i] );
19200 }
19201 }
19202 return TRUE;
19203 }
19204 else
19205 {
19206
19207 MTX epX;
19208 MTX emX;
19209
19210 MTX_Init( &epX );
19211 MTX_Init( &emX );
19212
19213 if( !MTX_Copy( src, &epX ) )
19214 {
19215 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19216 MTX_Free( &epX );
19217 MTX_Free( &emX );
19218 return FALSE;
19219 }
19220 if( !MTX_Copy( src, &emX ) )
19221 {
19222 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19223 MTX_Free( &epX );
19224 MTX_Free( &emX );
19225 return FALSE;
19226 }
19227 if( !MTX_Negate( &emX ) )
19228 {
19229 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
19230 MTX_Free( &epX );
19231 MTX_Free( &emX );
19232 return FALSE;
19233 }
19234
19235 if( !MTX_Exp( &epX ) )
19236 {
19237 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
19238 MTX_Free( &epX );
19239 MTX_Free( &emX );
19240 return FALSE;
19241 }
19242 if( !MTX_Exp( &emX ) )
19243 {
19244 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
19245 MTX_Free( &epX );
19246 MTX_Free( &emX );
19247 return FALSE;
19248 }
19249
19250 if( !MTX_Add( src, &epX, &emX ) )
19251 {
19252 MTX_ERROR_MSG( "MTX_Add returned FALSE." );
19253 MTX_Free( &epX );
19254 MTX_Free( &emX );
19255 return FALSE;
19256 }
19257 if( !MTX_Multiply_Scalar( src, 0.5 ) )
19258 {
19259 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
19260 MTX_Free( &epX );
19261 MTX_Free( &emX );
19262 return FALSE;
19263 }
19264
19265 MTX_Free(&epX);
19266 MTX_Free(&emX);
19267 }
19268 return TRUE;
19269 }
19270
19271 BOOL MTX_acosh( MTX *src )
19272 {
19273
19274 MTX sXp1;
19275 MTX sXm1;
19276 MTX_Init( &sXp1 );
19277 MTX_Init( &sXm1 );
19278
19279 if( MTX_isNull( src ) )
19280 {
19281 MTX_ERROR_MSG( "NULL Matrix" );
19282 return FALSE;
19283 }
19284
19285
19286 if( !MTX_Copy(src,&sXp1) )
19287 {
19288 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19289 MTX_Free(&sXp1);
19290 return FALSE;
19291 }
19292 if( !MTX_Copy(src,&sXm1) )
19293 {
19294 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19295 MTX_Free(&sXp1);
19296 MTX_Free(&sXm1);
19297 return FALSE;
19298 }
19299
19300
19301
19302 if( !MTX_Increment(&sXp1) )
19303 {
19304 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
19305 MTX_Free(&sXp1);
19306 MTX_Free(&sXm1);
19307 return FALSE;
19308 }
19309 if( !MTX_Decrement(&sXm1) )
19310 {
19311 MTX_ERROR_MSG( "MTX_Decrement returned FALSE." );
19312 MTX_Free(&sXp1);
19313 MTX_Free(&sXm1);
19314 return FALSE;
19315 }
19316 if( !MTX_Sqrt(&sXp1) )
19317 {
19318 MTX_ERROR_MSG( "MTX_Sqrt returned FALSE." );
19319 MTX_Free(&sXp1);
19320 MTX_Free(&sXm1);
19321 return FALSE;
19322 }
19323 if( !MTX_Sqrt(&sXm1) )
19324 {
19325 MTX_ERROR_MSG( "MTX_Sqrt returned FALSE." );
19326 MTX_Free(&sXp1);
19327 MTX_Free(&sXm1);
19328 return FALSE;
19329 }
19330 if( !MTX_DotMultiply_Inplace( &sXp1, &sXm1 ) )
19331 {
19332 MTX_ERROR_MSG( "MTX_DotMultiply_Inplace returned FALSE." );
19333 MTX_Free(&sXp1);
19334 MTX_Free(&sXm1);
19335 return FALSE;
19336 }
19337 if( !MTX_Add_Inplace( src, &sXp1 ) )
19338 {
19339 MTX_ERROR_MSG( "MTX_Add_Inplace returned FALSE." );
19340 MTX_Free(&sXp1);
19341 MTX_Free(&sXm1);
19342 return FALSE;
19343 }
19344 MTX_Free(&sXp1);
19345 MTX_Free(&sXm1);
19346
19347 if( !MTX_Ln( src ) )
19348 {
19349 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
19350 return FALSE;
19351 }
19352 return TRUE;
19353 }
19354
19355
19356 BOOL MTX_tan( MTX *src )
19357 {
19358 unsigned i = 0;
19359 unsigned j = 0;
19360
19361 if( MTX_isNull( src ) )
19362 {
19363 MTX_ERROR_MSG( "NULL Matrix" );
19364 return FALSE;
19365 }
19366
19367 if( src->isReal )
19368 {
19369 for( j = 0; j < src->ncols; j++ )
19370 {
19371 for( i = 0; i < src->nrows; i++ )
19372 {
19373 src->data[j][i] = tan( src->data[j][i] );
19374 }
19375 }
19376 return TRUE;
19377 }
19378 else
19379 {
19380 MTX cos_src;
19381 MTX_Init(&cos_src);
19382
19383 if( !MTX_Copy(src,&cos_src) )
19384 {
19385 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19386 MTX_Free(&cos_src);
19387 return FALSE;
19388 }
19389
19390 if( !MTX_cos(&cos_src) )
19391 {
19392 MTX_ERROR_MSG( "MTX_cos returned FALSE." );
19393 MTX_Free(&cos_src);
19394 return FALSE;
19395 }
19396
19397 if( !MTX_sin(src) )
19398 {
19399 MTX_ERROR_MSG( "MTX_sin returned FALSE." );
19400 MTX_Free(&cos_src);
19401 return FALSE;
19402 }
19403
19404 if( !MTX_DotDivide_Inplace( src, &cos_src ) )
19405 {
19406 MTX_ERROR_MSG( "MTX_DotDivide_Inplace returned FALSE." );
19407 MTX_Free(&cos_src);
19408 return FALSE;
19409 }
19410
19411 MTX_Free(&cos_src);
19412 }
19413 return TRUE;
19414 }
19415
19416 BOOL MTX_tanh( MTX *src )
19417 {
19418 unsigned i = 0;
19419 unsigned j = 0;
19420
19421 if( MTX_isNull( src ) )
19422 {
19423 MTX_ERROR_MSG( "NULL Matrix" );
19424 return FALSE;
19425 }
19426
19427 if( src->isReal )
19428 {
19429 for( j = 0; j < src->ncols; j++ )
19430 {
19431 for( i = 0; i < src->nrows; i++ )
19432 {
19433 src->data[j][i] = tanh( src->data[j][i] );
19434 }
19435 }
19436 return TRUE;
19437 }
19438 else
19439 {
19440
19441 MTX e2Xm1;
19442 MTX e2Xp1;
19443
19444 MTX_Init( &e2Xm1 );
19445 MTX_Init( &e2Xp1 );
19446
19447 if( !MTX_Copy( src, &e2Xm1 ) )
19448 {
19449 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19450 MTX_Free( &e2Xm1 );
19451 MTX_Free( &e2Xp1 );
19452 return FALSE;
19453 }
19454 if( !MTX_Multiply_Scalar( &e2Xm1, 2.0 ) )
19455 {
19456 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
19457 MTX_Free( &e2Xm1 );
19458 MTX_Free( &e2Xp1 );
19459 return FALSE;
19460 }
19461
19462 if( !MTX_Exp( &e2Xm1 ) )
19463 {
19464 MTX_ERROR_MSG( "MTX_Exp returned FALSE." );
19465 MTX_Free( &e2Xm1 );
19466 MTX_Free( &e2Xp1 );
19467 return FALSE;
19468 }
19469 if( !MTX_Copy( &e2Xm1, &e2Xp1 ) )
19470 {
19471 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19472 MTX_Free( &e2Xm1 );
19473 MTX_Free( &e2Xp1 );
19474 return FALSE;
19475 }
19476
19477 if( !MTX_Decrement( &e2Xm1 ) )
19478 {
19479 MTX_ERROR_MSG( "MTX_Decrement returned FALSE." );
19480 MTX_Free( &e2Xm1 );
19481 MTX_Free( &e2Xp1 );
19482 return FALSE;
19483 }
19484 if( !MTX_Increment( &e2Xp1 ) )
19485 {
19486 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
19487 MTX_Free( &e2Xm1 );
19488 MTX_Free( &e2Xp1 );
19489 return FALSE;
19490 }
19491
19492 if( !MTX_DotDivide_Inplace( &e2Xm1, &e2Xp1 ) )
19493 {
19494 MTX_ERROR_MSG( "MTX_DotDivide_Inplace returned FALSE." );
19495 MTX_Free( &e2Xm1 );
19496 MTX_Free( &e2Xp1 );
19497 return FALSE;
19498 }
19499
19500 if( !MTX_Copy( &e2Xm1, src ) )
19501 {
19502 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19503 MTX_Free( &e2Xm1 );
19504 MTX_Free( &e2Xp1 );
19505 return FALSE;
19506 }
19507
19508 MTX_Free(&e2Xm1);
19509 MTX_Free(&e2Xp1);
19510 }
19511 return TRUE;
19512 }
19513
19514
19515 BOOL MTX_atanh( MTX *src )
19516 {
19517
19518 MTX oneMx;
19519
19520 if( MTX_isNull( src ) )
19521 {
19522 MTX_ERROR_MSG( "NULL Matrix" );
19523 return FALSE;
19524 }
19525
19526
19527
19528 MTX_Init( &oneMx );
19529
19530 if( !MTX_Copy( src, &oneMx ) )
19531 {
19532 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19533 return FALSE;
19534 }
19535 if( !MTX_Increment( src ) )
19536 {
19537 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
19538 MTX_Free(&oneMx);
19539 return FALSE;
19540 }
19541 if( !MTX_Negate( &oneMx ) )
19542 {
19543 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
19544 MTX_Free(&oneMx);
19545 return FALSE;
19546 }
19547 if( !MTX_Increment( &oneMx ) )
19548 {
19549 MTX_ERROR_MSG( "MTX_Increment returned FALSE." );
19550 MTX_Free(&oneMx);
19551 return FALSE;
19552 }
19553
19554 if( !MTX_DotDivide_Inplace( src, &oneMx ) )
19555 {
19556 MTX_ERROR_MSG( "MTX_DotDivide_Inplace returned FALSE." );
19557 MTX_Free(&oneMx);
19558 return FALSE;
19559 }
19560
19561 MTX_Free(&oneMx);
19562
19563 if( !MTX_Ln(src) )
19564 {
19565 MTX_ERROR_MSG( "MTX_Ln returned FALSE." );
19566 return FALSE;
19567 }
19568 if( !MTX_Multiply_Scalar( src, 0.5 ) )
19569 {
19570 MTX_ERROR_MSG( "MTX_Multiply_Scalar returned FALSE." );
19571 return FALSE;
19572 }
19573
19574 return TRUE;
19575 }
19576
19577
19578 BOOL MTX_cot( MTX *src )
19579 {
19580 if( !MTX_tan( src ) )
19581 {
19582 MTX_ERROR_MSG( "MTX_tan returned FALSE." );
19583 return FALSE;
19584 }
19585
19586 if( !MTX_Inv( src ) )
19587 {
19588 MTX_ERROR_MSG( "MTX_Inv returned FALSE." );
19589 return FALSE;
19590 }
19591
19592 return TRUE;
19593 }
19594
19595 BOOL MTX_coth( MTX *src )
19596 {
19597 if( !MTX_tanh( src ) )
19598 {
19599 MTX_ERROR_MSG( "MTX_tanh returned FALSE." );
19600 return FALSE;
19601 }
19602
19603 if( !MTX_Inv( src ) )
19604 {
19605 MTX_ERROR_MSG( "MTX_Inv returned FALSE." );
19606 return FALSE;
19607 }
19608
19609 return TRUE;
19610 }
19611
19612 BOOL MTX_Inv( MTX *src )
19613 {
19614 unsigned i = 0;
19615 unsigned j = 0;
19616
19617 if( MTX_isNull(src) )
19618 {
19619 MTX_ERROR_MSG( "NULL Matrix" );
19620 return FALSE;
19621 }
19622
19623 if( src->isReal )
19624 {
19625 for( j = 0; j < src->ncols; j++ )
19626 {
19627 for( i = 0; i < src->nrows; i++ )
19628 {
19629 src->data[j][i] = 1.0 / src->data[j][i];
19630 }
19631 }
19632 }
19633 else
19634 {
19635
19636 MTX magSrc;
19637 MTX_Init(&magSrc);
19638
19639 if( !MTX_Magnitude(src,&magSrc) )
19640 {
19641 MTX_ERROR_MSG( "MTX_Magnitude returned FALSE." );
19642 MTX_Free(&magSrc);
19643 return FALSE;
19644 }
19645 if( !MTX_Sqr(&magSrc) )
19646 {
19647 MTX_ERROR_MSG( "MTX_Sqr returned FALSE." );
19648 MTX_Free(&magSrc);
19649 return FALSE;
19650 }
19651 if( !MTX_Conjugate(src) )
19652 {
19653 MTX_ERROR_MSG( "MTX_Conjugate returned FALSE." );
19654 MTX_Free(&magSrc);
19655 return FALSE;
19656 }
19657 if( !MTX_DotDivide_Inplace(src,&magSrc) )
19658 {
19659 MTX_ERROR_MSG( "MTX_DotDivide_Inplace returned FALSE." );
19660 MTX_Free(&magSrc);
19661 return FALSE;
19662 }
19663
19664 MTX_Free(&magSrc);
19665 }
19666 return TRUE;
19667 }
19668
19669
19670 BOOL MTX_Colon( MTX *dst, const double start, const double increment, const double end )
19671 {
19672 unsigned i = 0;
19673 unsigned nrows = 0;
19674
19675 if( increment == 0.0 )
19676 {
19677 MTX_ERROR_MSG( "if( increment == 0.0 )" );
19678 return FALSE;
19679 }
19680
19681 if( increment > 0.0 )
19682 {
19683 if( end < start )
19684 {
19685 MTX_ERROR_MSG( "if( end < start )" );
19686 return FALSE;
19687 }
19688
19689
19690 nrows = (unsigned)floor( (end-start)/increment ) + 1;
19691
19692 if( !MTX_Malloc( dst, nrows, 1, TRUE ) )
19693 {
19694 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
19695 return FALSE;
19696 }
19697
19698 for( i = 0; i < nrows; i++ )
19699 {
19700 dst->data[0][i] = start + i*increment;
19701 }
19702 }
19703 else
19704 {
19705 if( start < end )
19706 {
19707 MTX_ERROR_MSG( "if( start < end )" );
19708 return FALSE;
19709 }
19710
19711
19712 nrows = abs((unsigned)floor( (end-start)/increment )) + 1;
19713
19714 if( !MTX_Malloc( dst, nrows, 1, TRUE ) )
19715 {
19716 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
19717 return FALSE;
19718 }
19719
19720 for( i = 0; i < nrows; i++ )
19721 {
19722 dst->data[0][i] = start + i*increment;
19723 }
19724 }
19725
19726 return TRUE;
19727 }
19728
19729 BOOL MTX_RemoveRowsAndColumns(
19730 MTX *src,
19731 const unsigned nrows,
19732 const unsigned rows[],
19733 const unsigned ncols,
19734 const unsigned cols[]
19735 )
19736 {
19737 unsigned i = 0;
19738 unsigned j = 0;
19739 unsigned k = 0;
19740 unsigned col_index = 0;
19741 unsigned row_index = 0;
19742 MTX srcCopy;
19743 BOOL skip_row = FALSE;
19744
19745
19746 if( MTX_isNull( src ) )
19747 {
19748 MTX_ERROR_MSG( "NULL Matrix" );
19749 return FALSE;
19750 }
19751
19752 MTX_Init( &srcCopy );
19753
19754 if( nrows > 0 )
19755 {
19756 if( rows == NULL )
19757 {
19758 MTX_ERROR_MSG( "rows is a NULL pointer." );
19759 return FALSE;
19760 }
19761 }
19762
19763 if( ncols > 0 )
19764 {
19765 if( cols == NULL )
19766 {
19767 MTX_ERROR_MSG( "cols is a NULL pointer." );
19768 return FALSE;
19769 }
19770 }
19771
19772
19773
19774
19775
19776 for( j = 0; j < ncols; j++ )
19777 {
19778 col_index = cols[j];
19779 if( col_index-j >= src->ncols )
19780 {
19781 MTX_ERROR_MSG( "if( col_index-j >= src->ncols )" );
19782 return FALSE;
19783 }
19784
19785
19786
19787 if( !MTX_RemoveColumn( src, col_index-j ) )
19788 {
19789 MTX_ERROR_MSG( "MTX_RemoveColumn returned FALSE." );
19790 return FALSE;
19791 }
19792 }
19793
19794
19795
19796
19797
19798 if( !MTX_Copy( src, &srcCopy ) )
19799 {
19800 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
19801 return FALSE;
19802 }
19803
19804
19805 for( i = 0; i < nrows; i++ )
19806 {
19807 if( rows[i] >= src->nrows )
19808 {
19809 MTX_ERROR_MSG( "if( rows[i] >= src->nrows )" );
19810 return FALSE;
19811 }
19812 }
19813
19814
19815 if( !MTX_Resize( src, src->nrows-nrows, src->ncols, src->isReal ) )
19816 {
19817 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
19818 return FALSE;
19819 }
19820
19821
19822 for( i = 0; i < srcCopy.nrows; i++ )
19823 {
19824 skip_row = FALSE;
19825 for( row_index = 0; row_index < nrows; row_index++ )
19826 {
19827 if( i == rows[row_index] )
19828 {
19829 skip_row = TRUE;
19830 break;
19831 }
19832 }
19833
19834 if( !skip_row )
19835 {
19836 if( src->isReal )
19837 {
19838 for( j = 0; j < src->ncols; j++ )
19839 {
19840 src->data[j][k] = srcCopy.data[j][i];
19841 }
19842 }
19843 else
19844 {
19845 for( j = 0; j < src->ncols; j++ )
19846 {
19847 src->cplx[j][k].re = srcCopy.cplx[j][i].re;
19848 src->cplx[j][k].im = srcCopy.cplx[j][i].im;
19849 }
19850 }
19851 k++;
19852 }
19853 }
19854
19855
19856
19857
19858 MTX_Free( &srcCopy );
19859
19860 return TRUE;
19861 }
19862
19863
19864
19865 BOOL MTX_IsNAN( double value )
19866 {
19867 #ifdef WIN32
19868 if( _isnan( value ) )
19869 return TRUE;
19870 else
19871 return FALSE;
19872 #else
19873 if( isnan( value ) )
19874 return TRUE;
19875 else
19876 return FALSE;
19877 #endif
19878 }
19879
19880
19881
19882 BOOL MTX_IsPostiveINF( double value )
19883 {
19884 #ifdef WIN32
19885 if( _finite( value ) )
19886 {
19887 return FALSE;
19888 }
19889 else
19890 {
19891 if( value > 0 )
19892 return TRUE;
19893 else
19894 return FALSE;
19895 }
19896 #else
19897 if( isfinite( value ) )
19898 {
19899 return FALSE;
19900 }
19901 else
19902 {
19903 if( value > 0 )
19904 return TRUE;
19905 else
19906 return FALSE;
19907 }
19908 #endif
19909 }
19910
19911
19912
19913 BOOL MTX_IsNegativeINF( double value )
19914 {
19915 #ifdef WIN32
19916 if( _finite( value ) )
19917 {
19918 return FALSE;
19919 }
19920 else
19921 {
19922 if( value < 0 )
19923 return TRUE;
19924 else
19925 return FALSE;
19926 }
19927 #else
19928 if( isfinite( value ) )
19929 {
19930 return FALSE;
19931 }
19932 else
19933 {
19934 if( value < 0 )
19935 return TRUE;
19936 else
19937 return FALSE;
19938 }
19939 #endif
19940 }
19941
19942
19943 double MTX_static_get_rand_value()
19944 {
19945 double val;
19946 val = ((double)rand()) / ((double)RAND_MAX);
19947 return val;
19948 }
19949
19950
19951
19952
19953
19954
19955 double MTX_static_get_randn_value()
19956 {
19957
19958
19959
19960
19961
19962
19963
19964
19965
19966
19967
19968 static BOOL has_saved = FALSE;
19969 static double saved;
19970 double x;
19971 double y;
19972 double r;
19973 double mu;
19974
19975 if( has_saved )
19976 {
19977 has_saved = FALSE;
19978 return saved;
19979 }
19980
19981 do
19982 {
19983 x = MTX_static_get_rand_value()*2.0 - 1.0;
19984 y = MTX_static_get_rand_value()*2.0 - 1.0;
19985 r = x*x + y*y;
19986 } while( r >= 1.0 );
19987
19988 mu = sqrt( -2.0 * log( r ) / r );
19989
19990 saved = mu*y;
19991 has_saved = TRUE;
19992
19993 return mu*x;
19994 }
19995
19996 BOOL MTX_randn(
19997 MTX* M,
19998 const unsigned nrows,
19999 const unsigned ncols,
20000 const unsigned seed
20001 )
20002 {
20003 unsigned j;
20004 unsigned i;
20005
20006 if( M == NULL )
20007 {
20008 MTX_ERROR_MSG( "NULL input matrix." );
20009 return FALSE;
20010 }
20011 if( nrows == 0 || ncols == 0 )
20012 {
20013 MTX_ERROR_MSG( "if( nrows == 0 || ncols == 0 )" );
20014 return FALSE;
20015 }
20016 if( !MTX_Malloc( M, nrows, ncols, TRUE ) )
20017 {
20018 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
20019 return FALSE;
20020 }
20021 srand( seed );
20022
20023 for( j = 0; j < ncols; j++ )
20024 {
20025 for( i = 0; i < nrows; i++ )
20026 {
20027 M->data[j][i] = MTX_static_get_randn_value();
20028 }
20029 }
20030
20031 return TRUE;
20032 }
20033
20034 BOOL MTX_rand(
20035 MTX* M,
20036 const unsigned nrows,
20037 const unsigned ncols,
20038 const unsigned seed
20039 )
20040 {
20041 unsigned j;
20042 unsigned i;
20043
20044 if( M == NULL )
20045 {
20046 MTX_ERROR_MSG( "NULL input matrix." );
20047 return FALSE;
20048 }
20049 if( nrows == 0 || ncols == 0 )
20050 {
20051 MTX_ERROR_MSG( "if( nrows == 0 || ncols == 0 )" );
20052 return FALSE;
20053 }
20054 if( !MTX_Malloc( M, nrows, ncols, TRUE ) )
20055 {
20056 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
20057 return FALSE;
20058 }
20059 srand( seed );
20060
20061 for( j = 0; j < ncols; j++ )
20062 {
20063 for( i = 0; i < nrows; i++ )
20064 {
20065 M->data[j][i] = MTX_static_get_rand_value();
20066 }
20067 }
20068
20069 return TRUE;
20070 }
20071
20072
20073
20074
20075 #ifndef _MATRIX_NO_PLOTTING
20076
20077 BOOL MTX_PlotQuick( MTX* M, const char* bmpfilename, const unsigned x_col, const unsigned y_col )
20078 {
20079 CPLOT_structSeries s;
20080 CPLOT_structPlotOptions opt;
20081 CPLOT P;
20082 char xlabel[128];
20083 char ylabel[128];
20084 char slabel[128];
20085
20086 if( MTX_isNull(M) )
20087 {
20088 MTX_ERROR_MSG( "NULL Matrix" );
20089 return FALSE;
20090 }
20091 if( bmpfilename == NULL )
20092 {
20093 MTX_ERROR_MSG( "bmpfilename is a NULL pointer." );
20094 return FALSE;
20095 }
20096
20097 if( x_col > M->ncols )
20098 {
20099 MTX_ERROR_MSG( "if( x_col > M->ncols )" );
20100 return FALSE;
20101 }
20102 if( y_col > M->ncols )
20103 {
20104 MTX_ERROR_MSG( "if( y_col > M->ncols )" );
20105 return FALSE;
20106 }
20107
20108 memset( &s, 0, sizeof(CPLOT_structSeries) );
20109 memset( &opt, 0, sizeof(CPLOT_structPlotOptions) );
20110
20111 if( !CPLOT_PlotOptionsInit( &opt ) )
20112 {
20113 MTX_ERROR_MSG( "CPLOT_PlotOptionsInit returned FALSE." );
20114 return FALSE;
20115 }
20116
20117 if( !CPLOT_Init( &P ) )
20118 {
20119 MTX_ERROR_MSG( "CPLOT_Init returned FALSE." );
20120 return FALSE;
20121 }
20122
20123 opt.numberOfSeries = 1;
20124 opt.PlotSize_Height_cm = 8;
20125 opt.PlotSize_Width_cm = 10;
20126 opt.plotStatistics = 1;
20127 opt.title = (char*)bmpfilename;
20128 #ifndef _CRT_SECURE_NO_DEPRECATE
20129 if( sprintf_s( xlabel, 128, "column %d", x_col ) < 0 )
20130 {
20131 MTX_ERROR_MSG( "sprintf_s returned failure." );
20132 return FALSE;
20133 }
20134 #else
20135 if( sprintf( xlabel, "column %d", x_col ) < 0 )
20136 {
20137 MTX_ERROR_MSG( "sprintf returned failure." );
20138 return FALSE;
20139 }
20140 #endif
20141 opt.x.label = xlabel;
20142 opt.x.isGridOn = TRUE;
20143 #ifndef _CRT_SECURE_NO_DEPRECATE
20144 if( sprintf_s( ylabel, 128, "column %d", y_col ) < 0 )
20145 {
20146 MTX_ERROR_MSG( "sprintf_s returned failure." );
20147 return FALSE;
20148 }
20149 #else
20150 if( sprintf( ylabel, "column %d", y_col ) < 0 )
20151 {
20152 MTX_ERROR_MSG( "sprintf returned failure." );
20153 return FALSE;
20154 }
20155 #endif
20156 opt.y.label = ylabel;
20157 opt.y.isGridOn = TRUE;
20158
20159 if( !CPLOT_SetPlotOptions( &P, &opt ) )
20160 {
20161 MTX_ERROR_MSG( "CPLOT_SetPlotOptions returned FALSE." );
20162 return FALSE;
20163 }
20164
20165 s.color = CPLOT_BLUE;
20166 s.connected = TRUE;
20167 #ifndef _CRT_SECURE_NO_DEPRECATE
20168 if( sprintf_s( slabel, 128, "col %d vs %d", x_col, y_col ) < 0 )
20169 {
20170 MTX_ERROR_MSG( "sprintf_s returned failure." );
20171 return FALSE;
20172 }
20173 #else
20174 if( sprintf( slabel, "col %d vs %d", x_col, y_col ) < 0 )
20175 {
20176 MTX_ERROR_MSG( "sprintf returned failure." );
20177 return FALSE;
20178 }
20179 #endif
20180 s.label = slabel;
20181 s.markOutlierData = TRUE;
20182 s.n = M->nrows;
20183 s.precision = 6;
20184 s.units = NULL;
20185 s.X = M->data[x_col];
20186 s.Y = M->data[y_col];
20187
20188 if( !CPLOT_Plot( &P, &s ) )
20189 {
20190 MTX_ERROR_MSG( "CPLOT_Plot returned FALSE." );
20191 return FALSE;
20192 }
20193
20194 if( !CPLOT_SaveToFile( &P, bmpfilename ) )
20195 {
20196 MTX_ERROR_MSG( "CPLOT_SaveToFile returned FALSE." );
20197 return FALSE;
20198 }
20199
20200 return TRUE;
20201 }
20202
20203
20204 BOOL MTX_Plot(
20205 const char* bmpfilename,
20206 const char* title,
20207 const unsigned plot_height_cm,
20208 const unsigned plot_width_cm,
20209 const BOOL includeStats,
20210 const BOOL isXGridOn,
20211 const BOOL isYGridOn,
20212 const char* xlabel,
20213 const char* ylabel,
20214 const MTX_structAxisOptions opt_x,
20215 const MTX_structAxisOptions opt_y,
20216 const MTX_PLOT_structSeries* series,
20217 const unsigned nrSeries
20218 )
20219 {
20220 unsigned i = 0;
20221
20222 CPLOT_structSeries s;
20223 CPLOT_structPlotOptions opt;
20224 CPLOT P;
20225
20226 double val = 0;
20227 double re = 0;
20228 double im = 0;
20229 double xmin = DBL_MAX;
20230 double xmax = -DBL_MAX;
20231 double ymin = DBL_MAX;
20232 double ymax = -DBL_MAX;
20233
20234 typedef struct
20235 {
20236 double lowerlimit;
20237 double upperlimit;
20238 double tickstart;
20239 double ticksize;
20240 double tickend;
20241 }_structAxis;
20242 _structAxis x;
20243 _structAxis y;
20244
20245 if( bmpfilename == NULL )
20246 {
20247 MTX_ERROR_MSG( "bmpfilename is a NULL pointer." );
20248 return FALSE;
20249 }
20250
20251 if( plot_height_cm > 50 || plot_width_cm > 50 )
20252 {
20253 MTX_ERROR_MSG( "if( plot_height_cm > 50 || plot_width_cm > 50 )" );
20254 return FALSE;
20255 }
20256
20257 memset( &s, 0, sizeof(CPLOT_structSeries) );
20258 memset( &opt, 0, sizeof(CPLOT_structPlotOptions) );
20259
20260 if( !CPLOT_PlotOptionsInit( &opt ) )
20261 {
20262 MTX_ERROR_MSG( "CPLOT_PlotOptionsInit returned FALSE." );
20263 return FALSE;
20264 }
20265
20266 if( !CPLOT_Init( &P ) )
20267 {
20268 MTX_ERROR_MSG( "CPLOT_Init returned FALSE." );
20269 return FALSE;
20270 }
20271
20272 if( series == NULL )
20273 {
20274 MTX_ERROR_MSG( "series is a NULL pointer." );
20275 return FALSE;
20276 }
20277
20278 if( nrSeries == 0 )
20279 {
20280 MTX_ERROR_MSG( "if( nrSeries == 0 )" );
20281 return FALSE;
20282 }
20283
20284
20285 for( i = 0; i < nrSeries; i++ )
20286 {
20287 if( MTX_isNull(series[i].M) )
20288 {
20289 MTX_ERROR_MSG( "NULL Matrix" );
20290 return FALSE;
20291 }
20292 if( !series[i].M->isReal )
20293 {
20294 MTX_ERROR_MSG( "if( !series[i].M->isReal )" );
20295 return FALSE;
20296 }
20297
20298 if( series[i].x_col >= series[i].M->ncols )
20299 {
20300 MTX_ERROR_MSG( "if( series[i].x_col >= series[i].M->ncols )" );
20301 return FALSE;
20302 }
20303 if( series[i].y_col >= series[i].M->ncols )
20304 {
20305 MTX_ERROR_MSG( "if( series[i].y_col >= series[i].M->ncols )" );
20306 return FALSE;
20307 }
20308 }
20309
20310 for( i = 0; i < nrSeries; i++ )
20311 {
20312
20313
20314
20315 if( !MTX_MinColumn( series[i].M, series[i].x_col, &re, &im ) )
20316 {
20317 MTX_ERROR_MSG( "MTX_MinColumn returned FALSE." );
20318 return FALSE;
20319 }
20320 if( re < xmin )
20321 xmin = re;
20322 if( !MTX_MaxColumn( series[i].M, series[i].x_col, &re, &im ) )
20323 {
20324 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
20325 return FALSE;
20326 }
20327 if( re > xmax )
20328 xmax = re;
20329
20330 if( !MTX_MinColumn( series[i].M, series[i].y_col, &re, &im ) )
20331 {
20332 MTX_ERROR_MSG( "MTX_MinColumn returned FALSE." );
20333 return FALSE;
20334 }
20335 if( re < ymin )
20336 ymin = re;
20337 if( !MTX_MaxColumn( series[i].M, series[i].y_col, &re, &im ) )
20338 {
20339 MTX_ERROR_MSG( "MTX_MaxColumn returned FALSE." );
20340 return FALSE;
20341 }
20342 if( re > ymax )
20343 ymax = re;
20344 }
20345
20346
20347
20348
20349
20350
20351
20352
20353 if( !opt_x.lowerlimit.doNotUseDefault &&
20354 !opt_x.upperlimit.doNotUseDefault &&
20355 !opt_x.tickstart.doNotUseDefault &&
20356 !opt_x.tickend.doNotUseDefault )
20357 {
20358 val = xmin;
20359 if( val < 0 )
20360 {
20361 val = -ceil( -val * 10.0 ) / 10.0;
20362 }
20363 else
20364 {
20365 val = floor( val * 10.0 ) / 10.0;
20366 }
20367 x.lowerlimit = val;
20368
20369 val = xmax;
20370 if( val < 0 )
20371 {
20372 val = -floor( -val * 10.0 ) / 10.0;
20373 }
20374 else
20375 {
20376 val = ceil( val * 10.0 ) / 10.0;
20377 }
20378 x.upperlimit = val;
20379
20380
20381 if( x.lowerlimit == x.upperlimit )
20382 {
20383 x.lowerlimit -= x.lowerlimit/100.0;
20384 x.upperlimit += x.upperlimit/100.0;
20385 }
20386
20387 x.tickstart = x.lowerlimit;
20388 x.ticksize = (x.upperlimit-x.lowerlimit)/5.0;
20389 x.tickend = x.upperlimit;
20390 }
20391 else
20392 {
20393
20394
20395 if( opt_x.lowerlimit.doNotUseDefault )
20396 x.lowerlimit = opt_x.lowerlimit.val;
20397 else
20398 x.lowerlimit = xmin;
20399
20400 if( opt_x.upperlimit.doNotUseDefault )
20401 x.upperlimit = opt_x.upperlimit.val;
20402 else
20403 x.upperlimit = xmax;
20404
20405 if( opt_x.tickstart.doNotUseDefault )
20406 x.tickstart = opt_x.tickstart.val;
20407 else
20408 x.tickstart = x.lowerlimit;
20409
20410 if( opt_x.tickend.doNotUseDefault )
20411 x.tickend = opt_x.tickend.val;
20412 else
20413 x.tickend = x.upperlimit;
20414
20415 if( opt_x.ticksize.doNotUseDefault )
20416 x.ticksize = opt_x.ticksize.val;
20417 else
20418 x.ticksize = (x.tickend - x.tickstart)/5.0;
20419 }
20420 if( x.lowerlimit == x.upperlimit )
20421 {
20422 MTX_ERROR_MSG( "if( x.lowerlimit == x.upperlimit )" );
20423 return FALSE;
20424 }
20425 if( x.tickstart == x.tickend )
20426 {
20427 MTX_ERROR_MSG( "if( x.tickstart == x.tickend )" );
20428 return FALSE;
20429 }
20430 if( x.ticksize <= 0.0 )
20431 {
20432 MTX_ERROR_MSG( "if( x.ticksize <= 0.0 )" );
20433 return FALSE;
20434 }
20435
20436
20437
20438
20439 if( !opt_y.lowerlimit.doNotUseDefault &&
20440 !opt_y.upperlimit.doNotUseDefault &&
20441 !opt_y.tickstart.doNotUseDefault &&
20442 !opt_y.tickend.doNotUseDefault )
20443 {
20444 val = ymin;
20445 if( val < 0 )
20446 {
20447 val = -ceil( -val * 10.0 ) / 10.0;
20448 }
20449 else
20450 {
20451 val = floor( val * 10.0 ) / 10.0;
20452 }
20453 y.lowerlimit = val;
20454
20455 val = ymax;
20456 if( val < 0 )
20457 {
20458 val = -floor( -val * 10.0 ) / 10.0;
20459 }
20460 else
20461 {
20462 val = ceil( val * 10.0 ) / 10.0;
20463 }
20464 y.upperlimit = val;
20465
20466
20467 if( y.lowerlimit == y.upperlimit )
20468 {
20469 y.lowerlimit -= y.lowerlimit/100.0;
20470 y.upperlimit += y.upperlimit/100.0;
20471 }
20472
20473 y.tickstart = y.lowerlimit;
20474 y.ticksize = (y.upperlimit-y.lowerlimit)/10.0;
20475 y.tickend = y.upperlimit;
20476 }
20477 else
20478 {
20479
20480
20481 if( opt_y.lowerlimit.doNotUseDefault )
20482 y.lowerlimit = opt_y.lowerlimit.val;
20483 else
20484 y.lowerlimit = ymin;
20485
20486 if( opt_y.upperlimit.doNotUseDefault )
20487 y.upperlimit = opt_y.upperlimit.val;
20488 else
20489 y.upperlimit = ymax;
20490
20491 if( opt_y.tickstart.doNotUseDefault )
20492 y.tickstart = opt_y.tickstart.val;
20493 else
20494 y.tickstart = y.lowerlimit;
20495
20496 if( opt_y.tickend.doNotUseDefault )
20497 y.tickend = opt_y.tickend.val;
20498 else
20499 y.tickend = y.upperlimit;
20500
20501 if( opt_y.ticksize.doNotUseDefault )
20502 y.ticksize = opt_y.ticksize.val;
20503 else
20504 y.ticksize = (y.tickend - y.tickstart)/10.0;
20505 }
20506 if( y.lowerlimit == y.upperlimit )
20507 {
20508 MTX_ERROR_MSG( "if( y.lowerlimit == y.upperlimit )" );
20509 return FALSE;
20510 }
20511 if( y.tickstart == y.tickend )
20512 {
20513 MTX_ERROR_MSG( "if( y.tickstart == y.tickend )" );
20514 return FALSE;
20515 }
20516 if( y.ticksize <= 0.0 )
20517 {
20518 MTX_ERROR_MSG( "if( y.ticksize <= 0.0 )" );
20519 return FALSE;
20520 }
20521
20522
20523
20524 opt.x.lowerlimit.val = x.lowerlimit;
20525 opt.x.upperlimit.val = x.upperlimit;
20526 opt.x.tickstart.val = x.tickstart;
20527 opt.x.ticksize.val = x.ticksize;
20528 opt.x.tickend.val = x.tickend;
20529
20530 opt.x.lowerlimit.doNotUseDefault = TRUE;
20531 opt.x.upperlimit.doNotUseDefault = TRUE;
20532 opt.x.tickstart.doNotUseDefault = TRUE;
20533 opt.x.ticksize.doNotUseDefault = TRUE;
20534 opt.x.tickend.doNotUseDefault = TRUE;
20535
20536 opt.y.lowerlimit.val = y.lowerlimit;
20537 opt.y.upperlimit.val = y.upperlimit;
20538 opt.y.tickstart.val = y.tickstart;
20539 opt.y.ticksize.val = y.ticksize;
20540 opt.y.tickend.val = y.tickend;
20541
20542 opt.y.lowerlimit.doNotUseDefault = TRUE;
20543 opt.y.upperlimit.doNotUseDefault = TRUE;
20544 opt.y.tickstart.doNotUseDefault = TRUE;
20545 opt.y.ticksize.doNotUseDefault = TRUE;
20546 opt.y.tickend.doNotUseDefault = TRUE;
20547
20548 opt.title = (char*)title;
20549 opt.x.label = (char*)xlabel;
20550 opt.y.label = (char*)ylabel;
20551 opt.x.isGridOn = isXGridOn;
20552 opt.y.isGridOn = isYGridOn;
20553 opt.plotStatistics = includeStats;
20554 opt.PlotSize_Height_cm = plot_height_cm;
20555 opt.PlotSize_Width_cm = plot_width_cm;
20556 opt.numberOfSeries = nrSeries;
20557
20558 if( !CPLOT_SetPlotOptions( &P, &opt ) )
20559 {
20560 MTX_ERROR_MSG( "CPLOT_SetPlotOptions returned FALSE." );
20561 return FALSE;
20562 }
20563
20564 for( i = 0; i < nrSeries; i++ )
20565 {
20566 s.color = (CPLOT_enumColor) series[i].color;
20567 s.connected = series[i].connected;
20568 s.label = series[i].label;
20569 s.markOutlierData = series[i].markOutlierData;
20570 s.precision = series[i].precision;
20571 s.units = series[i].units;
20572 s.n = series[i].M->nrows;
20573 s.X = series[i].M->data[series[i].x_col];
20574 s.Y = series[i].M->data[series[i].y_col];
20575
20576 if( !CPLOT_Plot( &P, &s ) )
20577 {
20578 MTX_ERROR_MSG( "CPLOT_Plot returned FALSE." );
20579 return FALSE;
20580 }
20581 }
20582
20583 if( !CPLOT_SaveToFile( &P, bmpfilename ) )
20584 {
20585 MTX_ERROR_MSG( "CPLOT_SaveToFile returned FALSE." );
20586 return FALSE;
20587 }
20588
20589 return TRUE;
20590 }
20591
20592 #endif // ifndef _MATRIX_NO_PLOTTING
20593
20594 #ifdef _DEBUG
20595
20596
20597
20598
20599
20600
20601
20602 const char* _shortfile(const char *fname)
20603 {
20604 const char *cp1, *cp2, *r;
20605 cp1 = strrchr(fname, '/');
20606 cp2 = strrchr(fname, '\\');
20607 if (cp1 && cp2)
20608 {
20609 r = (cp1<cp2)?(cp2+1):(cp1+1);
20610 }
20611 else if (cp1)
20612 {
20613 r = cp1+1;
20614 }
20615 else if (cp2)
20616 {
20617 r = cp2+1;
20618 }
20619 else
20620 {
20621 r = fname;
20622 }
20623 return r;
20624 }
20625 #else
20626 const char* nullstring = "NULL";
20627 const char* _shortfile(const char *fname)
20628 {
20629 return nullstring;
20630 }
20631 #endif
20632
20633 BOOL MTX_AddIdentity( const MTX *src, MTX *dst )
20634 {
20635 unsigned i;
20636 if( MTX_isNull( src ) )
20637 {
20638 MTX_ERROR_MSG( "NULL Matrix" );
20639 return FALSE;
20640 }
20641 if( !MTX_Copy( src, dst ) )
20642 {
20643 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
20644 return FALSE;
20645 }
20646 if( src->isReal )
20647 {
20648 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20649 dst->data[i][i] += 1.0;
20650 }
20651 else
20652 {
20653 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20654 dst->cplx[i][i].re += 1.0;
20655 }
20656 return TRUE;
20657 }
20658
20659 BOOL MTX_AddIdentity_Inplace( MTX *src )
20660 {
20661 unsigned i;
20662 if( MTX_isNull( src ) )
20663 {
20664 MTX_ERROR_MSG( "NULL Matrix" );
20665 return FALSE;
20666 }
20667 if( src->isReal )
20668 {
20669 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20670 src->data[i][i] += 1.0;
20671 }
20672 else
20673 {
20674 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20675 src->cplx[i][i].re += 1.0;
20676 }
20677 return TRUE;
20678 }
20679
20680
20681 BOOL MTX_MinusIdentity( const MTX *src, MTX *dst )
20682 {
20683 unsigned i;
20684 if( MTX_isNull( src ) )
20685 {
20686 MTX_ERROR_MSG( "NULL Matrix" );
20687 return FALSE;
20688 }
20689 if( !MTX_Copy( src, dst ) )
20690 {
20691 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
20692 return FALSE;
20693 }
20694 if( src->isReal )
20695 {
20696 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20697 dst->data[i][i] -= 1.0;
20698 }
20699 else
20700 {
20701 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20702 dst->cplx[i][i].re -= 1.0;
20703 }
20704 return TRUE;
20705 }
20706
20707 BOOL MTX_MinusIdentity_Inplace( MTX *src )
20708 {
20709 unsigned i;
20710 if( MTX_isNull( src ) )
20711 {
20712 MTX_ERROR_MSG( "NULL Matrix" );
20713 return FALSE;
20714 }
20715 if( src->isReal )
20716 {
20717 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20718 src->data[i][i] -= 1.0;
20719 }
20720 else
20721 {
20722 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20723 src->cplx[i][i].re -= 1.0;
20724 }
20725 return TRUE;
20726 }
20727
20728 BOOL MTX_IdentityMinus( const MTX *src, MTX *dst )
20729 {
20730 unsigned i;
20731
20732 if( MTX_isNull( src ) )
20733 {
20734 MTX_ERROR_MSG( "NULL Matrix" );
20735 return FALSE;
20736 }
20737 if( !MTX_Copy( src, dst ) )
20738 {
20739 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
20740 return FALSE;
20741 }
20742 if( !MTX_Negate( dst ) )
20743 {
20744 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
20745 return FALSE;
20746 }
20747 if( dst->isReal )
20748 {
20749 for( i = 0; i < dst->nrows && i < dst->ncols; i++ )
20750 dst->data[i][i] += 1.0;
20751 }
20752 else
20753 {
20754 for( i = 0; i < dst->nrows && i < dst->ncols; i++ )
20755 dst->cplx[i][i].re += 1.0;
20756 }
20757 return TRUE;
20758 }
20759
20760 BOOL MTX_IdentityMinus_Inplace( MTX *src )
20761 {
20762 unsigned i;
20763
20764 if( MTX_isNull( src ) )
20765 {
20766 MTX_ERROR_MSG( "NULL Matrix" );
20767 return FALSE;
20768 }
20769 if( !MTX_Negate( src ) )
20770 {
20771 MTX_ERROR_MSG( "MTX_Negate returned FALSE." );
20772 return FALSE;
20773 }
20774 if( src->isReal )
20775 {
20776 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20777 src->data[i][i] += 1.0;
20778 }
20779 else
20780 {
20781 for( i = 0; i < src->nrows && i < src->ncols; i++ )
20782 src->cplx[i][i].re += 1.0;
20783 }
20784 return TRUE;
20785 }
20786
20787 BOOL MTX_Hilbert( MTX *src, const unsigned N )
20788 {
20789 unsigned i;
20790 unsigned j;
20791
20792 if( !src )
20793 {
20794 MTX_ERROR_MSG( "NULL pointer input." );
20795 return FALSE;
20796 }
20797
20798 if( src->nrows != N || src->ncols != N || !src->isReal )
20799 {
20800 if( !MTX_Malloc( src, N, N, TRUE ) )
20801 {
20802 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
20803 return FALSE;
20804 }
20805 }
20806
20807 for( j = 1; j < src->ncols+1; j++ )
20808 {
20809 for( i = 1; i < src->nrows+1; i++ )
20810 {
20811 src->data[j-1][i-1] = 1.0 / ( i + j - 1.0 );
20812 }
20813 }
20814
20815 return TRUE;
20816 }
20817
20818
20819 BOOL MTX_Swap( MTX* A, MTX *B )
20820 {
20821 MTX C;
20822 if( A == NULL )
20823 {
20824 MTX_ERROR_MSG( "A is a NULL Matrix" );
20825 return FALSE;
20826 }
20827 if( B == NULL )
20828 {
20829 MTX_ERROR_MSG( "B is a NULL Matrix" );
20830 return FALSE;
20831 }
20832
20833
20834
20835 C.isReal = A->isReal;
20836 C.comment = A->comment;
20837 C.cplx = A->cplx;
20838 C.data = A->data;
20839 C.ncols = A->ncols;
20840 C.nrows = A->nrows;
20841
20842 A->isReal = B->isReal;
20843 A->comment = B->comment;
20844 A->cplx = B->cplx;
20845 A->data = B->data;
20846 A->ncols = B->ncols;
20847 A->nrows = B->nrows;
20848
20849 B->isReal = C.isReal;
20850 B->comment = C.comment;
20851 B->cplx = C.cplx;
20852 B->data = C.data;
20853 B->ncols = C.ncols;
20854 B->nrows = C.nrows;
20855
20856
20857 return TRUE;
20858 }
20859
20860
20861 BOOL MTX_LDLt(
20862 MTX* src,
20863 MTX *L,
20864 MTX* d,
20865 BOOL checkSymmetric
20866 )
20867 {
20868 int i;
20869 int j;
20870 int k;
20871 int n;
20872 BOOL isSymmetric = TRUE;
20873 double val;
20874 double maxdif;
20875 double dtmp;
20876
20877 if( src == NULL || L == NULL || d == NULL )
20878 {
20879 MTX_ERROR_MSG( "An input Matrix is NULL" );
20880 return FALSE;
20881 }
20882
20883 if( MTX_isNull( src ) )
20884 {
20885 MTX_ERROR_MSG( "NULL Matrix" );
20886 return FALSE;
20887 }
20888
20889 if( !MTX_isSquare( src ) )
20890 {
20891 MTX_ERROR_MSG( "src Matrix is not square" );
20892 return FALSE;
20893 }
20894
20895 if( !src->isReal )
20896 {
20897 MTX_ERROR_MSG( "Complex LDLt not supported yet" );
20898 return FALSE;
20899 }
20900
20901
20902 n = src->ncols;
20903
20904 if( checkSymmetric )
20905 {
20906
20907 for( i = 0; i < n; i++ )
20908 {
20909 for( j = i+1; j < n; j++ )
20910 {
20911 val = src->data[j][i];
20912 maxdif = fabs( val )*1e-14;
20913
20914
20915 dtmp = fabs( val - src->data[i][j] );
20916 if( dtmp > maxdif )
20917 {
20918 isSymmetric = FALSE;
20919 break;
20920 }
20921 }
20922 if( !isSymmetric )
20923 break;
20924 }
20925 if( !isSymmetric )
20926 {
20927 MTX_ERROR_MSG( "src is not symmetric" );
20928 return FALSE;
20929 }
20930 }
20931
20932 if( !MTX_Copy( src, L ) )
20933 {
20934 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
20935 return FALSE;
20936 }
20937
20938 if( !MTX_Calloc( d, n, 1, TRUE ) )
20939 {
20940 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
20941 return FALSE;
20942 }
20943
20944
20945
20946
20947 for( j = 0; j < n; j++ )
20948 {
20949 dtmp = 0;
20950 for( k = 0; k < j; k++ )
20951 {
20952 val = L->data[k][j];
20953 dtmp += val * val * L->data[k][k];
20954 }
20955 L->data[j][j] -= dtmp;
20956
20957 for( i = j + 1; i < n; i++ )
20958 {
20959 for( k = 0; k < j; k++ )
20960 L->data[j][i] -= L->data[k][i] * L->data[k][j] * L->data[k][k];
20961
20962 if( L->data[j][j] == 0.0 )
20963 return FALSE;
20964
20965 L->data[j][i] /= L->data[j][j];
20966 }
20967 }
20968
20969
20970 for( i = 0; i < n; i++ )
20971 {
20972 d->data[0][i] = L->data[i][i];
20973 L->data[i][i] = 1.0;
20974
20975 for( j = i+1; j < n; j++ )
20976 {
20977 L->data[j][i] = 0.0;
20978 }
20979 }
20980
20981 return TRUE;
20982 }
20983
20984
20985 BOOL MTX_UDUt(
20986 MTX* src,
20987 MTX *U,
20988 MTX* d,
20989 BOOL checkSymmetric
20990 )
20991 {
20992 int i;
20993 int j;
20994 int k;
20995 int n;
20996 BOOL isSymmetric = TRUE;
20997 double val;
20998 double maxdif;
20999 double dtmp;
21000 double alpha;
21001 double beta;
21002
21003 if( src == NULL || U == NULL || d == NULL )
21004 {
21005 MTX_ERROR_MSG( "An input Matrix is NULL" );
21006 return FALSE;
21007 }
21008
21009 if( MTX_isNull( src ) )
21010 {
21011 MTX_ERROR_MSG( "NULL Matrix" );
21012 return FALSE;
21013 }
21014
21015 if( !MTX_isSquare( src ) )
21016 {
21017 MTX_ERROR_MSG( "src Matrix is not square" );
21018 return FALSE;
21019 }
21020
21021 if( !src->isReal )
21022 {
21023 MTX_ERROR_MSG( "Complex LDLt not supported yet" );
21024 return FALSE;
21025 }
21026
21027
21028 n = src->ncols;
21029
21030 if( checkSymmetric )
21031 {
21032
21033 for( i = 0; i < n; i++ )
21034 {
21035 for( j = i+1; j < n; j++ )
21036 {
21037 val = src->data[j][i];
21038 maxdif = fabs( val )*1e-14;
21039
21040
21041 dtmp = fabs( val - src->data[i][j] );
21042 if( dtmp > maxdif )
21043 {
21044 isSymmetric = FALSE;
21045 break;
21046 }
21047 }
21048 if( !isSymmetric )
21049 break;
21050 }
21051 if( !isSymmetric )
21052 {
21053 MTX_ERROR_MSG( "src is not symmetric" );
21054 return FALSE;
21055 }
21056 }
21057
21058 if( !MTX_Copy( src, U ) )
21059 {
21060 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
21061 return FALSE;
21062 }
21063
21064 if( !MTX_Calloc( d, n, 1, TRUE ) )
21065 {
21066 MTX_ERROR_MSG( "MTX_Calloc returned FALSE." );
21067 return FALSE;
21068 }
21069
21070
21071
21072 for( j = n-1; j >= 1; j-- )
21073 {
21074 dtmp = U->data[j][j];
21075 d->data[0][j] = dtmp;
21076 if( dtmp == 0.0 )
21077 return FALSE;
21078
21079 alpha = 1.0/dtmp;
21080 for( k = 0; k <= j-1; k++ )
21081 {
21082 beta = U->data[j][k];
21083 U->data[j][k] = alpha*beta;
21084 for( i = 0; i <= k; i++ )
21085 {
21086 U->data[k][i] -= beta*U->data[j][i];
21087 }
21088 }
21089 }
21090 d->data[0][0] = U->data[0][0];
21091
21092
21093 for( i = 0; i < n; i++ )
21094 {
21095 U->data[i][i] = 1.0;
21096 for( j = 0; j < i; j++ )
21097 {
21098 U->data[j][i] = 0.0;
21099 }
21100 }
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117
21118
21119
21120
21121
21122
21123
21124
21125
21126
21127
21128
21129
21130 return TRUE;
21131 }
21132
21133
21134
21135 static BOOL MTX_static_gammp(double a, double x, double* ans);
21136 static BOOL MTX_static_gammq(double a, double x, double* ans);
21137 static BOOL MTX_static_gser(double *gamser, double a, double x, double *gln);
21138 static BOOL MTX_static_gcf(double *gammcf, double a, double x, double *gln);
21139 static double MTX_static_gammln(double xx);
21140
21141
21142 BOOL MTX_erf_Inplace( MTX* src )
21143 {
21144 unsigned j = 0;
21145 unsigned i = 0;
21146 double x = 0;
21147
21148 if( MTX_isNull( src ) )
21149 {
21150 MTX_ERROR_MSG( "src matrix is NULL" );
21151 return FALSE;
21152 }
21153
21154 if( !src->isReal )
21155 {
21156 MTX_ERROR_MSG( "complex erf is not yet supported." );
21157 return FALSE;
21158 }
21159
21160 for( j = 0; j < src->ncols; j++ )
21161 {
21162
21163 for( i = 0; i < src->nrows; i++ )
21164 {
21165 x = src->data[j][i];
21166
21167 if( x < 0.0 )
21168 {
21169 if( !MTX_static_gammp( 0.5, x*x, &x ) )
21170 {
21171 MTX_ERROR_MSG( "MTX_static_gammp returned FALSE." );
21172 return FALSE;
21173 }
21174 src->data[j][i] = -x;
21175 }
21176 else
21177 {
21178 if( !MTX_static_gammp( 0.5, x*x, &x ) )
21179 {
21180 MTX_ERROR_MSG( "MTX_static_gammp returned FALSE." );
21181 return FALSE;
21182 }
21183 src->data[j][i] = x;
21184 }
21185 }
21186 }
21187
21188 return TRUE;
21189 }
21190
21191
21192
21193 BOOL MTX_erfinv_Inplace( MTX* src )
21194 {
21195 unsigned j = 0;
21196 MTX vec;
21197 unsigned i = 0;
21198 double u = 0;
21199 double z = 0;
21200 double y = 0;
21201
21202 const double a[4] = {0.886226899, -1.645349621, 0.914624893, -0.140543331};
21203 const double b[4] = {-2.118377725, 1.442710462, -0.329097515, 0.012229801};
21204 const double c[4] = {-1.970840454, -1.624906493, 3.429567803, 1.641345311};
21205 const double d[2] = {3.543889200, 1.637067800};
21206 const double y0 = 0.7;
21207 const double two_over_rootpi = 2.0/sqrt(PI);
21208 MTX vecX;
21209 MTX vecErfX;
21210 MTX_Init(&vecX);
21211 MTX_Init(&vecErfX);
21212 MTX_Init(&vec);
21213
21214 if( MTX_isNull( src ) )
21215 {
21216 MTX_ERROR_MSG( "src matrix is NULL" );
21217 return FALSE;
21218 }
21219
21220 if( !src->isReal )
21221 {
21222 MTX_ERROR_MSG( "complex erfinv is not supported." );
21223 return FALSE;
21224 }
21225
21226 for( j = 0; j < src->ncols; j++ )
21227 {
21228 if( !MTX_CopyColumn( src, j, &vec ) )
21229 {
21230 MTX_Free(&vec);
21231 MTX_ERROR_MSG( "MTX_CopyColumn returned FALSE." );
21232 return FALSE;
21233 }
21234
21235 if( !MTX_Resize( &vecX, vec.nrows, 1, TRUE ) )
21236 {
21237 MTX_Free(&vec);
21238 MTX_Free(&vecX);
21239 MTX_Free(&vecErfX);
21240 MTX_ERROR_MSG( "MTX_Resize returned FALSE." );
21241 return FALSE;
21242 }
21243 for( i = 0; i < vec.nrows; i++ )
21244 {
21245 y = vec.data[0][i];
21246 if( fabs( y ) < y0 )
21247 {
21248 z = y*y;
21249 vecX.data[0][i] = y * ( ( (a[3]*z+a[2])*z + a[1] )*z + a[0] );
21250 vecX.data[0][i] /= ( ( (b[3]*z+b[2])*z + b[1] )*z + b[0] )*z + 1.0;
21251 }
21252 else if( y0 < y && y < 1.0 )
21253 {
21254 z = sqrt( -log( (1.0 - y)/2.0 ) );
21255 vecX.data[0][i] = (( c[3]*z + c[2] )*z + c[1])*z + c[0];
21256 vecX.data[0][i] /= (d[1]*z + d[0])*z + 1.0;
21257 }
21258 else if( -y0 > y && y > -1.0 )
21259 {
21260 z = sqrt( -log( (1.0 + y)/2.0 ) );
21261 vecX.data[0][i] = -(((c[3]*z + c[2])*z + c[1])*z + c[0]);
21262 vecX.data[0][i] /= ((d[1]*z+d[0])*z+1.0);
21263 }
21264 }
21265
21266 if( !MTX_Copy( &vecX, &vecErfX ) )
21267 {
21268 MTX_Free(&vec);
21269 MTX_Free(&vecX);
21270 MTX_Free(&vecErfX);
21271 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
21272 return FALSE;
21273 }
21274
21275 if( !MTX_erf_Inplace( &vecErfX ) )
21276 {
21277 MTX_Free(&vec);
21278 MTX_Free(&vecX);
21279 MTX_Free(&vecErfX);
21280 MTX_ERROR_MSG( "MTX_erf_Inplace returned FALSE." );
21281 return FALSE;
21282 }
21283
21284 for( i = 0; i < vec.nrows; i++ )
21285 {
21286 u = (vecErfX.data[0][i] - vec.data[0][i]) / (two_over_rootpi * exp( -(vecX.data[0][i]*vecX.data[0][i]) ));
21287
21288
21289 vecX.data[0][i] -= u / (1.0 + vecX.data[0][i]*u);
21290
21291 y = vec.data[0][i];
21292 z = vecX.data[0][i];
21293
21294 if( y == -1 )
21295 z = MTX_NEG_INF;
21296 else if( y == 1 )
21297 z = MTX_POS_INF;
21298 else if( fabs(y) > 1 )
21299 z = MTX_NAN;
21300 else if( y == MTX_NAN )
21301 z = MTX_NAN;
21302
21303 src->data[j][i] = z;
21304 }
21305 }
21306
21307 MTX_Free(&vec);
21308 MTX_Free(&vecX);
21309 MTX_Free(&vecErfX);
21310
21311 return TRUE;
21312 }
21313
21314
21315 BOOL MTX_erfc_Inplace( MTX* src )
21316 {
21317 unsigned j = 0;
21318 unsigned i = 0;
21319 double x = 0;
21320
21321 if( MTX_isNull( src ) )
21322 {
21323 MTX_ERROR_MSG( "src matrix is NULL" );
21324 return FALSE;
21325 }
21326
21327 if( !src->isReal )
21328 {
21329 MTX_ERROR_MSG( "complex erfc is not yet supported." );
21330 return FALSE;
21331 }
21332
21333 for( j = 0; j < src->ncols; j++ )
21334 {
21335
21336 for( i = 0; i < src->nrows; i++ )
21337 {
21338 x = src->data[j][i];
21339
21340 if( x < 0.0 )
21341 {
21342 if( !MTX_static_gammp( 0.5, x*x, &x ) )
21343 {
21344 MTX_ERROR_MSG( "MTX_static_gammp returned FALSE." );
21345 return FALSE;
21346 }
21347 src->data[j][i] = 1+x;
21348 }
21349 else
21350 {
21351 if( !MTX_static_gammq( 0.5, x*x, &x ) )
21352 {
21353 MTX_ERROR_MSG( "MTX_static_gammp returned FALSE." );
21354 return FALSE;
21355 }
21356 src->data[j][i] = x;
21357 }
21358 }
21359 }
21360
21361 return TRUE;
21362 }
21363
21364
21365 BOOL MTX_erfcinv_Inplace( MTX* src )
21366 {
21367 MTX copySrc;
21368 MTX_Init( ©Src );
21369
21370 if( !MTX_OneMinus( src, ©Src ) )
21371 {
21372 MTX_Free( ©Src );
21373 MTX_ERROR_MSG( "MTX_OneMinus returned FALSE." );
21374 return FALSE;
21375 }
21376 if( !MTX_Copy( ©Src, src ) )
21377 {
21378 MTX_Free( ©Src );
21379 MTX_ERROR_MSG( "MTX_Copy returned FALSE." );
21380 return FALSE;
21381 }
21382 if( !MTX_erfinv_Inplace( src ) )
21383 {
21384 MTX_Free( ©Src );
21385 MTX_ERROR_MSG( "MTX_erfinv_Inplace returned FALSE." );
21386 return FALSE;
21387 }
21388 MTX_Free( ©Src );
21389 return TRUE;
21390 }
21391
21392
21393
21394
21395
21396
21397
21398
21399
21400
21401
21402
21403 BOOL MTX_static_gammp(double a, double x, double* ans)
21404 {
21405 double gamser=0;
21406 double gammcf=0;
21407 double gln=0;
21408 if( x < 0.0 || a <= 0.0 )
21409 {
21410 MTX_ERROR_MSG( "Invalid arguments a or x.");
21411 return FALSE;
21412 }
21413 if( x < (a+1.0) )
21414 {
21415
21416 if( !MTX_static_gser( &gamser, a, x, &gln) )
21417 {
21418 MTX_ERROR_MSG( "MTX_static_gser returned FALSE." );
21419 return FALSE;
21420 }
21421 *ans = gamser;
21422 return TRUE;
21423 }
21424 else
21425 {
21426
21427 if( !MTX_static_gcf( &gammcf, a, x, &gln ) )
21428 {
21429 MTX_ERROR_MSG( "MTX_static_gcf returned FALSE." );
21430 return FALSE;
21431 }
21432 *ans = 1.0-gammcf;
21433 return TRUE;
21434 }
21435 }
21436
21437
21438
21439
21440
21441
21442
21443
21444
21445 BOOL MTX_static_gammq(double a, double x, double* ans)
21446 {
21447 double gamser=0;
21448 double gammcf=0;
21449 double gln=0;
21450 if( x < 0.0 || a <= 0.0 )
21451 {
21452 MTX_ERROR_MSG("if( x < 0.0 || a <= 0.0 ) ");
21453 return FALSE;
21454 }
21455 if( x < (a+1.0) )
21456 {
21457
21458 if( !MTX_static_gser(&gamser,a,x,&gln) )
21459 {
21460 MTX_ERROR_MSG( "MTX_static_gser returned FALSE." );
21461 return FALSE;
21462 }
21463 *ans = 1.0-gamser;
21464 return TRUE;
21465 }
21466 else
21467 {
21468
21469 if( !MTX_static_gcf(&gammcf,a,x,&gln) )
21470 {
21471 MTX_ERROR_MSG( "MTX_static_gcf returned FALSE." );
21472 return FALSE;
21473 }
21474 *ans = gammcf;
21475 return TRUE;
21476 }
21477 }
21478
21479
21480
21481
21482
21483
21484
21485
21486
21487
21488 BOOL MTX_static_gser(double *gamser, double a, double x, double *gln)
21489 {
21490 int n;
21491 const int itmax = 10000;
21492 const double eps = DBL_EPSILON;
21493
21494
21495
21496
21497 double sum;
21498 double del;
21499 double ap;
21500
21501
21502
21503
21504 *gln = MTX_static_gammln(a);
21505
21506 if( x <= 0.0 )
21507 {
21508 if( x < 0.0 )
21509 {
21510 MTX_ERROR_MSG( "x less than 0.");
21511 return FALSE;
21512 }
21513 *gamser=0.0;
21514 return TRUE;
21515 }
21516 else
21517 {
21518 ap = a;
21519 del = sum = 1.0/a;
21520 for( n = 1; n <= itmax; n++)
21521 {
21522 ap += 1.0;
21523 del *= x/ap;
21524 sum += del;
21525 if( fabs(del) < fabs(sum)*eps )
21526 {
21527 *gamser = sum * exp( -x+a*log(x)-(*gln) );
21528 return TRUE;
21529 }
21530 }
21531 MTX_ERROR_MSG( "a is too large for the number of iterations in MTX_static_gser." );
21532 return FALSE;
21533 }
21534 }
21535
21536
21537
21538
21539
21540
21541
21542
21543
21544
21545
21546
21547 BOOL MTX_static_gcf(double *gammcf, double a, double x, double *gln)
21548 {
21549 const int itmax = 10000;
21550 const double eps = DBL_EPSILON;
21551 const double fpmin = DBL_MIN;
21552
21553
21554
21555
21556
21557 int i;
21558 double an,b,c,d,del,h;
21559
21560 *gln = MTX_static_gammln(a);
21561
21562 b = x+1.0-a;
21563 c = 1.0/fpmin;
21564 d = 1.0/b;
21565 h = d;
21566 for( i = 1; i <= itmax; i++ )
21567 {
21568
21569 an = -i*(i-a);
21570 b += 2.0;
21571 d = an*d+b;
21572 if( fabs(d) < fpmin )
21573 d = fpmin;
21574 c = b+an/c;
21575 if( fabs(c) < fpmin )
21576 c = fpmin;
21577 d = 1.0/d;
21578 del = d*c;
21579 h *= del;
21580 if( fabs(del-1.0) < eps )
21581 break;
21582 }
21583 if( i > itmax )
21584 {
21585 MTX_ERROR_MSG("a too large, too few iterations");
21586 return FALSE;
21587 }
21588 *gammcf = exp(-x+a*log(x)-(*gln))*h;
21589 return TRUE;
21590 }
21591
21592
21593
21594
21595
21596
21597
21598
21599
21600
21601 double MTX_static_gammln(double xx)
21602 {
21603 double x,y,tmp,ser;
21604 static double cof[6] = {76.18009172947146,-86.50532032941677,24.01409824083091,-1.231739572450155,0.1208650973866179e-2,-0.5395239384953e-5};
21605 int j;
21606 y = x = xx;
21607 tmp = x+5.5;
21608 tmp -= (x+0.5)*log(tmp);
21609 ser = 1.000000000190015;
21610 for( j = 0; j < 6; j++ )
21611 {
21612 y += 1.0;
21613 ser += cof[j]/y;
21614 }
21615 x = -tmp+log(2.5066282746310005*ser/x);
21616 return x;
21617 }
21618
21619
21620
21621 BOOL MTX_find_column_values_equalto(
21622 const MTX* src,
21623 const unsigned col,
21624 MTX* indexVector,
21625 const double re,
21626 const double im,
21627 const double tolerance
21628 )
21629 {
21630 unsigned i = 0;
21631 unsigned k = 0;
21632 if( MTX_isNull( src ) )
21633 {
21634 MTX_ERROR_MSG( "src is a NULL matrix" );
21635 return FALSE;
21636 }
21637 if( indexVector == NULL )
21638 {
21639 MTX_ERROR_MSG( "indexVector is NULL" );
21640 return FALSE;
21641 }
21642 if( col >= src->ncols )
21643 {
21644 MTX_ERROR_MSG( "Invalid column specified." );
21645 return FALSE;
21646 }
21647 if( tolerance < 0 )
21648 {
21649 MTX_ERROR_MSG( "invalid tolerance (-ve)" );
21650 return FALSE;
21651 }
21652
21653 if( src->isReal && fabs(im) > tolerance )
21654 {
21655 MTX_Free( indexVector );
21656
21657 return TRUE;
21658 }
21659
21660 if( !MTX_Malloc( indexVector, src->nrows, 1, TRUE ) )
21661 {
21662 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
21663 return FALSE;
21664 }
21665
21666 if( fabs(im) < tolerance && src->isReal )
21667 {
21668
21669 for( i = 0; i < src->nrows; i++ )
21670 {
21671 if( fabs( src->data[col][i] - re ) <= tolerance )
21672 {
21673 indexVector->data[0][k] = i;
21674 k++;
21675 }
21676 }
21677 }
21678 else
21679 {
21680
21681 if( src->isReal )
21682 {
21683 MTX_ERROR_MSG("Unexpected real matrix");
21684 return FALSE;
21685 }
21686
21687 for( i = 0; i < src->nrows; i++ )
21688 {
21689 if( fabs( src->cplx[col][i].re - re ) <= tolerance &&
21690 fabs( src->cplx[col][i].im - im ) <= tolerance )
21691 {
21692 indexVector->data[0][k] = i;
21693 k++;
21694 }
21695 }
21696 }
21697
21698 if( k == 0 )
21699 {
21700 if( !MTX_Free( indexVector ) )
21701 {
21702 MTX_ERROR_MSG("MTX_Free returned FALSE.");
21703 return FALSE;
21704 }
21705 }
21706 else
21707 {
21708 if( !MTX_Redim( indexVector, k, 1 ) )
21709 {
21710 MTX_ERROR_MSG("Unexpected real matrix.");
21711 return FALSE;
21712 }
21713 }
21714
21715 return TRUE;
21716 }
21717
21718 BOOL MTX_find_column_values_not_equalto(
21719 const MTX* src,
21720 const unsigned col,
21721 MTX* indexVector,
21722 const double re,
21723 const double im,
21724 const double tolerance
21725 )
21726 {
21727 unsigned i = 0;
21728 unsigned k = 0;
21729 if( MTX_isNull( src ) )
21730 {
21731 MTX_ERROR_MSG( "src is a NULL matrix" );
21732 return FALSE;
21733 }
21734 if( indexVector == NULL )
21735 {
21736 MTX_ERROR_MSG( "indexVector is NULL" );
21737 return FALSE;
21738 }
21739 if( col >= src->ncols )
21740 {
21741 MTX_ERROR_MSG( "Invalid column specified." );
21742 return FALSE;
21743 }
21744 if( tolerance < 0 )
21745 {
21746 MTX_ERROR_MSG( "invalid tolerance (-ve)" );
21747 return FALSE;
21748 }
21749
21750 if( src->isReal && fabs(im) > tolerance )
21751 {
21752
21753 if( !MTX_Colon( indexVector, 0, 1, src->nrows - 1 ) )
21754 {
21755 MTX_ERROR_MSG( "invalid tolerance (-ve)" );
21756 return FALSE;
21757 }
21758 return TRUE;
21759 }
21760
21761 if( !MTX_Malloc( indexVector, src->nrows, 1, TRUE ) )
21762 {
21763 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
21764 return FALSE;
21765 }
21766
21767 if( fabs(im) <= tolerance && src->isReal )
21768 {
21769
21770 for( i = 0; i < src->nrows; i++ )
21771 {
21772 if( fabs( src->data[col][i] - re ) > tolerance )
21773 {
21774 indexVector->data[0][k] = i;
21775 k++;
21776 }
21777 }
21778 }
21779 else
21780 {
21781
21782 if( src->isReal )
21783 {
21784 MTX_ERROR_MSG("Unexpected real matrix");
21785 return FALSE;
21786 }
21787
21788 for( i = 0; i < src->nrows; i++ )
21789 {
21790 if( fabs( src->cplx[col][i].re - re ) > tolerance ||
21791 fabs( src->cplx[col][i].im - im ) > tolerance )
21792 {
21793 indexVector->data[0][k] = i;
21794 k++;
21795 }
21796 }
21797 }
21798
21799 if( k == 0 )
21800 {
21801 if( !MTX_Free( indexVector ) )
21802 {
21803 MTX_ERROR_MSG("MTX_Free returned FALSE.");
21804 return FALSE;
21805 }
21806 }
21807 else
21808 {
21809 if( !MTX_Redim( indexVector, k, 1 ) )
21810 {
21811 MTX_ERROR_MSG("Unexpected real matrix.");
21812 return FALSE;
21813 }
21814 }
21815
21816 return TRUE;
21817 }
21818
21819
21820 BOOL MTX_find_column_values_less_than(
21821 const MTX* src,
21822 const unsigned col,
21823 MTX* indexVector,
21824 const double value
21825 )
21826 {
21827 unsigned i = 0;
21828 unsigned k = 0;
21829 double re = 0;
21830 double im = 0;
21831 double magv = 0;
21832 if( MTX_isNull( src ) )
21833 {
21834 MTX_ERROR_MSG( "src is a NULL matrix" );
21835 return FALSE;
21836 }
21837 if( indexVector == NULL )
21838 {
21839 MTX_ERROR_MSG( "indexVector is NULL" );
21840 return FALSE;
21841 }
21842 if( col >= src->ncols )
21843 {
21844 MTX_ERROR_MSG( "Invalid column specified." );
21845 return FALSE;
21846 }
21847
21848 if( !MTX_Malloc( indexVector, src->nrows, 1, TRUE ) )
21849 {
21850 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
21851 return FALSE;
21852 }
21853
21854
21855 if( src->isReal )
21856 {
21857 for( i = 0; i < src->nrows; i++ )
21858 {
21859 if( src->data[col][i] < value )
21860 {
21861 indexVector->data[0][k] = i;
21862 k++;
21863 }
21864 }
21865 }
21866 else
21867 {
21868 for( i = 0; i < src->nrows; i++ )
21869 {
21870 re = src->cplx[col][i].re;
21871 im = src->cplx[col][i].im;
21872 magv = sqrt( re*re + im*im );
21873 if( magv < value )
21874 {
21875 indexVector->data[0][k] = i;
21876 k++;
21877 }
21878 }
21879 }
21880
21881 if( k == 0 )
21882 {
21883 if( !MTX_Free( indexVector ) )
21884 {
21885 MTX_ERROR_MSG("MTX_Free returned FALSE.");
21886 return FALSE;
21887 }
21888 }
21889 else
21890 {
21891 if( !MTX_Redim( indexVector, k, 1 ) )
21892 {
21893 MTX_ERROR_MSG("Unexpected real matrix.");
21894 return FALSE;
21895 }
21896 }
21897
21898 return TRUE;
21899 }
21900
21901
21902 BOOL MTX_find_column_values_more_than(
21903 const MTX* src,
21904 const unsigned col,
21905 MTX* indexVector,
21906 const double value
21907 )
21908 {
21909 unsigned i = 0;
21910 unsigned k = 0;
21911 double re = 0;
21912 double im = 0;
21913 double magv = 0;
21914 if( MTX_isNull( src ) )
21915 {
21916 MTX_ERROR_MSG( "src is a NULL matrix" );
21917 return FALSE;
21918 }
21919 if( indexVector == NULL )
21920 {
21921 MTX_ERROR_MSG( "indexVector is NULL" );
21922 return FALSE;
21923 }
21924 if( col >= src->ncols )
21925 {
21926 MTX_ERROR_MSG( "Invalid column specified." );
21927 return FALSE;
21928 }
21929
21930 if( !MTX_Malloc( indexVector, src->nrows, 1, TRUE ) )
21931 {
21932 MTX_ERROR_MSG( "MTX_Malloc returned FALSE." );
21933 return FALSE;
21934 }
21935
21936
21937 if( src->isReal )
21938 {
21939 for( i = 0; i < src->nrows; i++ )
21940 {
21941 if( src->data[col][i] > value )
21942 {
21943 indexVector->data[0][k] = i;
21944 k++;
21945 }
21946 }
21947 }
21948 else
21949 {
21950 for( i = 0; i < src->nrows; i++ )
21951 {
21952 re = src->cplx[col][i].re;
21953 im = src->cplx[col][i].im;
21954 magv = sqrt( re*re + im*im );
21955 if( magv > value )
21956 {
21957 indexVector->data[0][k] = i;
21958 k++;
21959 }
21960 }
21961 }
21962
21963 if( k == 0 )
21964 {
21965 if( !MTX_Free( indexVector ) )
21966 {
21967 MTX_ERROR_MSG("MTX_Free returned FALSE.");
21968 return FALSE;
21969 }
21970 }
21971 else
21972 {
21973 if( !MTX_Redim( indexVector, k, 1 ) )
21974 {
21975 MTX_ERROR_MSG("Unexpected real matrix.");
21976 return FALSE;
21977 }
21978 }
21979
21980 return TRUE;
21981 }
21982