source: cpp/frams/model/similarity/SVD/matrix_tools.cpp @ 568

Last change on this file since 568 was 455, checked in by oriona, 9 years ago

Malloc/free replaced by new/delete, pointers-to-vectors changed into vectors.

  • Property svn:eol-style set to native
File size: 4.8 KB
RevLine 
[349]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5
6#include "matrix_tools.h"
7#include "lapack.h"
8#include <cstdlib>
9#include <cmath>
10#include <cstdio>
[370]11#include <stdlib.h> //malloc(), embarcadero
[368]12#include <math.h> //sqrt(), embarcadero
[349]13
[368]14
[349]15double *Create(int nSize)
16{
[455]17        double *matrix = new double[nSize];
[349]18
[389]19        for (int i = 0; i < nSize; i++)
20        {
21                matrix[i] = 0;
22        }
[349]23
[389]24        return matrix;
[349]25}
26
27double *Multiply(double *&a, double *&b, int nrow, int ncol, double ncol2, double *&toDel, int delSize)
28{
[389]29        double *c = Create(nrow * ncol2);
30        int i = 0, j = 0, k = 0;
[349]31
[389]32        for (i = 0; i < nrow; i++)
33        {
34                for (j = 0; j < ncol2; j++)
35                {
36                        for (k = 0; k < ncol; k++)
37                                c[i * nrow + j] += a[i * nrow + k] * b[k * ncol + j];
38                }
39        }
[349]40
[389]41        if (delSize != 0)
[455]42                delete[] toDel;
[389]43        return c;
[349]44}
45
46double *Power(double *&array, int nrow, int ncol, double pow, double *&toDel, int delSize)
47{
[389]48        double *m_Power = Create(nrow * ncol);
49        if (pow == 2)
50        {
51                for (int i = 0; i < nrow; i++)
52                {
53                        for (int j = 0; j < ncol; j++)
54                        {
55                                m_Power[i * nrow + j] = array[i * nrow + j] * array[i * nrow + j];
56                        }
[349]57
[389]58                }
59        }
60        else
61        {
62                for (int i = 0; i < nrow; i++)
63                {
64                        for (int j = 0; j < ncol; j++)
65                        {
66                                m_Power[i * nrow + j] = sqrt(array[i * nrow + j]);
67                        }
[349]68
[389]69                }
70        }
[349]71
[389]72        if (delSize != 0)
[455]73                delete[] toDel;
[349]74
[389]75        return m_Power;
[349]76}
77
78void Print(double *&mat, int nelems)
79{
[389]80        for (int i = 0; i < nelems; i++)
81                printf("%6.2f ", mat[i]);
82        printf("\n");
[349]83
84}
85
86double *Transpose(double *&A, int arow, int acol)
87{
[389]88        double *result = Create(acol * arow);
[349]89
[389]90        for (int i = 0; i < acol; i++)
91                for (int j = 0; j < arow; j++)
92                {
93                result[i * arow + j] = A[j * acol + i];
94                }
[349]95
[389]96        return result;
[349]97
98}
99
100/** Computes the SVD of the nSize x nSize distance matrix
[389]101                @param vdEigenvalues [OUT] Vector of doubles. On return holds the eigenvalues of the
102                decomposed distance matrix (or rather, to be strict, of the matrix of scalar products
103                created from the matrix of distances). The vector is assumed to be empty before the function call and
104                all variance percentages are pushed at the end of it.
105                @param nSize size of the matrix of distances.
106                @param pDistances [IN] matrix of distances between parts.
107                @param Coordinates [OUT] array of three dimensional coordinates obtained from SVD of pDistances matrix.
108                */
[349]109void MatrixTools::SVD(std::vector<double> &vdEigenvalues, int nSize, double *pDistances, Pt3D *&Coordinates)
110{
[389]111        // compute squares of elements of this array
112        // compute the matrix B that is the parameter of SVD
113        double *B = Create(nSize * nSize);
114        {
115                // use additional scope to delete temporary matrices
116                double *Ones, *Eye, *Z, *D;
[349]117
[389]118                D = Create(nSize * nSize);
119                D = Power(pDistances, nSize, nSize, 2.0, D, nSize);
[349]120
[389]121                Ones = Create(nSize * nSize);
122                for (int i = 0; i < nSize; i++)
123                        for (int j = 0; j < nSize; j++)
124                        {
125                        Ones[i * nSize + j] = 1;
126                        }
[349]127
[389]128                Eye = Create(nSize * nSize);
129                for (int i = 0; i < nSize; i++)
130                {
131                        for (int j = 0; j < nSize; j++)
132                        {
133                                if (i == j)
134                                {
135                                        Eye[i * nSize + j] = 1;
136                                }
137                                else
138                                {
139                                        Eye[i * nSize + j] = 0;
140                                }
141                        }
142                }
[349]143
[389]144                Z = Create(nSize * nSize);
145                for (int i = 0; i < nSize; i++)
146                {
147                        for (int j = 0; j < nSize; j++)
148                        {
149                                Z[i * nSize + j] = 1.0 / ((double)nSize) * Ones[i * nSize + j];
150                        }
151                }
[349]152
[389]153                for (int i = 0; i < nSize; i++)
154                {
155                        for (int j = 0; j < nSize; j++)
156                        {
157                                Z[i * nSize + j] = Eye[i * nSize + j] - Z[i * nSize + j];
158                        }
159                }
[349]160
[389]161                for (int i = 0; i < nSize; i++)
162                {
163                        for (int j = 0; j < nSize; j++)
164                        {
165                                B[i * nSize + j] = Z[i * nSize + j] * -0.5;
166                        }
167                }
[349]168
[389]169                B = Multiply(B, D, nSize, nSize, nSize, B, nSize);
170                B = Multiply(B, Z, nSize, nSize, nSize, B, nSize);
[349]171
[455]172                delete[] Ones;
173                delete[] Eye;
174                delete[] Z;
175                delete[] D;
[389]176        }
[349]177
[389]178        double *Eigenvalues = Create(nSize);
179        double *S = Create(nSize * nSize);
[349]180
[389]181        // call SVD function
182        double *Vt = Create(nSize * nSize);
183        size_t astep = nSize * sizeof(double);
184        Lapack::JacobiSVD(B, astep, Eigenvalues, Vt, astep, nSize, nSize, nSize);
[349]185
[389]186        double *W = Transpose(Vt, nSize, nSize);
[349]187
[455]188        delete[] B;
189        delete[] Vt;
[349]190
[389]191        for (int i = 0; i < nSize; i++)
192                for (int j = 0; j < nSize; j++)
193                {
194                if (i == j)
195                        S[i * nSize + j] = Eigenvalues[i];
196                else
197                        S[i * nSize + j] = 0;
198                }
[349]199
[389]200        // compute coordinates of points
201        double *sqS, *dCoordinates;
202        sqS = Power(S, nSize, nSize, 0.5, S, nSize);
203        dCoordinates = Multiply(W, sqS, nSize, nSize, nSize, W, nSize);
[455]204        delete[] sqS;
[349]205
[389]206        for (int i = 0; i < nSize; i++)
207        {
208                // set coordinate from the SVD solution
209                Coordinates[i].x = dCoordinates[i * nSize];
210                Coordinates[i].y = dCoordinates[i * nSize + 1];
211                if (nSize > 2)
212                        Coordinates[i].z = dCoordinates[i * nSize + 2];
213                else
214                        Coordinates[i].z = 0;
215        }
[349]216
[389]217        // store the eigenvalues in the output vector
218        for (int i = 0; i < nSize; i++)
219        {
220                double dElement = Eigenvalues[i];
221                vdEigenvalues.push_back(dElement);
222        }
[349]223
[455]224        delete[] Eigenvalues;
225        delete[] dCoordinates;
[389]226}
Note: See TracBrowser for help on using the repository browser.