Tomato
KWUtil.hxx
1 //
2 // KWUtil.hxx
3 // TomatoLib
4 //
5 // Created by Konrad Werys on 12/8/16.
6 // Copyright © 2016 Konrad Werys. All rights reserved.
7 //
8 
9 #ifndef KWUtil_hxx
10 #define KWUtil_hxx
11 
12 //#include "KWUtil.h"
13 
14 /***********************/
15 /* copyArrayToArray */
16 /***********************/
17 
18 template< typename TYPE1, typename TYPE2 >
19 void KWUtil::copyArrayToArray(int nSamples, TYPE1 *arrayTo, const TYPE2 *arrayFrom){
20 
21  if (arrayFrom == NULL){
22  arrayTo = NULL;
23  return;
24  }
25 
26  for (int i = 0; i < nSamples; i++)
27  arrayTo[i] = (TYPE1)arrayFrom[i];
28 }
29 
30 /***********************/
31 /* printVector */
32 /***********************/
33 
34 template<typename TYPE>
35 void KWUtil::printVector(const std::string& name, const std::vector<TYPE> vector){
36  std::cout << name << " ";
37  for (unsigned int i = 0; i < vector.size(); ++i){
38  std::cout << " " << vector.at(i);
39  }
40  std::cout << std::endl;
41 }
42 
43 template<typename TYPE>
44 void KWUtil::printVectorNewline(const std::string &name, const std::vector<TYPE> vector){
45  std::cout << name << std::endl;
46  for (unsigned int i = 0; i < vector.size(); ++i){
47  std::cout << " " << vector.at(i) << std::endl;
48  }
49 }
50 
51 /***********************/
52 /* printArray 1D */
53 /***********************/
54 
55 template< typename TYPE >
56 void KWUtil::printArray(int nSamples, const TYPE *myarray){
57  for (int i=0; i<nSamples; i++){
58  std::cout << myarray[i] << " ";
59  }
60 }
61 
62 template< typename TYPE >
63 void KWUtil::printArray(int nSamples, const TYPE *myarray, int width){
64  for (int i=0; i<nSamples; i++){
65  std::cout << std::setw(width) << myarray[i] << " ";
66  }
67 }
68 
69 template< typename TYPE >
70 void KWUtil::printArray(int nSamples, const TYPE *myarray, char* text){
71  std::cout << text;
72  printArray(nSamples, myarray);
73 }
74 
75 template< typename TYPE >
76 void KWUtil::printArray(bool doPrint, int nSamples, const TYPE *myarray){
77  if(doPrint) printArray(nSamples, myarray);
78 }
79 
80 template< typename TYPE >
81 void KWUtil::printArray(bool doPrint, int nSamples, const TYPE *myarray, char* text){
82  if(doPrint) printArray(nSamples, myarray, text);
83 }
84 
85 /***********************/
86 /* printArray 2D */
87 /***********************/
88 
89 template< typename TYPE >
90 void KWUtil::printArray2D(int nRows, int nCols, TYPE **myarray){
91  for(int i = 0; i < nRows; i++){
92  for(int j = 0; j < nCols; j++)
93  std::cout << myarray[i][j] << "\t";
94  std::cout << std::endl;
95  }
96  std::cout << std::endl;
97 }
98 
99 template< typename TYPE >
100 void KWUtil::printArray2D(int nRows, int nCols, TYPE **myarray, char * text){
101  std::cout << text;
102  printArray2D(nRows, nCols, myarray);
103 }
104 
105 template< typename TYPE >
106 void KWUtil::printArray2D(bool doPrint, int nRows, int nCols, TYPE **myarray){
107  if(doPrint) printArray2D(nRows, nCols, myarray);
108 }
109 
110 template< typename TYPE >
111 void KWUtil::printArray2D(bool doPrint, int nRows, int nCols, TYPE **myarray, char * text){
112  if(doPrint) printArray2D(nRows, nCols, myarray, text);
113 }
114 
115 
116 template< typename TYPE >
117 void KWUtil::printStdVector(const std::vector<TYPE> myvector){
118  int nSamples = myvector.size();
119  KWUtil::printArray(nSamples, &myvector[0]);
120 }
121 
122 template< typename TYPE >
123 void KWUtil::printStdVector(const std::vector<TYPE> myvector, char* text){
124  int nSamples = myvector.size();
125  KWUtil::printArray(nSamples, &myvector[0], text);
126 }
127 
128 template< typename TYPE >
129 void KWUtil::printStdVector(bool doPrint, const std::vector<TYPE> myvector){
130  int nSamples = myvector.size();
131  KWUtil::printArray(doPrint, nSamples, &myvector[0]);
132 }
133 
134 template< typename TYPE >
135 void KWUtil::printStdVector(bool doPrint, const std::vector<TYPE> myvector, char* text){
136  int nSamples = myvector.size();
137  KWUtil::printArray(doPrint, nSamples, &myvector[0], text);
138 }
139 
140 /***********************/
141 /* calculations */
142 /***********************/
143 
144 template< typename TYPE >
145 void KWUtil::swap(TYPE &a, TYPE &b){
146  TYPE temp = a;
147  a = b;
148  b = temp;
149 }
150 
151 template< typename TYPE >
152 TYPE KWUtil::max(TYPE a, TYPE b){
153  return (a > b) ? a : b;
154 }
155 
156 template< typename TYPE >
157 TYPE KWUtil::min(TYPE a, TYPE b){
158  return (a < b) ? a : b;
159 }
160 
161 template< typename TYPE >
162 TYPE KWUtil::calcSumArray(int nSamples, const TYPE *myarray){
163  TYPE sum = TYPE(); // 0
164  for(long i = 0; i < nSamples; i++){
165  sum+= myarray[i];
166  }
167  return sum;
168 }
169 
170 template< typename TYPE >
171 double KWUtil::calcMeanArray(int nSamples, const TYPE *myarray){
172  if (nSamples == 0)
173  return 0.0;
174  else if (nSamples == 1)
175  return myarray[0];
176  else
177  return (calcSumArray(nSamples,myarray)/nSamples);
178 }
179 
180 template< typename TYPE >
181 double KWUtil::calcMedianArray(int nSamples, const TYPE *myarray){
182  if (nSamples == 0){
183  return 0.0;
184  } else if (nSamples == 1){
185  return myarray[0];
186  } else {
187  TYPE *sortedArray = new TYPE[nSamples];
188  KWUtil::copyArrayToArray(nSamples, sortedArray, myarray);
189  KWUtil::quickSort(nSamples, sortedArray);
190  double result;
191  if(nSamples % 2) {
192  // if odd number of samples, return the middle
193  result = sortedArray[(nSamples - 1) / 2];
194  } else {
195  // if even number of samples, return mean of the two in the middle
196  int pos = nSamples/2-1;
197  result = (sortedArray[pos] + sortedArray[pos+1]) / 2;
198  }
199  delete[] sortedArray;
200  return result;
201  }
202 }
203 
204 template< typename TYPE >
205 double KWUtil::calcStandardDeviationArray(int nSamples, const TYPE *myarray) {
206  if (nSamples < 2) {
207  return 0.0;
208  } else {
209  TYPE mymean = KWUtil::calcMeanArray(nSamples, myarray);
210  TYPE sum = 0.0;
211  for (unsigned int i = 0; i < nSamples; ++i){
212  sum = sum + (myarray[i] - mymean) * (myarray[i] - mymean);
213  }
214  return sqrt(sum/(nSamples-1));
215  }
216 }
217 
218 template< typename TYPE >
219 // calculate R square confidence map
220 double KWUtil::calcR2ss(int nSamples, const TYPE *fitted, const TYPE *ysignal){
221  // equation taken from wikipedia https://en.wikipedia.org/wiki/Coefficient_of_determination
222  TYPE meanYsignal = TYPE(); // 0
223  TYPE SStot = TYPE(); // 0
224  TYPE SSres = TYPE(); // 0
225 
226  for (int i = 0; i < nSamples; i++){
227  meanYsignal = meanYsignal + ysignal[i];
228  }
229  meanYsignal = meanYsignal/nSamples;
230  for (int i = 0; i < nSamples; i++){
231  SStot = SStot + (ysignal[i] - meanYsignal)*(ysignal[i] - meanYsignal);
232  }
233  for (int i = 0; i < nSamples; i++){
234  SSres = SSres + (ysignal[i] - fitted[i])*(ysignal[i] - fitted[i]);
235  }
236  if (SStot == 0)
237  return 0.0;
238  else
239  return 1-SSres/SStot;
240 }
241 
242 // calculate R square confidence map
243 template< typename TYPE >
244 double KWUtil::calcR2cor(int nSamples, const TYPE *fitted, const TYPE *ysignal){
245  // calculated from squared pearson correlation coefficient
246  // R2 = (covYF / (stdY*stdF))^2 = covYF^2 / (std2Y * std2F)
247  // covYF = sum((y-meany)(calcCostValue-meanf))/N
248  // stdY = sqrt(sum((y-meany)/N)
249  // std2Y = sum((y-meany)/N
250  // Ns are reduced, so not used in this calculations
251 
252  TYPE meanY = 0, meanF = 0, sumYY = 0, sumFF = 0, covYF = 0; //xf =sum((y-meany)(calcCostValue-meanf))
253  for (int i = 0; i < nSamples; i++){
254  meanY = meanY + ysignal[i];
255  meanF = meanF + fitted[i];
256  }
257  meanY = meanY/nSamples;
258  meanF = meanF/nSamples;
259  for (int i = 0; i < nSamples; i++){
260  sumYY = sumYY + (ysignal[i] - meanY)*(ysignal[i] - meanY);
261  sumFF = sumFF + (fitted[i] - meanF)*(fitted[i] - meanF);
262  covYF = covYF + (ysignal[i] - meanY)*(fitted[i] - meanF);
263  }
264  if ((sumYY == 0) || (sumFF == 0))
265  return 0.0;
266  else
267  return covYF*covYF/(sumYY*sumFF);
268 }
269 
270 template< typename TYPE >
271 int KWUtil::linearFit(
272  int nSamples,
273  const TYPE *datax,
274  const TYPE *datay,
275  TYPE &a,
276  TYPE &b,
277  TYPE &siga,
278  TYPE &sigb,
279  TYPE &R2,
280  TYPE &chi2){
281  // inspired by NR
282  // zero the output variables
283  a = 0;
284  b = 0;
285  siga = 0;
286  sigb = 0;
287  R2 = 0;
288  chi2 = 0;
289 
290  // helper variables
291  TYPE Sx = KWUtil::calcSumArray(nSamples, datax);
292  TYPE Sy = KWUtil::calcSumArray(nSamples, datay);
293  TYPE St2 = 0;
294 
295  // fitting
296  for (size_t i = 0; i < nSamples; i++){
297  TYPE t = datax[i] - Sx/nSamples;
298  St2 += t * t;
299  b += t * datay[i];
300  }
301  b /= St2;
302  a = (Sy - Sx * b) / nSamples;
303 
304  // standard errors
305  for (size_t i = 0; i < nSamples; i++){
306  chi2 += (datay[i] - a - b * datax[i]) * (datay[i] - a - b * datax[i]);
307  }
308  TYPE sigdat = 1;
309  if (nSamples > 2) sigdat = std::sqrt(chi2 / (nSamples - 2));
310  siga = sigdat * std::sqrt((1 + Sx * Sx / (nSamples * St2)) / nSamples);
311  sigb = sigdat * std::sqrt(1 / St2);
312 
313  // R2
314  TYPE *fitted = new TYPE[nSamples];
315  for (size_t i = 0; i < nSamples; i++){
316  fitted[i] = a + b * datax[i];
317  }
318  R2 = KWUtil::calcR2cor(nSamples, fitted, datay);
319  delete [] fitted;
320 
321  return 0; // EXIT_SUCCESS
322 }
323 
324 template< typename TYPE >
325 double KWUtil::SKPLinReg(const TYPE *datax, const TYPE *datay, int nSamples, TYPE &rslope, TYPE &roffset){
326  // sets slope and offset and returns pearson's R between two vectors [0:n-1] elements each.
327  TYPE yt, xt, syy = 0.0, sxy = 0.0, sxx = 0.0, ay = 0.0, ax = 0.0;
328  if(nSamples<2) return(0.0); // sanity check
329  for (long j = 0; j < nSamples; j++) // caclualte means
330  {
331  ax += datax[j];
332  ay += datay[j];
333  }
334  ax /= nSamples;
335  ay /= nSamples;
336  for (long j = 0; j < nSamples; j++)
337  {
338  xt = datax[j]-ax;
339  yt = datay[j]-ay;
340  sxx += xt*xt;
341  syy += yt*yt;
342  sxy += xt*yt;
343  }
344  // error return in case no adequate diviation
345  if (sxx*syy <=0)
346  {
347  rslope = 0.0;
348  roffset = ay;
349  return(0);
350  }
351  // else normal return
352  rslope = sxy/sxx;
353  roffset = ay-rslope*ax;
354  return (sxy/sqrt(sxx*syy)); // correlation = (sxy/sqrt(sxx*syy)
355 } //double SKPLinReg(double *x,double *y, int n, double &rslope, double &roffset)
356 
357 template< typename TYPE >
358 void KWUtil::SKPsort(int nSamples, const TYPE *myarray, int *index){
359  // sorts array [1..nSamples+1] :/
360  int l,j,ir,indxt,i;
361  double q;
362  for (j=1;j<=nSamples;j++) index[j]=j;
363  if (nSamples == 1) return;
364  l=(nSamples >> 1) + 1;
365  ir=nSamples;
366  for (;;)
367  {
368  if (l > 1)
369  q=myarray[(indxt=index[--l])];
370  else {
371  q=myarray[(indxt=index[ir])];
372  index[ir]=index[1];
373  if (--ir == 1) {
374  index[1]=indxt;
375  return;
376  }
377  }
378  i=l;
379  j=l << 1;
380  while (j <= ir) {
381  if (j < ir && myarray[index[j]] < myarray[index[j+1]]) j++;
382  if (q < myarray[index[j]]) {
383  index[i]=index[j];
384  j += (i=j);
385  }
386  else j=ir+1;
387  }
388  index[i]=indxt;
389  }
390 }
391 
392 template< typename TYPE >
393 void KWUtil::quickSort(int nSamples, TYPE *myarray){
394  KWUtil::quickSort(myarray, 0, nSamples-1);
395 }
396 
397 template< typename TYPE >
398 void KWUtil::quickSortIndex(int nSamples, TYPE *myarray, int *indexArray){
399  for (int i = 0; i < nSamples; i++){
400  indexArray[i] = i;
401  }
402  KWUtil::quickSortIndex(myarray, indexArray, 0, nSamples-1);
403 }
404 
405 // private
406 template< typename TYPE >
407 void KWUtil::quickSort(TYPE arr[], int left, int right) {
408  // http://www.algolist.net/Algorithms/Sorting/Quicksort
409  int i = left, j = right;
410  TYPE tmp;
411  TYPE pivot = arr[(left + right) / 2];
412 
413  /* partition */
414  while (i <= j) {
415  while (arr[i] < pivot)
416  i++;
417  while (arr[j] > pivot)
418  j--;
419  if (i <= j) {
420  tmp = arr[i];
421  arr[i] = arr[j];
422  arr[j] = tmp;
423  i++;
424  j--;
425  }
426  };
427 
428  /* recursion */
429  if (left < j)
430  quickSort(arr, left, j);
431  if (i < right)
432  quickSort(arr, i, right);
433 }
434 
435 template< typename TYPE >
436 void KWUtil::quickSortIndex(TYPE arr[], int indexArr[], int left, int right) {
437  // http://www.algolist.net/Algorithms/Sorting/Quicksort
438  int i = left, j = right, tmpIdx;
439  TYPE tmp;
440  TYPE pivot = arr[(left + right) / 2];
441 
442  /* partition */
443  while (i <= j) {
444  while (arr[i] < pivot)
445  i++;
446  while (arr[j] > pivot)
447  j--;
448  if (i <= j) {
449  // array
450  tmp = arr[i];
451  arr[i] = arr[j];
452  arr[j] = tmp;
453  // indexArray
454  tmpIdx = indexArr[i];
455  indexArr[i] = indexArr[j];
456  indexArr[j] = tmpIdx;
457  i++;
458  j--;
459  }
460  };
461 
462  /* recursion */
463  if (left < j)
464  quickSortIndex(arr, indexArr, left, j);
465  if (i < right)
466  quickSortIndex(arr, indexArr, i, right);
467 }
468 
469 template< typename TYPE >
470 void KWUtil::printKW(bool doPrint, char* fmt, ...){
471  if (doPrint){
472  va_list args;
473  va_start(args,fmt);
474  vprintf(fmt,args);
475  va_end(args);
476  }
477 }
478 
479 template< typename TYPE >
480 TYPE KWUtil::calcFeFromT2(TYPE T2){
481  return 45 * std::pow(T2, -1.22);
482 }
483 
484 template< typename TYPE >
485 TYPE KWUtil::calcFeErrorFromT2(TYPE T2, TYPE deltaT2){
486  return 45 * 1.22 * std::pow(T2, -2.22) * deltaT2;
487 }
488 template< typename TYPE >
489 int KWUtil::calculateFitError(int nSamples, int nDims, const TYPE* jacobian, TYPE mFuncNorm, TYPE* fitError){
490  // compute matrix g=J^{T}J
491  TYPE* g = new TYPE[nDims*nDims];
492  TYPE* g_inv = new TYPE[nDims*nDims];
493  for (int i = 0; i < nDims; i++){
494  for (int j = 0; j < nDims; j++){
495  g[j + i * nDims] = 0;
496  for (int k = 0; k < nSamples; k++){
497  g[j + i * nDims] += jacobian[i + k * nDims] * jacobian[j + k * nDims];
498  }
499  }
500  }
501  int exit = 1; // EXIT_FAILURE
502  if (nDims == 2){
503  exit = calcMatrixInverse2x2(g, g_inv);
504  }
505  if (nDims == 3){
506  exit = calcMatrixInverse3x3(g, g_inv);
507  }
508 
509  if (exit == 0) { // EXIT SUCCESS
510  for (int i = 0; i < nDims; i++){
511  int pos = i * nDims + i;
512  fitError[i] = mFuncNorm * sqrt(g_inv[pos]/(nSamples-nDims));
513  }
514  }
515 
516  delete [] g;
517  delete [] g_inv;
518  return exit;
519 }
520 
521 template< typename TYPE >
522 int KWUtil::calcMatrixInverse2x2(const TYPE *matrix, TYPE *matrixInverse){
523 
524  for (int i = 0; i < 4; ++i){
525  matrixInverse[i] = 0;
526  }
527 
528  const TYPE *a = matrix; // just for shorter equations
529  TYPE det = a[0] * a[3] - a[1] * a[2];
530  if (fabs(det) < std::numeric_limits<TYPE>::min() || det==0)
531  return 1; // EXIT_FAILURE
532 
533  matrixInverse[0] = a[3]/det;
534  matrixInverse[1] = -a[1]/det;
535  matrixInverse[2] = -a[2]/det;
536  matrixInverse[3] = a[0]/det;
537 
538  return 0; // EXIT_SUCCESS
539 }
540 
541 template< typename TYPE >
542 int KWUtil::calcMatrixInverse3x3(const TYPE *matrix, TYPE *matrixInverse){
543 
544  for (int i = 0; i < 9; ++i){
545  matrixInverse[i] = 0;
546  }
547 
548  const TYPE *a = matrix; // just for shorter equations
549  TYPE det = a[0]*a[4]*a[8] - a[0]*a[5]*a[7] - a[1]*a[3]*a[8] + a[1]*a[5]*a[6] + a[2]*a[3]*a[7] - a[2]*a[4]*a[6];
550 
551  if (fabs(det) < std::numeric_limits<TYPE>::min())
552  return 1; // EXIT_FAILURE
553 
554  matrixInverse[0] = (a[4]*a[8] - a[5]*a[7])/det;
555  matrixInverse[1] = -(a[1]*a[8] - a[2]*a[7])/det;
556  matrixInverse[2] = (a[1]*a[5] - a[2]*a[4])/det;
557  matrixInverse[3] = -(a[3]*a[8] - a[5]*a[6])/det;
558  matrixInverse[4] = (a[0]*a[8] - a[2]*a[6])/det;
559  matrixInverse[5] = -(a[0]*a[5] - a[2]*a[3])/det;
560  matrixInverse[6] = (a[3]*a[7] - a[4]*a[6])/det;
561  matrixInverse[7] = -(a[0]*a[7] - a[1]*a[6])/det;
562  matrixInverse[8] = (a[0]*a[4] - a[1]*a[3])/det;
563 
564  return 0; // EXIT_SUCCESS
565 }
566 
567 template< typename TYPE >
568 TYPE KWUtil::getChiSqrt(TYPE lastFValue, int nSamples){
569  return sqrt(lastFValue/(nSamples-1));
570 }
571 
572 template< typename TYPE >
573 TYPE KWUtil::MOLLI_min(TYPE a[], int n, int *indm)
574 {
575  int i=0;
576  TYPE mval=a[0];
577  *indm=0;
578  for (i=0;i<n;i++)if(mval>a[i]){*indm=i;mval=a[i];};
579  return(mval);
580 }
581 
582 template< typename TYPE >
583 TYPE KWUtil::MOLLI_max(TYPE a[], int n, int *indm)
584 {
585  int i=0;
586  TYPE mval=a[0];
587  *indm=0;
588  for (i=0;i<n;i++)if(mval<a[i]){*indm=i;mval=a[i];};
589  return(mval);
590 }
591 
592 template< typename TYPE >
593 TYPE KWUtil::dicomTime2Seconds(std::string dicomTimeString){
594  TYPE dicomTimeSeconds = 0;
595 
596  if (dicomTimeString.length() < 1) {
597  // printf("ERROR: Dicom string should not be empty");
598  return dicomTimeSeconds; // return 0
599  }
600 
601  if (dicomTimeString.length() != 6 && dicomTimeString[6] != '.'){
602  printf("ERROR: Dicom string should have a dot at the sixth index");
603  return dicomTimeSeconds; // return 0
604  }
605 
606  std::string hours = dicomTimeString.substr(0,2);
607  std::string minutes = dicomTimeString.substr(2,2);
608  std::string seconds = dicomTimeString.substr(4,2);
609  std::string milliseconds = "0";
610  if (dicomTimeString.length() > 6) {
611  milliseconds = dicomTimeString.substr(6, dicomTimeString.length()-6);
612  }
613 
614  TYPE hoursInSeconds = 60 * 60 * KWUtil::StringToNumber<TYPE>(hours);
615  TYPE minutesInSeconds = 60 * KWUtil::StringToNumber<TYPE>(minutes);
616  TYPE secondsInSeconds = 1 *KWUtil::StringToNumber<TYPE>(seconds);
617  TYPE millisecondsInSeconds = KWUtil::StringToNumber<TYPE>(milliseconds);
618 
619  dicomTimeSeconds = hoursInSeconds + minutesInSeconds + secondsInSeconds + millisecondsInSeconds;
620 
621  return dicomTimeSeconds;
622 }
623 
624 // for threading
625 // from https://solarianprogrammer.com/2012/02/27/cpp-11-thread-tutorial-part-2/
626 template < typename TYPE >
627 std::vector<int> KWUtil::bounds(int parts, int mem) {
628  std::vector<int>bnd;
629  int delta = mem / parts;
630  int reminder = mem % parts;
631  int N1 = 0, N2 = 0;
632  bnd.push_back(N1);
633  for (int i = 0; i < parts; ++i) {
634  N2 = N1 + delta;
635  if (i == parts - 1)
636  N2 += reminder;
637  bnd.push_back(N2);
638  N1 = N2;
639  }
640  return bnd;
641 }
642 
643 template < typename TYPE >
644 bool KWUtil::array_expect_near(
645  int nElements,
646  const TYPE *array1,
647  const TYPE *array2,
648  TYPE abs_error,
649  const std::string& comment) {
650  for (int i = 0; i < nElements; i ++){
651  TYPE abs_diff = std::abs(array1[i] - array2[i]);
652  if ( abs_diff > abs_error){
653  std::cout << std::setprecision(std::numeric_limits<double>::digits10 + 1) <<
654  "The difference between array1 and array2 at element "
655  << i << " evaluates to " << abs_diff << " which exceeds tolerance, where\n"
656  << "array1[" << i << "] evaluates to " << array1[i] << "\n"
657  << "array2[" << i << "] evaluates to " << array2[i] << "\n"
658  << "tolerance evaluates to " << abs_error << "\n"
659  << comment << std::endl;
660  return false;
661  }
662  }
663  return true;
664 }
665 
666 #endif
static void printVectorNewline(const std::string &name, const std::vector< TYPE > vector)
Definition: KWUtil.hxx:44
static void printVector(const std::string &name, const std::vector< TYPE > vector)
Definition: KWUtil.hxx:35
static int calcMatrixInverse3x3(const TYPE *matrix, TYPE *matrixInverse)
Definition: KWUtil.hxx:542
static int calcMatrixInverse2x2(const TYPE *matrix, TYPE *matrixInverse)
Definition: KWUtil.hxx:522