Poniżej przestawiamy wybrane kody źródłowe programów omawianych w drugiej części podręcznika Obliczenia inżynierskie i naukowe (PWN, 2011). Większość z nich jest dostępna na licencji Creative Commons BY-SA.
Listing 9.1 - harm.c. [Pobierz]
/* ** ** Listing 9.1 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* Kompilacja: gcc -o harm harm.c Uruchomienie: ./harm */ #include <stdio.h> #define N 2012 int main(void) { float x; unsigned int i; x = 0.0; for(i = 1; i <= N; i++) x = x + 1.0/i; printf("Wartosc sumy x = 1 + 1/2 + .. + 1/%d jest rowna %g\n", N, x); return(0); }
Listing 9.2 - sinusy.c. [Pobierz]
/* ** ** Listing 9.2 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* kompilacja: gcc -o sinusy sinusy.c -lm */ #include <stdio.h> #include <stdlib.h> /* zawiera prototyp funkcji drand48() i srand48() */ #include <math.h> #define N 15 /* ile liczb wydrukować */ int main(void) { int i; double x, y[N]; srand48(time(NULL)); /* inicjalizacja generatora liczb losowych; nie używać, gdy chcemy mieć powtarzalne (sic!) wyniki */ for( i = 0; i < N; i++) { x = 2.0*M_PI*drand48(); y[i] = sin(x); fprintf(stderr, "(%3d) x = %10.5le | sin(x) = %10.5le\n", i, x, y[i]); } return(0); }
Listing 9.3 - zapiszdane.c. [Pobierz]
/* ** ** Listing 9.3 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* kompilacja: gcc -o zapiszdane zapiszdane.c -lm */ #include <stdio.h> #include <stdlib.h> #include <math.h> const int N = 10; /* liczba wierszy */ const int M = 5; /* liczba kolumn */ #define IJ(i,j,N) (((i)-1) + ((j)-1)*(N)) int main(void) { FILE *plik; double *T; int i,j; /* Faza 1: tworzymy tablicę liczb T */ if ((T = (double *) malloc(N*M*sizeof(double))) == NULL) { fprintf(stderr, "Nie mozna przydzielic pamieci\n"); return(-1); } for( j = 1; j <= M; j++) for( i = 1; i <= N; i++) T[IJ(i,j,N)] = exp(-i/(double)N -j); /* Faza 2: wypisujemy dane z tablicy T do pliku tablica.dat */ if ((plik = fopen("tablica.dat","w")) == NULL) { fprintf(stderr, "Nie mozna otworzyc pliku\n"); return(-1); } fprintf(plik, "%8d %8d\n", N, M); for( i = 1; i <= N; i++) { for( j = 1; j <= M; j++) fprintf(plik, "%16.10E ", T[IJ(i,j,N)]); fprintf(plik, "\n"); } /* Faza 3: sprzątanie */ ferror(plik); fclose(plik); free(T); return(0); }
Listing 9.4 - wczytajdane.c. [Pobierz]
/* ** ** Listing 9.4 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* kompilacja: gcc -o wczytajdane wczytajdane.c */ #include <stdio.h> #include <stdlib.h> #include <math.h> #define IJ(i,j,N) (((i)-1) + ((j)-1)*(N)) int main(int argc, char** argv) { FILE *plik; double *X; /* tu będzie wczytana macierz */ int N,M; /* zmienne na wymiary macierzy */ int i,j; /* wczytujemy dane z pliku do tablicy - najpierw musimy ustalić jej wymiary */ if ( (plik = fopen(argv[1], "r")) == NULL ) { fprintf(stderr, "Nie można otworzyć pliku '%s'\n", argv[1]); return(-1); } fscanf(plik, "%d %d\n", &N, &M); /* znając wymiary, alokujemy pamięć na macierz */ if ((X = (double *) malloc(N*M*sizeof(double))) == NULL) { fprintf(stderr, "Nie można przydzielić pamięci\n"); return(-1); } fprintf(stderr, "Wczytuje macierz %d x %d\n", N, M); for( i = 1; i <= N; i++) { for( j = 1; j <= M; j++) fscanf(plik, "%lE", &X[IJ(i,j,N)]); } /* ...i od tej pory możemy używać tablicy X, wypełnionej danymi z pliku; ale my już kończymy program... */ fclose(plik); free(X); return(0); }
Listing 9.5 - IJ.h. [Pobierz]
/* ** ** Listing 9.5 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz swobodnie używać tego kodu ** */ /* makra dostępu do macierzy rozwiniętej kolumnami */ /* elementy indeksowane od "1" */ #define I(i) ((i)-1) /* wektor */ #define IJ(i,j,n) ((i)-1+((j)-1)*(n)) /* macierz n x m */ #define IJK(i,j,k,n,m) ((i)-1+((j)-1)*(n)+((k)-1)*(n*m)) /* macierz n x m x k */
Listing 9.6 - testblas.c. [Pobierz]
/* ** ** Listing 9.6 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* Kompilacja: gcc -o testblas testblas.c -lblas -lgfortran -lm */ #include <stdio.h> #define N 3 extern double dnrm2_(int*,double*,int*); /* prototyp DNRM2 z BLAS */ int main(void) { int n=N, incx=1; double x[N]= {3,0,4}; printf("Norma zadanego wektora: %e\n", dnrm2_(&n, x, &incx)); return(0); }
Listing 9.7 - mx2.c. [Pobierz]
/* ** ** Listing 9.7 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ #include <stdio.h> #include <stdlib.h> #include "mx2.h" double *mx2alloc(int n, int m) { /* przydziela pamięć na macierz n x m liczb typu double */ return((double *) malloc(n*m*sizeof(double))); } void mx2free( double *matrix ) { /* zwalnia pamięć wskazywaną przez matrix */ free(matrix); } void mx2rand( double *matrix, int n, int m) { /* generuje losową macierz n x m o wartościach z przedziału [0,1) */ int i,j; for( j = 1; j <= m; j++) for( i = 1; i <= n; i++) matrix[IJ(i,j,n)] = drand48(); } int mx2write( double *matrix, int n, int m, char *nazwapliku) { /* zapisuje (wierszami) macierz do pliku tekstowego; w pierwszej linii podajemy wymiary macierzy */ int i,j; FILE *plik; if ((plik = fopen(nazwapliku,"w")) == NULL) { fprintf(stderr, "Nie mozna otworzyc pliku: %s\n", nazwapliku); return(-1); } fprintf(plik, "%8d %8d\n", n, m); for( i = 1; i <= n; i++) { for( j = 1; j <= m; j++) fprintf(plik, "%16.10E ", matrix[IJ(i,j,n)]); fprintf(plik, "\n"); } fclose(plik); return(0); } double mx2frobnorm(double *matrix, int n, int m) { /* Norma Frobeniusa macierzy dwuwymiarowej: $||A||_F = \sqrt{\sum_{i,j} A_{ij}^2}$ Wystarczy potraktować macierz jako długi wektor (a to już i tak zrobiliśmy), a potem obliczyć jego normę euklidesową, korzystając z DNRM2 z biblioteki BLAS */ static int incx=1; int size; size = n*m; return(dnrm2_(&size, matrix, &incx)); }
Listing 9.8 - mx2.h. [Pobierz]
/* ** ** Listing 9.8 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* plik nagłówkowy dla biblioteczki macierzowej: macierze 2-wymiarowe */ #include "IJ.h" /* makro dostępu do elementów macierzy */ /* prototyp funkcji DNRM2 z BLAS */ extern double dnrm2_(int *, double *, int *); /* prototypy definiowanych funkcji */ double *mx2alloc(int n, int m); void mx2free( double *matrix ); void mx2rand( double *matrix, int n, int m); int mx2write( double *matrix, int n, int m, char *nazwapliku); double mx2frobnorm(double *matrix, int n, int m);
Listing 9.9 - testmx.c. [Pobierz]
/* ** ** Listing 9.9 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ #include <stdio.h> #include "mx2.h" int main(void) { int N=10, M=5; double *A; A = mx2alloc(N,M); mx2rand(A,N,M); A[IJ(1,1,N)] = 1.0; mx2write(A,N,M,"macierzA.dat"); printf("Norma Frobeniusa wygenerowanej macierzy = %e\n", mx2frobnorm(A,N,M)); return(0); }
Listing 9.10 - Makefile. [Pobierz]
## ## Listing 9.10 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ## (C) Piotr Krzyżanowski, 2011 ## ## Możesz swobodnie używać tego kodu ## # Makefile dla programu testblas.c CC = gcc CFLAGS = -O3 CLIBS = -lblas -lgfortran -lm testblas: testblas.c $(CC) $(CFLAGS) -o $@ $< $(CLIBS)
Listing 9.13 - Makefile-umfpack. [Pobierz]
## ## Listing 9.13 i 10.11 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ## (C) Piotr Krzyżanowski, 2011 ## ## Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ## zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ## # Zapisz ten plik pod nazwą "Makefile"! # # "uniwersalny" Makefile przystosowany do kompilacji pliku testumfpacksolve.c # z listingu 10.10 # #--------- definicja konkretnego zadania (projektu) --------- PROJECT = testumfpacksolve #--------- ogólne definicje --------- CC = gcc CFLAGS = -O3 -funroll-loops -static CLIBS = -lumfpack -lamd -llapack -lblas -lgfortran -lm CINCDIR = -I/usr/include/suitesparse -I.. #--------- pliki źródłowe i pośrednie ----------- OBJS = mmread.o mmio.o $(PROJECT).o #--------- ogólne reguły --------- %.o: %.c Makefile $(HEADERS) $(CC) $(CFLAGS) $(CINCDIR) -c $< -o $@ #--------- główne zadanie --------- $(PROJECT): $(OBJS) $(CC) $(CFLAGS) $(CLIBDIR) -o $@ $(OBJS) $(CLIBS) -lrt #--------- praktyczne zadania ogólne --------- clean: rm $(OBJS) $(PROJECT)
Listing 10.1 - sinusy-gsl.c. [Pobierz]
/* ** ** Listing 10.1 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* Kompilacja: gcc -o sinusy-gsl sinusy-gsl.c -lgsl -lgslcblas -lm */ #include <stdio.h> #include <gsl/gsl_rng.h> /* zawiera prototypy funkcji losowych GSL */ #include <math.h> #define N 15 /* ile liczb wydrukować */ int main(void) { int i; double x,y; gsl_rng *rng; /* wskaźnik do generatora, którego będziemy używać */ gsl_rng_env_setup(); /* inicjalizacja domyślnego generatora gsl_rng_default i jego ziarna, na podstawie zmiennych środowiskowych GSL_RNG_TYPE i GSL_RNG_SEED. Domyślnie GSL_RNG_TYPE=gsl_rng_mt19937 oraz GSL_RNG_SEED=0 */ rng = gsl_rng_alloc(gsl_rng_default); /* utworzenie instancji rng generatora liczb losowych domyślnego typu */ gsl_rng_set(rng, time(NULL)); /* zasianie wygenerowanego generatora bieżącą wartością czasu systemowego */ for( i = 0; i < N; i++) { x = 2.0*M_PI*gsl_rng_uniform(rng); y = sin(x); fprintf(stderr, "(%3d) x = %10.5le sin(x) = %10.5le\n", i, x, y); } gsl_rng_free(rng); /* usuwamy niepotrzebny już generator */ return(0); }
Listing 10.2 - testgslint.c. [Pobierz]
/* ** ** Listing 10.2 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ #include <stdio.h> #include <math.h> #include <gsl/gsl_integration.h> double F(double X, void * param) /* wrapper dla funkcji sin(x)/x */ { return(sin(X)/X); } int main(void) { gsl_function f; /* argument z funkcją podcałkową */ double A,ABSERR,B, EPSABS,EPSREL,RESULT; int IER,NEVAL; gsl_integration_workspace *workspace; int KEY, LIMIT; /* przygotowujemy argument z funkcją podcałkową */ f.function = &F; A = 0.0E0; B = 10*M_PI; /* przedział całkowania */ EPSABS = 0.0E0; EPSREL = 1.0E-3; /* tolerancja błędu */ /* parametry specyficzne dla QAG */ KEY = 1; /* tzn. użyj minimalnej liczby punktów kwadratury bazowej */ LIMIT = 100; /* maksymalny podział przedziału całkowania */ workspace = gsl_integration_workspace_alloc(LIMIT); /* całkujemy: QAG! */ IER = gsl_integration_qag(&f, A, B, EPSABS, EPSREL, LIMIT, KEY, workspace, &RESULT, &ABSERR); if (IER != 0) fprintf(stderr,"GSL_QAG: Kłopoty z całkowaniem\n"); fprintf(stderr,"Całka: %g Est. błąd: %g IER: %d\n", RESULT, ABSERR, IER); gsl_integration_workspace_free(workspace); }
Listing 10.4 - sinusy-acml.c. [Pobierz]
/* ** ** Listing 10.4 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* Kompilacja wersji dla x86 (tzn. 32-bitowej): gcc -static -o sinusy-acml sinusy-acml.c \ -I $HOME/Software/acml4.3.0/gfortran32/include \ -L $HOME/Software/acml4.3.0/gfortran32/lib \ -lacml -lgfortran -lm -lrt Kompilacja wersji dla x86-64 (tzn. 64-bitowej): gcc -static -o sinusy-acml sinusy-acml.c \ -D ACML_MV \ -I $HOME/Software/acml4.3.0/gfortran64/lib \ -L $HOME/Software/acml4.3.0/gfortran64/lib \ -lacml_mv -lacml -lgfortran -lm -lrt */ #include <stdio.h> #include <stdlib.h> #include <acml.h> /* zawiera prototypy funkcji losowych ACML */ #ifdef ACML_MV #include <acml_mv.h>/* zawiera prototypy funkcji wektorowych ACML */ #endif #include <math.h> /* stałe opisujące paramtery generatora Mersenne Twister (MT) w ACML */ #define DRAND_MT_CODE 2 /* kod generatora */ #define DRAND_MT_LSEED 624 /* rozmiar tablicy z ziarnem */ #define DRAND_MT_LSTATE 20 /* rozmiar tablicy stanu */ #define N 15 /* ile liczb wydrukować */ int main(void) { int i; double x[N],y[N]; /* zmienne wymagane do inicjalizacji generatora liczb losowych */ int drand_lseed = DRAND_MT_LSEED; int drand_seed[DRAND_MT_LSEED]; int drand_lstate = DRAND_MT_LSTATE; int drand_state[DRAND_MT_LSTATE]; int drand_info; /* inicjalizacja ziarna generatora MT */ for(i=0; i < DRAND_MT_LSEED; i++) drand_seed[i] = rand(); /* inicjalizacja generatora bazowego */ drandinitialize(DRAND_MT_CODE, 1, drand_seed, &drand_lseed, drand_state, &drand_lstate, &drand_info); /* generujemy od razu N liczb losowych! */ dranduniform(N, 0.0, 2.0*M_PI, drand_state, x, &drand_info); #ifdef ACML_MV vrda_sin(N, x, y); /* wektorowa instrukcja sin() */ #else for( i = 0; i < N; i++) { y[i] = sin(x[i]); } #endif for( i = 0; i < N; i++) fprintf(stderr, "(%3d) x = %10.5le sin(x) = %10.5le\n", i, x[i], y[i]); return(0); }
Listing 10.5 - blaslapack.h. [Pobierz]
/* ** ** Listing 10.5 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* przydatne pliki nagłówkowe dla procedur BLAS i LAPACK-a */ #include <stdlib.h> #include "IJ.h" /* makra dostępu do macierzy i wektorów - zob. listing 9.5 */ /* przydatne stałe */ static int BLASONE = 1, BLASMONE = -1, BLASZERO = 0; /* BLAS Level 1 */ extern double dnrm2_(int* N, double* X, int* INCX); /* BLAS Level 2 */ extern void dgemv_( char * TRANS, int * M, int * N, \ double * ALPHA, double * A, int * LDA, double * X, int * INCX, \ double * BETA, double * Y, int * INCY ); /* BLAS Level 3 */ extern void dgemm_(char * TRANSA,char * TRANSB, int * M, int * N, int * K, \ double * ALPHA, double * A, int * LDA, double * B, int * LDB, \ double * BETA, double * C, int * LDC ); /* LAPACK */ extern void dgesv_( int * N, int * NRHS, double * A, int * LDA, \ int * IPIV, double * B, int * LDB, int * INFO ); extern void dsysv_(char *, int *, int *, double *, int *, \ int *, double *, int *, double *, int *, int *); extern void dgels_( char * TRANS, int * M, int * N, int * NRHS, \ double * A, int * LDA, double * B, int * LDB, \ int * WORK, double * LWORK, int * INFO);
Listing 10.6 - testdgemv.c. [Pobierz]
/* ** ** Listing 10.6 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ #include <stdio.h> #include "blaslapack.h" int main() { int N = 5, i, j; double *A, *x, *y; /* generujemy przykładową macierz N x N jako odwrotną macierz Laplasjanu */ A = (double *)malloc(N*N*sizeof(double)); for (j = 1; j <= N; j++) { for (i = 1; i <= j; i++) A[IJ(i,j,N)] = i; for (i = j+1; i <= N; i++) A[IJ(i,j,N)] = j; } /* tworzymy wektory x i y, inicjalizujemy x */ x = (double *)malloc(N*sizeof(double)); y = (double *)malloc(N*sizeof(double)); for (i = 1; i <= N; i++) x[I(i)] = (double)i; /* obliczamy y = 5*A*x, korzystając z procedury BLAS Level 2: DGEMV dla zadania y = 5*A*x + 0*y */ { char TRANS = 'N'; double ALPHA = 5.0, BETA = 0.0; dgemv_(&TRANS, &N, &N, &ALPHA, A, &N, x, &BLASONE, &BETA, y, &BLASONE ); } for (i = 1; i <= N; i++) printf("%E\n",y[I(i)]); return(0); }
Listing 10.10 - testumfpacksolve.c. [Pobierz]
/* ** ** Listing 10.10 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** */ #include <stdio.h> #include <malloc.h> #include "umfpack.h" #define CHECK(status) {if (status != 0) \ { fprintf(stderr, "==> An error occured. Aborting program!\n"); \ return(-1);}} /* procedura wczytująca macierz do formatu AIJ indeksowanego od zera */ int mmreadsparse(char *filename, int* N, int* M, int* nz, int** I, int** J, double** Val ); int main(int argc, char** argv) { int M, N, nz; /* wymiary macierzy i liczba niezerowych elementów */ int *Ap, *Ai; double *Av; /* tu będziemy przechowywać macierz w formacie CSC */ int *I, *J; double *Val; /* tu będziemy przechowywać macierz w formacie AIJ */ double *x, *b; /* wektory prawej strony i rozwiązania */ int i; /* zmienne używane przez procedury UMFPACK */ double Control[UMFPACK_CONTROL], Info[UMFPACK_INFO]; void *Symbolic, *Numeric; int status; /* kod zakończenia procedury: różny od zera oznacza kłopoty */ /* ustawiamy parametry sterujące UMFPACKa */ umfpack_di_defaults(Control); Control[UMFPACK_PRL] = 2; /* poziom szczegółowości diagnostyki */ umfpack_di_report_control(Control); if (argc < 2) /* sposób użycia programu */ { fprintf(stderr,"Wywołanie: %s PlikMacierzy [PlikPrawejStrony [PlikRozwiązania]]\n", argv[0]); return(-1); } /* wczytujemy macierz w formacie MatrixMarket do formatu AIJ*/ if (mmreadsparse(argv[1], &N, &M, &nz, &I, &J, &Val ) != 0) return(-1); /* Transformujemy macierz z formatu AIJ do formatu CSC */ Ap = (int *) malloc((N+1) * sizeof(int)); /* N+1, a nie N: to ważne!! */ Ai = (int *) malloc(nz * sizeof(int)); Av = (double *) malloc(nz * sizeof(double)); umfpack_di_triplet_to_col(N,N,nz, I,J,Val, Ap,Ai,Av,(int *)NULL ); umfpack_di_report_matrix(N,N, Ap, Ai, Av, 1, Control); umfpack_di_report_triplet(N,N,nz, I, J, Val, Control); /* zwalniamy pamięć zajmowaną przez niepotrzebne zmienne pomocnicze */ free(I); free(J); free(Val); /* faktoryzacja symboliczna, reordering */ status = umfpack_di_symbolic(N, N, Ap, Ai, Av, &Symbolic, Control, Info); umfpack_di_report_status(Control,status); CHECK(status); /* faktoryzacja numeryczna */ status = umfpack_di_numeric(Ap, Ai, Av, Symbolic, &Numeric, Control, Info); umfpack_di_report_status(Control,status); CHECK(status); /* szykujemy wektory rozwiązania i prawej strony */ x = (double *)calloc(N,sizeof(double)); b = (double *)calloc(N,sizeof(double)); /* calloc zeruje alokowaną pamięć */ /* wczytujemy wektor prawej strony (o ile jest podany) w formacie MatrixMarket*/ if (argc > 2) { int Nrhs, Mrhs; if (mmreadsparse(argv[2], &Nrhs, &Mrhs, &nz, &I, &J, &Val) != 0) return(-1); else fprintf(stderr,"Wczytano prawą stronę : %dx%d\n", Nrhs, Mrhs); if (Mrhs > 1) { fprintf(stderr,"Oczekiwano jednego wektora prawej strony!\n"); return(-1); } /* zapisujemy go do wektora b */ for (i = 1; i <= nz; i++) b[I[i]] += Val[i]; /* zwalniamy pamięć zajmowaną przez niepotrzebne zmienne pomocnicze */ free(I); free(J); free(Val); } /* rozwiązanie układu Ax=b */ status = umfpack_di_solve(UMFPACK_A, Ap, Ai, Av, x, b, Numeric, Control, Info); umfpack_di_report_status(Control,status); CHECK(status); /* statystyki */ umfpack_di_report_info(Control,Info); /* sprzątanie */ umfpack_di_free_symbolic(&Symbolic); umfpack_di_free_numeric(&Numeric); /* ... korzystamy z wyznaczonego rozwiązania x .... */ /* zapisujemy je do pliku (tekstowego), o ile było takie życzenie */ if (argc > 3) { FILE *plik; if ((plik = fopen( argv[3], "w")) == NULL) { fprintf(stderr, "Nie mozna zapisac pliku %s\n", argv[3]); return(-1); } for (i = 0; i < N; i++) fprintf(plik, "%26.10e \n", x[i]); fclose(plik); } /* zwalniamy pamięć zajmowaną przez niepotrzebne zmienne */ free(Ap); free(Ai); free(Av); free(x); free(b); return(0); }
Listing 11.1 - timer.c. [Pobierz]
/* ** ** Listing 11.1 w książce "Obliczenia inżynierskie i naukowe", PWN 2011 ** (C) Piotr Krzyżanowski, 2011 ** ** Możesz używać tego kodu zgodnie z licencją Creative Commons BY-SA, ** zob. http://creativecommons.org/licenses/by-sa/3.0/pl/ ** */ /* Stoper w C, mierzący czas na trzy różne sposoby, za pomocą funkcji clock(), times(), clock_gettime(). Sposób użycia: tic(); ... instrukcje ... czas = toc(); */ #include <stdio.h> #include <unistd.h> /* zawiera pewne stałe systemowe */ #include <sys/times.h> /* zawiera funkcję times() */ #include <time.h> /* zawiera funkcję clock_gettime() i clock() */ static clock_t start_clk, stop_clk; /* dla clock() */ static struct tms start_tms, stop_tms; /* dla times() */ static struct timespec start_tmsp, stop_tmsp; /* dla clock_gettime() */ double tic(void) { fprintf(stderr, ">>>> Stoper START\n"); start_clk = clock(); times(&start_tms); clock_gettime(CLOCK_REALTIME, &start_tmsp); return(0.0); } double toc(void) { double cpu_timer_clk; double cpu_timer_total; double cpu_timer_real; stop_clk = clock(); times(&stop_tms); clock_gettime(CLOCK_REALTIME, &stop_tmsp); cpu_timer_total = (stop_tms.tms_utime-start_tms.tms_utime) * (1.0/sysconf(_SC_CLK_TCK)); cpu_timer_clk = (stop_clk-start_clk) * (1.0/CLOCKS_PER_SEC); cpu_timer_real = stop_tmsp.tv_sec-start_tmsp.tv_sec + 1e-9*(stop_tmsp.tv_nsec-start_tmsp.tv_nsec); fprintf(stderr, "<<<< Stoper STOP: %g (TOTAL CPU) %g (CLOCK) %g (REAL) sekund\n", cpu_timer_total, cpu_timer_clk, cpu_timer_real); return(cpu_timer_real); }