Flow123d  release_2.1.0-84-g6a13a75
math_fce.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file math_fce.cc
15  * @ingroup la
16  * @brief Auxiliary math functions.
17  */
18 
19 #include <math.h>
20 #include "global_defs.h"
21 #include "system/system.hh"
22 #include "system/math_fce.h"
23 
24 
25 static double Inverse2(SmallMtx2 a,SmallMtx2 b);
26 static double Inverse3(SmallMtx3 a,SmallMtx3 b);
27 static double Inverse4(SmallMtx4 a,SmallMtx4 b);
28 
29 //=============================================================================
30 // LENGTH OF VECTOR
31 //=============================================================================
32 double vector_length( double v[] )
33 {
34  return sqrt( v[0]*v[0]+v[1]*v[1]+v[2]*v[2] );
35 }
36 //=============================================================================
37 // SCALAR PRODUCT OF VECTORS
38 //=============================================================================
39 double scalar_product( double u[], double v[] )
40 {
41  return u[0]*v[0]+u[1]*v[1]+u[2]*v[2];
42 }
43 //=============================================================================
44 // NORMALIZE GIVEN VECTOR
45 //=============================================================================
46 void normalize_vector( double u[] )
47 {
48  double l;
49 
50  if ((l = vector_length( u )) < NUM_ZERO ) {
51  WarningOut() << "Normalization of nearly zero vector." << std::endl;
52  }
53  u[0] /= l; u[1] /= l; u[2] /= l;
54 }
55 //=============================================================================
56 // MULTIPLE VECTOR BY REAL NUMBER
57 //=============================================================================
58 void scale_vector( double u[], double k )
59 {
60  u[ 0 ] *= k; u[ 1 ] *= k; u[ 2 ] *= k;
61 }
62 
63 //=============================================================================
64 // VECTOR PRODUCT OF VECTORS
65 //=============================================================================
66 void vector_product( double u[], double v[], double x[] )
67 {
68  // u, v - inputs
69  // x - output, result
70 
71  x[ 0 ] = u[ 1 ] * v[ 2 ] - u[ 2 ] * v[ 1 ];
72  x[ 1 ] = u[ 2 ] * v[ 0 ] - u[ 0 ] * v[ 2 ];
73  x[ 2 ] = u[ 0 ] * v[ 1 ] - u[ 1 ] * v[ 0 ];
74 }
75 //=============================================================================
76 // VECTOR DIFFERENCE OF VECTORS
77 //=============================================================================
78 void vector_difference( double u[], double v[], double x[] )
79 {
80  x[ 0 ] = u[ 0 ] - v[ 0 ];
81  x[ 1 ] = u[ 1 ] - v[ 1 ];
82  x[ 2 ] = u[ 2 ] - v[ 2 ];
83 }
84 
85 /*************************************************
86  * SMALL MATRIX OPERATIONS
87  *************************************************/
88 
89 /**************************************************
90  * determinant 3x3
91  * *************************/
92 double Det3( SmallMtx3 a ) {
93  return a[0][0]*SUBDET2(1,2,1,2)
94  -a[0][1]*SUBDET2(1,2,0,2)
95  +a[0][2]*SUBDET2(1,2,0,1);
96 }
97 
98 /*************************************************
99  * Inverse of general small matrix with given size
100  * a - input; b - output; returns determinant
101  * ************************************************/
102 double MatrixInverse(double *a, double *b, int size) {
103  switch (size) {
104  case 1:
105  *b=1/(*a); return (*a);
106  case 2:
107  return ( Inverse2((SmallMtx2)a, (SmallMtx2)b) );
108  case 3:
109  return ( Inverse3((SmallMtx3)a, (SmallMtx3)b) );
110  case 4:
111  return ( Inverse4((SmallMtx4)a, (SmallMtx4)b) );
112  }
113  return 0.0;
114 }
115 
116 
117 /******************************************************************
118  * Inverse of 2x2 matrix with determinant
119  * a - input; b - output; returns determinant;
120  * *****************************************************************/
122  double Det;
123 
124  Det=SUBDET2(0,1,0,1);
125  if ( fabs(Det) < NUM_ZERO ) return Det;
126  b[0][0]=a[1][1]/Det;
127  b[1][0]=-a[1][0]/Det;
128  b[0][1]=-a[0][1]/Det;
129  b[1][1]=a[0][0]/Det;
130  return Det;
131 }
132 
133 /******************************************************************
134  * Inverse of 3x3 matrix with determinant
135  * a - input; b - output; returns determinant;
136  * *****************************************************************/
137 
139  double Det;
140 
141  b[0][0]=SUBDET2(1,2,1,2);
142  b[1][0]=-SUBDET2(1,2,0,2);
143  b[2][0]=SUBDET2(1,2,0,1);
144 
145  Det=a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0];
146  if ( fabs(Det)< NUM_ZERO) return Det;
147  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det;
148 
149  b[0][1]=-SUBDET2(0,2,1,2)/Det;
150  b[1][1]=SUBDET2(0,2,0,2)/Det;
151  b[2][1]=-SUBDET2(0,2,0,1)/Det;
152 
153  b[0][2]=SUBDET2(0,1,1,2)/Det;
154  b[1][2]=-SUBDET2(0,1,0,2)/Det;
155  b[2][2]=SUBDET2(0,1,0,1)/Det;
156  return Det;
157 }
158 
159 /******************************************************************
160  * Inverse of 4x4 matrix with determinant
161  * a - input; b - output; det - determinant; returns determinant
162  * *****************************************************************/
163 
165  double u[6], l[6], Det;
166  // 2x2 subdets of rows 1,2
167  u[0]=SUBDET2(0,1,0,1);
168  u[1]=SUBDET2(0,1,0,2);
169  u[2]=SUBDET2(0,1,0,3);
170  u[3]=SUBDET2(0,1,1,2);
171  u[4]=SUBDET2(0,1,1,3);
172  u[5]=SUBDET2(0,1,2,3);
173 
174  //1x1 subdets of rows 2,3
175  l[0]=SUBDET2(2,3,0,1);
176  l[1]=SUBDET2(2,3,0,2);
177  l[2]=SUBDET2(2,3,0,3);
178  l[3]=SUBDET2(2,3,1,2);
179  l[4]=SUBDET2(2,3,1,3);
180  l[5]=SUBDET2(2,3,2,3);
181 
182  // 3x3 subdets
183  b[0][0]=+a[1][1]*l[5]-a[1][2]*l[4]+a[1][3]*l[3];
184  b[1][0]=-a[1][0]*l[5]+a[1][2]*l[2]-a[1][3]*l[1];
185  b[2][0]=+a[1][0]*l[4]-a[1][1]*l[2]+a[1][3]*l[0];
186  b[3][0]=-a[1][0]*l[3]+a[1][1]*l[1]-a[1][2]*l[0];
187  // 4x4 det
188  Det=a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];
189  if ( fabs(Det)< NUM_ZERO) return Det;
190  b[0][0]/=Det; b[1][0]/=Det; b[2][0]/=Det; b[3][0]/=Det;
191 
192  b[0][1]=(-a[0][1]*l[5]+a[0][2]*l[4]-a[0][3]*l[3])/Det;
193  b[1][1]=(+a[0][0]*l[5]-a[0][2]*l[2]+a[0][3]*l[1])/Det;
194  b[2][1]=(-a[0][0]*l[4]+a[0][1]*l[2]-a[0][3]*l[0])/Det;
195  b[3][1]=(+a[0][0]*l[3]-a[0][1]*l[1]+a[0][2]*l[0])/Det;
196 
197  b[0][2]=(+a[3][1]*u[5]-a[3][2]*u[4]+a[3][3]*u[3])/Det;
198  b[1][2]=(-a[3][0]*u[5]+a[3][2]*u[2]-a[3][3]*u[1])/Det;
199  b[2][2]=(+a[3][0]*u[4]-a[3][1]*u[2]+a[3][3]*u[0])/Det;
200  b[3][2]=(-a[3][0]*u[3]+a[3][1]*u[1]-a[3][2]*u[0])/Det;
201 
202  b[0][3]=(-a[2][1]*u[5]+a[2][2]*u[4]-a[2][3]*u[3])/Det;
203  b[1][3]=(+a[2][0]*u[5]-a[2][2]*u[2]+a[2][3]*u[1])/Det;
204  b[2][3]=(-a[2][0]*u[4]+a[2][1]*u[2]-a[2][3]*u[0])/Det;
205  b[3][3]=(+a[2][0]*u[3]-a[2][1]*u[1]+a[2][2]*u[0])/Det;
206  return Det;
207 }
208 
209 /******************************************************************
210  * Print a full matrix stored in a vector size x size
211  * *****************************************************************/
212 void PrintSmallMatrix(double *mtx, int size ) {
213  int i,j;
214  printf("matrix %d x %d :\n",size,size);
215  for (i=0;i<size;i++) {
216  for(j=0;j<size;j++) printf("%f ",mtx[i*size+j]);
217  printf("\n");
218  }
219 }
220 
221 /*******************************************************************************
222  * at place inverse of an NxN matrix by Gauss-Jordan elimination without pivotation
223  * this should by faster then via adjung. matrix at least for N>3
224  * *****************************************************************************/
225 void MatInverse(int n,double **a) {
226  int row,subrow,col;
227  double Div,Mult;
228 
229  // forward run - lower triangle and diagonal of the inverse matrix
230  for(row=0;row<n-1;row++) {
231  // divide the row by diagonal
232  Div=a[row][row];a[row][row]=1;
233  for(col=0;col<n;col++) a[row][col]/=Div;
234  // eliminate the lower part of column "row"
235  for(subrow=row+1;subrow<n;subrow++) {
236  Mult=a[subrow][row];a[subrow][row]=0;
237  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
238  }
239  }
240  // divide the last row
241  Div=a[row][row];a[row][row]=1;
242  for(col=0;col<n;col++) a[row][col]/=Div;
243  //backward run - upper trinagle
244  for(;row>0;row--) {
245  // eliminate the upper part of column "row"
246  for(subrow=row-1;subrow>=0;subrow--) {
247  Mult=a[subrow][row];a[subrow][row]=0;
248  for(col=0;col<n;col++) a[subrow][col]-=a[row][col]*Mult;
249  }
250  }
251 }
252 
253 //=============================================================================
254 // solve equation system - gauss; returns 1 - one result 0 - system doesn't have result; 2 - oo results
255 // !!! THIS FUNCTION IS NOT USED and probably is WRONG !!!
256 //=============================================================================
257 /*
258 int gauss(double *A, double *B,int s,double *R)
259 {
260  int res=1,i,j,k,size;
261  double koef,tmp,max;
262  double *M;
263  size=s+1;
264  M = (double *) xmalloc( (size-1) * size * sizeof(double));
265  for(i=0;i<s;i++)
266  {
267  for(j=0;j<s;j++)
268  M[i*(size)+j]=A[i*s+j];
269  M[i*(size)+j]=B[i];
270  }
271  for(i=0;i<size-1;i++)
272  {
273  if(M[i*size+i]==0)
274  {
275  for(j=i+1;j<size-1;j++)
276  {
277  if(M[j*size+i]!=0)
278  {
279  for(k=0;k<size;k++)
280  {
281  tmp=M[j*size+k];
282  M[j*size+k]=M[i*size+k];
283  M[i*size+k]=tmp;
284  }
285  j=size-1;
286  }
287  }
288  }
289  max=0;
290  for(k=0;k<size;k++)
291  if (fabs(max)<fabs(M[i*size+k])) max=fabs(M[i*size+k]);
292  if (max!=0)
293  for(k=0;k<size;k++)
294  M[i*size+k]/=max;
295  for(j=i+1;j<size-1;j++)
296  {
297  if (M[j*size+i]!=0)
298  {
299  koef=M[i*size+i]/M[j*size+i];
300  koef=fabs(koef);
301  if((M[i*size+i]>=0 && M[j*size+i]>=0) ||
302  (M[i*size+i]<0 && M[j*size+i]<0)) koef*=-1;
303  for(k=i;k<size;k++)
304  M[j*size+k]=M[j*size+k]*koef + M[i*size+k];
305 // M[j*size+i] = 0;
306  }
307  }
308  }
309  for(i=size-1-1;i>=0;i--)
310  {
311  koef=0;
312  for(j=i+1;j<size-1;j++)
313  {
314  koef=koef+R[j]*M[i*size+j];
315  }
316  if (!(DBL_EQ(M[i*size+i],0)))
317  R[i]=(M[i*size + size-1]-koef)/M[i*size+i];
318  else
319  {
320  if (koef==0 && M[i*size + size-1]==0)
321  return 2;
322  else
323  return 0;
324  }
325  }
326  xfree(M);
327  return res;
328 }
329 */
330 
331 //=============================================================================
332 // ANGLE BETWEEN TWO VECTORS
333 // !!! THIS FUNCTION IS NOT USED !!!
334 //=============================================================================
335 /*
336 double get_vectors_angle( double u[ 3 ], double v[ 3 ] )
337 {
338  double a,b,fi,p;
339  a = scalar_product (u, v);
340  b = vector_length( u ) * vector_length( v );
341  p = a / b;
342  if (p > 1) p = 1;
343  if (p < -1) p = -1;
344  fi = acos( p );
345  return fi * 180 / M_PI;
346 }
347 */
348 
349 //=============================================================================
350 // MATRIX TIMES MATRIX
351 // !!! THIS FUNCTION IS NOT USED !!!
352 //=============================================================================
353 /*
354 void matrix_x_matrix(double *A,int ra, int ca,
355  double *B, int rb, int cb, double *X)
356 {
357  int i,j,k;
358  OLD_ASSERT(!(ca != rb),"Matrix A has different number of columns than matrix B rows in the function matrix_x_matrix()\n");
359  for (i = 0; i < ra; i++)
360  for (j = 0; j < cb; j++)
361  {
362  X[ i* cb + j] = 0;
363  for (k = 0; k < rb; k++)
364  X[ i * cb + j] += A[ i * ca + k] * B[ k * cb + j];
365  }
366  return;
367 }
368 */
369 
370 //-----------------------------------------------------------------------------
371 // vim: set cindent:
void vector_product(double u[], double v[], double x[])
Definition: math_fce.cc:66
static double Inverse3(SmallMtx3 a, SmallMtx3 b)
Definition: math_fce.cc:138
#define SUBDET2(i, j, k, l)
Definition: math_fce.h:59
SmallVec3_t * SmallMtx3
Definition: math_fce.h:31
SmallVec4_t * SmallMtx4
Definition: math_fce.h:32
void normalize_vector(double u[])
Definition: math_fce.cc:46
double vector_length(double v[])
Definition: math_fce.cc:32
void scale_vector(double u[], double k)
Definition: math_fce.cc:58
Global macros to enhance readability and debugging, general constants.
static double Inverse2(SmallMtx2 a, SmallMtx2 b)
Definition: math_fce.cc:121
double scalar_product(double u[], double v[])
Definition: math_fce.cc:39
void MatInverse(int n, double **a)
Definition: math_fce.cc:225
void PrintSmallMatrix(double *mtx, int size)
Definition: math_fce.cc:212
#define NUM_ZERO
Numerical helpers.
Definition: math_fce.h:41
SmallVec2_t * SmallMtx2
Definition: math_fce.h:30
double Det3(SmallMtx3 a)
Definition: math_fce.cc:92
double MatrixInverse(double *a, double *b, int size)
Definition: math_fce.cc:102
void vector_difference(double u[], double v[], double x[])
Definition: math_fce.cc:78
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:234
static double Inverse4(SmallMtx4 a, SmallMtx4 b)
Definition: math_fce.cc:164
void printf(BasicWriter< Char > &w, BasicCStringRef< Char > format, ArgList args)
Definition: printf.h:444