{"id":19832050,"url":"https://github.com/danielmartensson/embeddedlapack","last_synced_at":"2025-05-01T16:32:58.547Z","repository":{"id":55926859,"uuid":"165274437","full_name":"DanielMartensson/EmbeddedLapack","owner":"DanielMartensson","description":"Linear algebra for embedded system with MATLAB style","archived":false,"fork":false,"pushed_at":"2023-12-21T17:48:15.000Z","size":21402,"stargazers_count":122,"open_issues_count":0,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-12-21T19:54:17.795Z","etag":null,"topics":["c","embedded-systems","linear-algebra","mathematics"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DanielMartensson.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-01-11T16:27:57.000Z","updated_at":"2023-12-20T11:11:39.000Z","dependencies_parsed_at":"2023-12-21T19:55:01.086Z","dependency_job_id":null,"html_url":"https://github.com/DanielMartensson/EmbeddedLapack","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanielMartensson%2FEmbeddedLapack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanielMartensson%2FEmbeddedLapack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanielMartensson%2FEmbeddedLapack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DanielMartensson%2FEmbeddedLapack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DanielMartensson","download_url":"https://codeload.github.com/DanielMartensson/EmbeddedLapack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224267672,"owners_count":17283364,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","embedded-systems","linear-algebra","mathematics"],"created_at":"2024-11-12T11:36:10.694Z","updated_at":"2024-11-12T11:36:11.300Z","avatar_url":"https://github.com/DanielMartensson.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EmbeddedLapack \n\n![](https://raw.githubusercontent.com/DanielMartensson/EmbeddedAlgebra/master/C-symbol.png)  ![](https://raw.githubusercontent.com/DanielMartensson/EmbeddedAlgebra/master/CPU-symbol.png) \n![](https://raw.githubusercontent.com/DanielMartensson/EmbeddedAlgebra/master/Matrix-symbol.png)\n\n## Introduction\nThis is a C-library for linear algebra which is meant to be used for embedded systems such as AVR, PIC, ARM etc. The library is\nbuilt easily and follows the MATLAB/Octave \"standard\" as much as it can when computing and solving matrices.\nThis C-library uses Lapack subroutines from Lapack version 3.2.1 and I have changed this Lapack library so it does not require a specific CPU/computer or asking for an operating system. I want this library to have 100% portability.  \n\n* Easy to use in the editor\n* Basic easy code to read if needed\n* Follows MATLAB commands as much as it can\n* Can be used with a compiler as low as C99 standard, default is C11\n* Simple use for most common matrix algebra\n* Using minimal but necessary Lapack subroutines as possible due to the small amout of flash memory it will be loaded into.\n\nIf you are looking for an even smaller library that performs the same job (except for imaginary eigenvectors), then CControl will be a good alternative. CControl is more applied and contains lots of examples such as system identification, path finding, linear algebra, filtering, control engineering, optimization etc. CControl does not use LAPACK therefore it fits even on smaller microcontrollers. Please fork and star so more people can see CControl. \n\n2023-07-31: This library is now supporting LAPACK for embedded systems.\nhttps://github.com/DanielMartensson/CControl\n\n## Status of the project\n\nSupport for this project is ongoing and is subject to found bugs or when new features are added otherwise everything on the main branch is currently functional.\n\n## Tested on the following without any compile errors\n* Windows 7 MinGW 64 bit\n* Ubuntu Linux GCC 64 bit\n* Raspberry Pi B+/Zero W GCC-ARM 32 bit\n* STM32 GCC-ARM-Atollic 32 bit\n\n## Installation for testing and buildning your matrix algebra\n\nStep 1: Download EmbeddedLapack folder\n\nStep 2: Open EmbeddedLapack and go to Debug folder\n\nStep 3:\nExecute this to compile\n```\nmake clean\nmake\n```\n\n## Installation to an embedded target\nStep 1: Download EmbeddedLapack folder\n\nStep 2: Move the folders \"Lapack\" and \"LinearAlgebra\" from the folder EmbeddedLapack -\u003e src, to the same folder as your main.c file is located.\n\nStep 3: Link \"-lm\" like this.\n\n![](https://raw.githubusercontent.com/DanielMartensson/EmbeddedLapack/master/Markering_006.png)\n\nStep 4: Paste in \"#include \"LinearAlgebra/declareFunctions.h\"\" in top of your main.c file\n\n![](https://raw.githubusercontent.com/DanielMartensson/EmbeddedLapack/master/Markering_008.png)\n\nDone! Now you can compile.\n\n## Functions\n\n```\nvoid tran(double* A, int row, int column);\nvoid print(double* A, int row, int column);\nvoid linsolve(double* A, double* X, double* B, int row, int column_b);\nvoid svd(double* A, double* U, double* S, double* V, int row, int column);\nvoid diag(double* A, double* B, int row_b, int column_b);\nvoid qr(double* A, double* Q, double* R, int row, int column);\nvoid triu(double* A, double* B, int shift, int row, int column);\nvoid eye(double* A, int row, int column);\nvoid mul(double* A, double* B, bool elementWise, double* C, int row_a, int column_a, int column_b);\nvoid scale(double* A, double scalar, int row, int column);\nvoid sub(double* A, double* B, double* C, int row_a, int column_a, int column_b);\nvoid lu(double* A, double* L, double* U, double* P, int row, int column);\nvoid tril(double* A, double* B, int shift, int row, int column);\nvoid inv(double* A, int row);\nvoid chol(double* A, double* L, int row);\ndouble det(double *A, int row);\nvoid toeplitz(double* A, double* B, int length);\nvoid hankel(double* A, double* H, int length, int step);\nvoid cut(double* A, int row, int column, double* B, int start_row, int stop_row, int start_column, int stop_column);\nvoid diagpower(double* A, double p, int row, int column);\nvoid eabs(double* A, int row, int column);\nvoid add(double* A, double* B, double* C, int row_a, int column_a, int column_b);\nvoid copy(double* A, double* B, int row, int column);\nvoid cofact(double* A, double* CO, int row, int column);\nvoid mdiag(double* A, double* B, int row, int column);\ndouble dot(double* A, double* B, int row);\nvoid horzcat(double* A, double* B, double* C, int row_a, int column_a, int column_b);\nvoid maxvector(double* A, int row, double* val, int* index);\nvoid minvector(double* A, int row, double* val, int* index);\ndouble norm(double* A, int row, char* P);\nvoid ones(double* A, int row, int column);\nvoid pinv(double* A, int row, int column);\nvoid power(double* A, int row, int column, double value);\nvoid repmat(double* A, int row, int column, int horz, int vert, double* B);\nvoid sqrte(double* A, int row, int column);\nvoid sumrows(double* A, double* B, int row, int column);\nvoid vec(double* A, double* B, int row, int column);\nvoid vertcat(double* A, double* B, double* C, int row_a, int column_a, int row_b);\nvoid zeros(double* A, int row, int column);\nint rank(double* A, int row);\nvoid eig(double* A, double* Ereal, double* Eimag, double* Vreal_left, double* Vimag_left, double* Vreal_right, double* Vimag_right, int row);\nvoid mpower(double* A, int row, int n);\nvoid insert(double* A, double* B, int row_a, int column_a, int column_b, int startRow_b, int startColumn_b);\nvoid move(double* A, int row, int column, int down, int right);\nvoid quadprog(double* H, double* g, double* A, double* ulb_vec, double* uub_vec,  double* ylb_vec, double* yub_vec, int* nWSR, double* u, int columnH, int rowA);\nvoid linprog(double* c, double* A, double* b, double* x, int row_a, int column_a, uint8_t max_or_min, int iteration_limit);\n```\n## Compiler and microprocessor\nWhen you compile this, you need to take respect on this.\n```\n#include \u003cmath.h\u003e  // Need be linked with \"-lm\" when compiling this code\n```\nAlso you need to link the folder \"Include\" located inside EmbeddedLapack -\u003e src -\u003e Lapack. \n\n## Troubleshooting\nIf you declare a matrix or a vector and you use that with this library, but you getting garbage values back. Try to sett all values of the matrix or vector to zeros by using:\n```\nzeros(A, row, column);\n```\nMost of my functions have this algorithm included in the beginning of the functions. \n\n## Examples and how to use\nHere is some examples how to use\n\n## QR-factorization\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\nint main() {\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\t // A matrix with size 6 x 4\n\tdouble A[6*4] = {0.674878,   0.151285,   0.875139,   0.150518,\n\t\t\t0.828102,   0.150747,   0.934674,   0.474325,\n\t\t\t0.476510,   0.914686,   0.740681,   0.060455,\n\t\t\t0.792594,   0.471488,   0.529343,   0.743405,\n\t\t\t0.084739,   0.475160,   0.419307,   0.628999,\n\t\t\t0.674878,   0.151285,   0.875139,   0.150518};\n\n\tdouble Q[6*6];\n\tdouble R[6*4];\n\n\t// Solve\n\tqr(A, Q, R, 6, 4);\n\n\t// Print\n\tprint(A, 6,4);\n\tprint(Q, 6,6);\n\tprint(R, 6,4);\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n```\n## Singular Value Decomposition\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\n\n#define row 17\n#define column 15\n\nint main( )\n{\n\n   clock_t start, end;\n   float cpu_time_used;\n   start = clock();\n\n   double A[row*column] = {\n0.84245,     0.23405   ,  0.69751 ,    0.27905   ,  0.18851  ,   0.61018    , 0.62182  ,   0.71839   ,  0.79161     ,0.56156   ,  0.83395   , 0.092388     , 0.8511    , 0.44826    , 0.82158,\n0.84614  ,   0.15947  ,  0.096336  ,   0.80793  ,   0.35114 ,    0.42583 ,     0.2134 ,    0.75324   ,  0.31391 ,    0.22892  ,   0.94773 ,    0.81204   ,  0.62554 ,    0.28367   ,  0.26637,\n0.26509  ,   0.91429  ,   0.14222  ,   0.28321   ,  0.11607 ,    0.41188 ,    0.10071 ,    0.18224   ,  0.75723 ,    0.89125  ,   0.62494 ,    0.83016   ,  0.46448  ,   0.73119  ,   0.10982,\n0.45197  ,   0.44562  ,   0.27909  ,   0.76019   , 0.014571 ,    0.42705 ,    0.70214 ,    0.64936   ,  0.98451 ,    0.59632  ,   0.07654 ,    0.95633   ,  0.18574   ,  0.92716  ,   0.65401,\n0.48034  ,   0.38327  ,   0.32906  ,   0.34794   ,  0.68673 ,    0.54113 ,    0.34142 ,    0.48561  ,   0.37221 ,    0.16097  ,   0.15569 ,    0.63287  ,   0.17518  ,  0.055447  ,   0.44536,\n0.54119  ,   0.34478   ,  0.53297  ,    0.2796   ,  0.95212 ,     0.5353 ,     0.8202 ,    0.32707  , 0.0062771 ,    0.64993  ,  0.057361 ,    0.59959  ,   0.16867  ,   0.67892  ,   0.52882,\n0.082573  ,   0.96676  ,  0.080315  ,   0.48813   ,  0.33496 ,     0.4436 ,    0.01436 ,    0.89664   ,  0.49167 ,    0.37092  ,   0.31586 ,    0.54683  ,   0.65159  ,   0.38531  ,   0.20697,\n0.35775  ,   0.42437  ,   0.79392  ,   0.49724    , 0.01319 ,  0.0074932 ,    0.66462 ,     0.6506   ,   0.9889 ,    0.27213  ,   0.99607 ,    0.68418  ,   0.70238  ,   0.81493  ,   0.46062,\n0.22609  ,   0.59924  ,   0.74631  ,   0.81566   ,  0.92784 ,    0.47376 ,    0.83531 ,    0.47031   ,  0.97093 ,    0.44778  ,   0.42997 ,    0.71882  ,   0.36504  ,   0.34216  ,   0.95187,\n0.87475  ,   0.22003  ,   0.71901  ,   0.90968   ,  0.27265 ,    0.16106 ,    0.21283 ,    0.14918   ,  0.16776 ,    0.83038  ,   0.43605 ,    0.85075  ,   0.54771  ,   0.77479  ,   0.24739,\n0.21203  ,   0.65616  ,   0.63534  ,   0.57569   ,  0.22113 ,    0.48063 ,    0.24207 ,    0.54873   ,  0.25042 ,    0.82671  ,   0.88986 ,    0.41674  ,   0.95235  ,   0.89875  ,   0.15004,\n0.86164  ,   0.89058  ,   0.66423  ,   0.60958   ,  0.47708 ,    0.18674 ,    0.66359 ,    0.92383  ,   0.48073 ,    0.79466  ,   0.64519 ,    0.69876  , 0.0066587  ,   0.55114  ,   0.10979,\n0.35586  ,   0.94772  ,   0.28888  ,   0.63119   ,  0.42774 ,    0.82597 ,    0.90274 ,    0.40152  ,   0.96414 ,    0.84376  ,  0.028355 ,   0.040771   ,  0.85359  ,   0.92875  ,   0.32352,\n0.39274  ,   0.27788  ,   0.41549  ,   0.90884  ,  0.042767 ,    0.64168 ,   0.086933 ,    0.47941  ,   0.91491 ,    0.26425  ,   0.11667 ,    0.49996   ,  0.12644  ,   0.87136  ,   0.30768,\n0.86527 ,    0.92393  ,   0.47957  ,   0.32175  ,   0.87965 ,    0.13719 ,     0.4014 ,    0.25277  ,   0.83936 ,    0.73476  ,   0.97174 ,    0.65243   ,  0.85813  ,   0.62705  , 0.0013063,\n0.34355 ,    0.43424  ,   0.34352  ,   0.34341  ,   0.94343 ,    0.45452  ,     0.343  ,    0.1243   ,   0.12522 ,    0.214343 ,   0.12432 ,    0.54534   ,  0.12442  ,   0.12467  , 0.9988,\n0.84245,     0.23405   ,  0.69751 ,    0.27905   ,  0.18851  ,   0.61018    , 0.62182  ,   0.71839   ,  0.79161     ,0.56156   ,  0.83395   , 0.092388     , 0.8511    , 0.44826    , 0.82158};\n\n\n   double U[row*row];\n   double S[row*column];\n   double V[column*column];\n\n   // Solve\n   svd(A, U, S, V, row, column);\n\n   // print\n   print(U, row, row);\n   print(S, row, column);\n   print(V, column, column);\n\n   end = clock();\n   cpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n   printf(\"\\nTotal speed  was %f,\", cpu_time_used);\n   return 0;\n}\n\n```\n\n## Solve AX=B\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\nint main( )\n{\n    clock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\t\n\n\t/*\n\t * A matrix 3x3 - Need to be square\n\t */\n\tdouble A[3*3] = {3, 4, 1,\n\t\t\t6, 10, 2,\n\t\t\t5, 3, 2\n\t};\n\n\n\t/*\n\t * Solution 3x4\n\t */\n\tdouble X[3*4];\n\n\t/*\n\t * B matrix 3x4\n\t */\n\tdouble B[3*4] = {4, 3, 22, 5,\n\t\t\t5, 3, 2, 5,\n\t\t\t3, 4, 5, 3};\n\n\t/*\n\t * Solve\n\t */\n\tlinsolve(A, X, B, 3, 4); // 3 = A row, 4 = B column\n\n\t/*\n\t * Print solution\n\t */\n\tprint(X, 3, 4);\n\t\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n    return 0;\n}\n```\n## Find eigenvalues and eigenvectors\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\nint main( ) {\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\t// Need to be square\n\tdouble A[6*6] = {4,3,1,4,2,23,\n\t\t\t 6,3,-2,3,5,8,\n\t\t\t 1,3,6,2,3,2,\n\t\t\t 2,5,6,7,4,4,\n\t\t\t 4,6,-88,6,4,6,\n\t\t\t 2,1,44,54,3,2\n\t};\n\n\n\tdouble Ereal[6]; // Eigenvalues real\n\tdouble Eimag[6]; // Eigenvalues imag part\n\tdouble Vreal_left[6*6]; // Eigenvectors real left\n\tdouble Vimag_left[6*6]; // Eigenvectors imag left\n\tdouble Vreal_right[6*6]; // Eigenvectors real right\n\tdouble Vimag_right[6*6]; // Eigenvectors imag right\n\n\t// Solve\n\teig(A,Ereal,Eimag,Vreal_left,Vimag_left,Vreal_right,Vimag_right,6);\n\n\t// Print\n\tprint(A, 6, 6);\n\tprint(Ereal, 6, 1);\n\tprint(Eimag, 6, 1);\n\tprint(Vreal_left, 6,6);\n\tprint(Vimag_left, 6,6);\n\tprint(Vreal_right, 6,6);\n\tprint(Vimag_right, 6,6);\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n```\n\n## LU-factorization\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\nint main( ) {\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\tdouble A[5*4] = {2, 7, 6, 2,\n\t\t\t 9, 5, 1, 3,\n\t\t\t 4, 3, 8, 4,\n\t\t\t 5, 6, 7, 8,\n\t\t\t 2, 2, -3,-1\n\t};\n\n\tdouble U[4*4];\n\tdouble L[5*4];\n\tdouble P[5*5];\n\n\t// Solve\n\tlu(A, L, U, P, 5, 4);\n\n\t// Print\n\tprint(A, 5,4);\n\tprint(U, 4,4);\n\tprint(L, 5,4);\n\tprint(P, 5,5);\n\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n\n```\n\n## Observer Kalman IDentification(OKID) and Eigensystem Realization Theory(ERA)\nThis will estimate a 2x2 state space model from measurement data\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\n\nint main() {\n\n\t/*\n\t * G(s) = 1/(s^2 + 1s + 3)  - Model\n\t * y = measured output values\n\t * u = measured input values\n\t */\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\tdouble y[144] = { 0.00000, 0.49525, 1.43863, 2.13779, 2.30516, 2.05713,\n\t\t\t1.69220, 1.45608, 1.42777, 1.54146, 1.67927, 1.75624, 1.75400,\n\t\t\t1.70478, 1.65394, 1.62996, 1.63549, 1.65594, 1.67426, 1.68125,\n\t\t\t1.67752, 1.66930, 1.66285, 1.66102, 1.66300, 1.66621, 1.66842,\n\t\t\t1.66880, 1.66786, 1.66664, 1.66591, 1.66588, 1.66629, 1.66675,\n\t\t\t1.66698, 1.66695, 1.66678, 1.66661, 1.66654, 1.66657, 1.66664,\n\t\t\t1.66670, 1.66672, 1.66670, 1.66667, 1.66665, 1.66665, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66666, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667 };\n\n\tdouble u[144] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5 };\n\n\t// Toeplitz matrix\n\tdouble toe[144 * 144];\n\ttoeplitz(u, toe, 144);\n\n\t// Upper triangular\n\tdouble tru[144 * 144];\n\ttriu(toe, tru, 0, 144, 144);\n\n\t// inverse\n\tinv(tru, 144);\n\n\t// Multiplication\n\tdouble g[144];\n\tmul(y, tru, false, g, 1, 144, 144);\n\n\t// Create hankel\n\tdouble H0[144 * 144];\n\thankel(g, H0, 144, 1);\n\tdouble H1[144 * 144];\n\thankel(g, H1, 144, 2);\n\n\t// Cut hankel into half\n\tdouble H0_half[72 * 72];\n\tdouble H1_half[72 * 72];\n\tcut(H0, 144, 144, H0_half, 0, 71, 0, 71);\n\tcut(H1, 144, 144, H1_half, 0, 71, 0, 71);\n\n\t// Do SVD\n\tdouble U[72 * 72];\n\tdouble S[72 * 72];\n\tdouble V[72 * 72];\n\tsvd(H0_half, U, S, V, 72, 72);\n\n\t// Model reduction to second order model\n\tdouble Un[72 * 2];\n\tdouble Sn[2 * 2];\n\tdouble Vn[72 * 2];\n\tcut(U, 72, 72, Un, 0, 71, 0, 1);\n\tcut(S, 72, 72, Sn, 0, 1, 0, 1);\n\tcut(V, 72, 72, Vn, 0, 71, 0, 1);\n\n\t// Create A, B, C\n\tdouble Sn_sqrt_negative[2 * 2];\n\tdouble Sn_sqrt_positive[2 * 2];\n\tcopy(Sn, Sn_sqrt_negative, 2,2);\n\tcopy(Sn, Sn_sqrt_positive, 2,2);\n\tdiagpower(Sn_sqrt_negative, -0.5, 2, 2);\n\tdiagpower(Sn_sqrt_positive, 0.5, 2, 2);\n\n\t/*\n\t * C = Un*Sn^(1/2);\n\t * Cd = C(1, 1:2)\n\t */\n\tdouble C[72 * 2];\n\tdouble Cd[1 * 2];\n\tmul(Un, Sn_sqrt_positive, false, C, 72, 2, 2);\n\tcut(C, 72, 2, Cd, 0, 0, 0, 1);\n\n\t/*\n\t * Ad = Sn^(-1/2)*Un'*H1*Vn*Sn^(-1/2);\n\t */\n\tdouble A[72 * 2];\n\tdouble A1[72 * 2];\n\tdouble Ad[2 * 2];\n\tdouble Ad1[2 * 2];\n\tmul(Vn, Sn_sqrt_negative, false, A, 72, 2, 2);\n\tmul(H1_half, A, false, A1, 72, 72, 2);\n\ttran(Un, 72, 2);\n\tmul(Un, A1, false, Ad1, 2, 72, 2);\n\tmul(Sn_sqrt_negative, Ad1, false, Ad, 2, 2, 2);\n\n\t/*\n\t * B = Sn^(1/2)*Vn'\n\t * Bd = B(:, 1);\n\t */\n\tdouble B[2 * 72];\n\tdouble Bd[2 * 1];\n\ttran(Vn, 72, 2);\n\tmul(Sn_sqrt_positive, Vn, false, B, 2, 2, 72);\n\tcut(B, 2, 72, Bd, 0, 1, 0, 0);\n\n\t/*\n\t * Print A, B, C\n\t */\n\tprintf(\"A Matrix: \\n\");\n\tprint(Ad, 2, 2);\n\n\tprintf(\"B Matrix: \\n\");\n\tprint(Bd, 2, 1);\n\n\tprintf(\"C Matrix: \\n\");\n\tprint(Cd, 1, 2);\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n```\n\n## Basic Model Predictive Control example\nGiven a state space model and a reference point, this example can compute your best input signals U depending on how you set your control- and predictive horizons column_o and column_h\n\n```\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\n/*\n * Here you can set the sizes for the matrices\n */\n\n#define row_a 2 // A row\n#define column_a 2 // A column\n\n#define row_b 2 // B row, the same row as A.\n#define column_b 1 // B column, the same column as D\n\n#define row_c 1 // C row, the same row as D\n#define column_c 2 // C column, the same column as A\n\n/*\n * Create a state space model - discrete\n */\ndouble A[row_a * column_a] = { -0.099272, 0.029481,\n\t\t               -0.088444, -0.158234};\n\ndouble B[row_b * column_b] = { 0.366424,\n\t\t\t       0.029481\n};\n\ndouble C[row_c * column_c] = {1, 0};\n\ndouble D[row_c * column_b] = {0};\n\ndouble X[row_a] = {0, 0};\n\ndouble R =  6;\n\n// Create the length of the observability matrix, notice it will have the dimension (row_o * row_c + row_c) x column_b\n#define row_o 20\n\n// Create the widt of the lower triangular toeplitz H matrix, notice that it will have the dimension (row_o * row_c + row_c) x (column_h * column_b)\n#define column_h 19 // column_h \u003c row_o - always!\n\n// Define the column of the reference vector - Standard is 1\n#define column_ry 1\n\nint main() {\n\n\t/*\n\t * Model predictive control\n\t */\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\t/*\n\t * Create the Observabillity matrix and the\n\t */\n\n\tdouble O[(row_o * row_c) * row_a];\n\tdouble O_[(row_o * row_c) * row_a]; // This is for the lower triangular toeplitz matrix\n\tdouble A_[row_a * column_a];\n\tdouble C_[row_c * column_c];\n\n\tfor (int i = 1; i \u003c= row_o; i++) {\n\t\tcopy(A, A_, row_a, column_a); // Copy A -\u003e A_\n\t\tmpower(A_, row_a, i); // Power A_^i\n\t\tmul(C, A_, false, C_, row_c, column_c, column_a); // C_ = C*A_\n\t\tinsert(C_, O, row_c, column_c, row_a, (i-1)*row_c, 0); // Insert O = [CA^1; CA^2; CA^3; ... ; CA^row_o];\n\n\t\tcopy(A, A_, row_a, column_a); // Copy A -\u003e A_\n\t\tmpower(A_, row_a, i - 1); // Power A_^(i-1)\n\t\tmul(C, A_, false, C_, row_c, column_c, column_a); // C_ = C*A_\n\t\tinsert(C_, O_, row_c, column_c, row_a, (i-1)*row_c, 0); // Insert O_ = [CA^0; CA^1; CA^2; ... ; CA^(row_o-1)];\n\t}\n\n\t//print(O, row_o * row_c, row_a);\n\n\t/*\n\t * Create the lower triangular toeplitz matrix\n\t */\n\tdouble H[(row_o * row_c) * (column_h * column_b)];\n        zeros(H, row_o * row_c, column_h * column_b);\n\n\t// T = O_*B - Observabillity matrix times B\n        double T[(row_o * row_c) * column_b];\n\tmul(O_, B, false, T, row_o * row_c, row_a, column_b);\n\n\n\t// Lower triangular toeplitz matrix of T = [C*A^0*B; C*A^1*B; C*A^2*B; C*A^3*B; ...; C*A^(row_o-1)*B]\n\tfor (int j = 0; j \u003c column_h; j++){\n\t\tinsert(T, H, row_o * row_c, column_b, column_h * column_b, 0, j*column_b);\n\t\tmove(T, row_o * row_c, column_b, row_c , 0);\n\t}\n\n\t//print(H, row_o * row_c, column_h * column_b); // H matrix\n\n\n\t/*\n\t * Compute U = pinv(H)*(Ry*R - O*X), where R is our reference vector, X is our initial state vector\n\t */\n\n\tpinv(H, row_o * row_c, column_h * column_b); // Pseudo inverse of H. Using the SVD method\n\n\tdouble Ry[(row_o * row_c)*column_ry];\n\tones(Ry, row_o * row_c, column_ry);\n\tscale(Ry, R, row_o * row_c, column_ry); // Ry*R = Ry\n\n\tdouble OX[(row_o * row_c)*column_ry];\n\tmul(O, X, false, OX, row_o * row_c, row_a, column_ry); // O*X\n\n\tdouble Ry_OX[(row_o * row_c)*column_ry];\n\tsub(Ry, OX, Ry_OX, row_o * row_c, column_ry, column_ry); // Ry-O*X\n\n\tdouble U[(column_h * column_b)*column_ry];\n\tmul(H, Ry_OX, false, U, column_h * column_b, row_o * row_c, column_ry); // U = pinv(H)*(Ry-O*X);\n\n\t/*\n\t * Our best input values\n\t */\n\tprint(U, column_h * column_b, column_ry);\n\n\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n```\n## Simulation between EmbeddedLapack (C), Armadillo (C++) and GNU Octave\nHere is a simulation of a step response that turning into an impulse response. Then we take the SVD of that impulse response.\n\n### EmbeddedLapack\n```\n13:15:53 **** Incremental Build of configuration Debug for project EmbeddedLapack ****\nmake all \nBuilding file: ../src/main.c\nInvoking: Cross GCC Compiler\ngcc -std=c11 -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF\"src/main.d\" -MT\"src/main.o\" -o \"src/main.o\" \"../src/main.c\"\nFinished building: ../src/main.c\n \nBuilding target: EmbeddedLapack\nInvoking: Cross GCC Linker\ngcc  -o \"EmbeddedLapack\"  ./src/LinearAlgebra/add.o ./src/LinearAlgebra/chol.o ./src/LinearAlgebra/cofact.o ./src/LinearAlgebra/copy.o ./src/LinearAlgebra/cut.o ./src/LinearAlgebra/det.o ./src/LinearAlgebra/diag.o ./src/LinearAlgebra/diagpower.o ./src/LinearAlgebra/dot.o ./src/LinearAlgebra/eabs.o ./src/LinearAlgebra/eig.o ./src/LinearAlgebra/eye.o ./src/LinearAlgebra/hankel.o ./src/LinearAlgebra/horzcat.o ./src/LinearAlgebra/insert.o ./src/LinearAlgebra/inv.o ./src/LinearAlgebra/linsolve.o ./src/LinearAlgebra/lu.o ./src/LinearAlgebra/maxvector.o ./src/LinearAlgebra/mdiag.o ./src/LinearAlgebra/minvector.o ./src/LinearAlgebra/move.o ./src/LinearAlgebra/mpower.o ./src/LinearAlgebra/mul.o ./src/LinearAlgebra/norm.o ./src/LinearAlgebra/ones.o ./src/LinearAlgebra/pinv.o ./src/LinearAlgebra/power.o ./src/LinearAlgebra/print.o ./src/LinearAlgebra/qr.o ./src/LinearAlgebra/rank.o ./src/LinearAlgebra/repmat.o ./src/LinearAlgebra/scale.o ./src/LinearAlgebra/sqrte.o ./src/LinearAlgebra/sub.o ./src/LinearAlgebra/sumrows.o ./src/LinearAlgebra/svd.o ./src/LinearAlgebra/toeplitz.o ./src/LinearAlgebra/tran.o ./src/LinearAlgebra/tril.o ./src/LinearAlgebra/triu.o ./src/LinearAlgebra/vec.o ./src/LinearAlgebra/vertcat.o ./src/LinearAlgebra/zeros.o  ./src/Lapack/Scr/dbdsqr.o ./src/Lapack/Scr/dgebak.o ./src/Lapack/Scr/dgebal.o ./src/Lapack/Scr/dgebd2.o ./src/Lapack/Scr/dgebrd.o ./src/Lapack/Scr/dgeev.o ./src/Lapack/Scr/dgehd2.o ./src/Lapack/Scr/dgehrd.o ./src/Lapack/Scr/dgelq2.o ./src/Lapack/Scr/dgelqf.o ./src/Lapack/Scr/dgeqr2.o ./src/Lapack/Scr/dgeqrf.o ./src/Lapack/Scr/dgesv.o ./src/Lapack/Scr/dgesvd.o ./src/Lapack/Scr/dgetf2.o ./src/Lapack/Scr/dgetrf.o ./src/Lapack/Scr/dgetrs.o ./src/Lapack/Scr/dhseqr.o ./src/Lapack/Scr/disnan.o ./src/Lapack/Scr/dlabad.o ./src/Lapack/Scr/dlabrd.o ./src/Lapack/Scr/dlacpy.o ./src/Lapack/Scr/dladiv.o ./src/Lapack/Scr/dlaexc.o ./src/Lapack/Scr/dlahqr.o ./src/Lapack/Scr/dlahr2.o ./src/Lapack/Scr/dlaisnan.o ./src/Lapack/Scr/dlaln2.o ./src/Lapack/Scr/dlange.o ./src/Lapack/Scr/dlanv2.o ./src/Lapack/Scr/dlapy2.o ./src/Lapack/Scr/dlaqr0.o ./src/Lapack/Scr/dlaqr1.o ./src/Lapack/Scr/dlaqr2.o ./src/Lapack/Scr/dlaqr3.o ./src/Lapack/Scr/dlaqr4.o ./src/Lapack/Scr/dlaqr5.o ./src/Lapack/Scr/dlarf.o ./src/Lapack/Scr/dlarfb.o ./src/Lapack/Scr/dlarfg.o ./src/Lapack/Scr/dlarfp.o ./src/Lapack/Scr/dlarft.o ./src/Lapack/Scr/dlarfx.o ./src/Lapack/Scr/dlartg.o ./src/Lapack/Scr/dlas2.o ./src/Lapack/Scr/dlascl.o ./src/Lapack/Scr/dlaset.o ./src/Lapack/Scr/dlasq1.o ./src/Lapack/Scr/dlasq2.o ./src/Lapack/Scr/dlasq3.o ./src/Lapack/Scr/dlasq4.o ./src/Lapack/Scr/dlasq5.o ./src/Lapack/Scr/dlasq6.o ./src/Lapack/Scr/dlasr.o ./src/Lapack/Scr/dlasrt.o ./src/Lapack/Scr/dlassq.o ./src/Lapack/Scr/dlasv2.o ./src/Lapack/Scr/dlaswp.o ./src/Lapack/Scr/dlasy2.o ./src/Lapack/Scr/dorg2r.o ./src/Lapack/Scr/dorgbr.o ./src/Lapack/Scr/dorghr.o ./src/Lapack/Scr/dorgl2.o ./src/Lapack/Scr/dorglq.o ./src/Lapack/Scr/dorgqr.o ./src/Lapack/Scr/dorm2r.o ./src/Lapack/Scr/dormbr.o ./src/Lapack/Scr/dormhr.o ./src/Lapack/Scr/dorml2.o ./src/Lapack/Scr/dormlq.o ./src/Lapack/Scr/dormqr.o ./src/Lapack/Scr/dtrevc.o ./src/Lapack/Scr/dtrexc.o ./src/Lapack/Scr/ieeeck.o ./src/Lapack/Scr/iladlc.o ./src/Lapack/Scr/iladlr.o ./src/Lapack/Scr/ilaenv.o ./src/Lapack/Scr/ilaslc.o ./src/Lapack/Scr/ilaslr.o ./src/Lapack/Scr/iparmq.o ./src/Lapack/Scr/sgebak.o ./src/Lapack/Scr/sgebal.o ./src/Lapack/Scr/sgeev.o ./src/Lapack/Scr/sgehd2.o ./src/Lapack/Scr/sgehrd.o ./src/Lapack/Scr/sgeqr2.o ./src/Lapack/Scr/sgetf2.o ./src/Lapack/Scr/sgetrf.o ./src/Lapack/Scr/shseqr.o ./src/Lapack/Scr/sisnan.o ./src/Lapack/Scr/slabad.o ./src/Lapack/Scr/slacpy.o ./src/Lapack/Scr/sladiv.o ./src/Lapack/Scr/slaexc.o ./src/Lapack/Scr/slahqr.o ./src/Lapack/Scr/slahr2.o ./src/Lapack/Scr/slaisnan.o ./src/Lapack/Scr/slaln2.o ./src/Lapack/Scr/slange.o ./src/Lapack/Scr/slanv2.o ./src/Lapack/Scr/slapy2.o ./src/Lapack/Scr/slaqr0.o ./src/Lapack/Scr/slaqr1.o ./src/Lapack/Scr/slaqr2.o ./src/Lapack/Scr/slaqr3.o ./src/Lapack/Scr/slaqr4.o ./src/Lapack/Scr/slaqr5.o ./src/Lapack/Scr/slarf.o ./src/Lapack/Scr/slarfb.o ./src/Lapack/Scr/slarfg.o ./src/Lapack/Scr/slarfp.o ./src/Lapack/Scr/slarft.o ./src/Lapack/Scr/slarfx.o ./src/Lapack/Scr/slartg.o ./src/Lapack/Scr/slascl.o ./src/Lapack/Scr/slaset.o ./src/Lapack/Scr/slassq.o ./src/Lapack/Scr/slaswp.o ./src/Lapack/Scr/slasy2.o ./src/Lapack/Scr/sorg2r.o ./src/Lapack/Scr/sorghr.o ./src/Lapack/Scr/sorgqr.o ./src/Lapack/Scr/sorm2r.o ./src/Lapack/Scr/sormhr.o ./src/Lapack/Scr/sormqr.o ./src/Lapack/Scr/strevc.o ./src/Lapack/Scr/strexc.o  ./src/Lapack/Install/dlamch.o ./src/Lapack/Install/slamch.o  ./src/Lapack/F2c/d_lg10.o ./src/Lapack/F2c/d_sign.o ./src/Lapack/F2c/exit_.o ./src/Lapack/F2c/f77_aloc.o ./src/Lapack/F2c/i_nint.o ./src/Lapack/F2c/pow_dd.o ./src/Lapack/F2c/pow_di.o ./src/Lapack/F2c/pow_ri.o ./src/Lapack/F2c/r_lg10.o ./src/Lapack/F2c/r_sign.o ./src/Lapack/F2c/s_cat.o ./src/Lapack/F2c/s_cmp.o ./src/Lapack/F2c/s_copy.o  ./src/Lapack/Blas/daxpy.o ./src/Lapack/Blas/dcopy.o ./src/Lapack/Blas/ddot.o ./src/Lapack/Blas/dgemm.o ./src/Lapack/Blas/dgemv.o ./src/Lapack/Blas/dger.o ./src/Lapack/Blas/dnrm2.o ./src/Lapack/Blas/drot.o ./src/Lapack/Blas/dscal.o ./src/Lapack/Blas/dswap.o ./src/Lapack/Blas/dtrmm.o ./src/Lapack/Blas/dtrmv.o ./src/Lapack/Blas/dtrsm.o ./src/Lapack/Blas/idamax.o ./src/Lapack/Blas/isamax.o ./src/Lapack/Blas/lsame.o ./src/Lapack/Blas/saxpy.o ./src/Lapack/Blas/scopy.o ./src/Lapack/Blas/sdot.o ./src/Lapack/Blas/sgemm.o ./src/Lapack/Blas/sgemv.o ./src/Lapack/Blas/sger.o ./src/Lapack/Blas/snrm2.o ./src/Lapack/Blas/srot.o ./src/Lapack/Blas/sscal.o ./src/Lapack/Blas/sswap.o ./src/Lapack/Blas/strmm.o ./src/Lapack/Blas/strmv.o ./src/Lapack/Blas/strsm.o ./src/Lapack/Blas/xerbla.o  ./src/main.o   -lm\nFinished building target: EmbeddedLapack\n \n\n13:15:54 Build Finished. 0 errors, 0 warnings. (took 563ms)\n-------------------------------------------------------------------------------------------------\n#include \u003ctime.h\u003e\n#include \"LinearAlgebra/declareFunctions.h\"\n\n\nint main() {\n\n\t/*\n\t * y = measured output values\n\t * u = measured input values\n\t */\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\tdouble y[144] = { 0.00000, 0.49525, 1.43863, 2.13779, 2.30516, 2.05713,\n\t\t\t1.69220, 1.45608, 1.42777, 1.54146, 1.67927, 1.75624, 1.75400,\n\t\t\t1.70478, 1.65394, 1.62996, 1.63549, 1.65594, 1.67426, 1.68125,\n\t\t\t1.67752, 1.66930, 1.66285, 1.66102, 1.66300, 1.66621, 1.66842,\n\t\t\t1.66880, 1.66786, 1.66664, 1.66591, 1.66588, 1.66629, 1.66675,\n\t\t\t1.66698, 1.66695, 1.66678, 1.66661, 1.66654, 1.66657, 1.66664,\n\t\t\t1.66670, 1.66672, 1.66670, 1.66667, 1.66665, 1.66665, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66666, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667 };\n\n\tdouble u[144] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5 };\n\n\t// Toeplitz matrix\n\tdouble toe[144 * 144];\n\ttoeplitz(u, toe, 144);\n\n\t// Upper triangular\n\tdouble tru[144 * 144];\n\ttriu(toe, tru, 0, 144, 144);\n\n\t// inverse\n\tinv(tru, 144);\n\n\t// Multiplication\n\tdouble g[144];\n\tmul(y, tru, false, g, 1, 144, 144);\n\n\t// Create hankel\n\tdouble H0[144 * 144];\n\thankel(g, H0, 144, 1);\n\tdouble H1[144 * 144];\n\thankel(g, H1, 144, 2);\n\n\t// Cut hankel into half\n\tdouble H0_half[72 * 72];\n\tdouble H1_half[72 * 72];\n\tcut(H0, 144, 144, H0_half, 0, 71, 0, 71);\n\tcut(H1, 144, 144, H1_half, 0, 71, 0, 71);\n\n\t// Do SVD\n\tdouble U[72 * 72];\n\tdouble S[72 * 72];\n\tdouble V[72 * 72];\n\tsvd(H0_half, U, S, V, 72, 72);\n\n\n\t/*\n\t * Collect all singular values\n\t */\n\tdouble B[72*1];\n\tmdiag(S, B, 72, 72);\n\tprint(B, 72, 1);\n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\treturn 0;\n}\n-----------------------------------------------------------------------------------------\n0.407681034422245847 \n0.238123608303610790 \n0.000011845213482911 \n0.000011666082457162 \n0.000008883438909084 \n0.000008631689698976 \n0.000007734962524526 \n0.000007511490842174 \n0.000007488406152694 \n0.000007407380025140 \n0.000006121475748177 \n0.000005522531730072 \n0.000005116007541059 \n0.000004797631110215 \n0.000004784509561686 \n0.000004473545605918 \n0.000004342577631107 \n0.000004064797343488 \n0.000004063644188412 \n0.000003865877590879 \n0.000003653037790875 \n0.000003637842419990 \n0.000003386516594547 \n0.000003130366457631 \n0.000002977246663017 \n0.000002882530710919 \n0.000002538497184049 \n0.000002505827486202 \n0.000002309697235112 \n0.000001808839531249 \n0.000001797106897059 \n0.000001565211931281 \n0.000001555312183134 \n0.000001408267510825 \n0.000001365907202482 \n0.000001302339916052 \n0.000001237594241464 \n0.000001108041144894 \n0.000001061571017183 \n0.000000937397714155 \n0.000000871167733055 \n0.000000834535321843 \n0.000000760280816693 \n0.000000676935925759 \n0.000000657762114094 \n0.000000612476643054 \n0.000000541625110851 \n0.000000514281053563 \n0.000000439069844454 \n0.000000370412162418 \n0.000000023499011157 \n0.000000018764254299 \n0.000000001444867446 \n0.000000001262488202 \n0.000000000836084418 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n0.000000000000000000 \n\n\nTotal speed  was 0.005488,\n```\n\n## Armadillo\n```\n13:11:58 **** Incremental Build of configuration Debug for project TestSVD ****\nmake all \nBuilding file: ../src/TestSVD.cpp\nInvoking: Cross G++ Compiler\ng++ -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF\"src/TestSVD.d\" -MT\"src/TestSVD.o\" -o \"src/TestSVD.o\" \"../src/TestSVD.cpp\"\nFinished building: ../src/TestSVD.cpp\n \nBuilding target: TestSVD\nInvoking: Cross G++ Linker\ng++  -o \"TestSVD\"  ./src/TestSVD.o   -larmadillo\nFinished building target: TestSVD\n \n\n13:12:04 Build Finished. 0 errors, 0 warnings. (took 6s.452ms)\n\n------------------------------------------------------------------------------\n/*\n * Simulation with Armadillo C++\n */\n\n#include \u003ciostream\u003e\n#include \u003carmadillo\u003e\n#include \u003ctime.h\u003e\nusing namespace std;\nusing namespace arma;\n\nint main() {\n\n\tclock_t start, end;\n\tfloat cpu_time_used;\n\tstart = clock();\n\n\t/*\n\t * Declare vector and matrix\n\t */\n\tmat u(1, 144);\n\tmat y(1, 144);\n\tmat toe(144, 144);\n\tmat triup(144, 144);\n\tmat inverse(144, 144);\n\tmat g(1, 144); // markov parameters\n\tvec g_v; // Impulse vector\n\tmat H1(144, 144); // Hankel 1 of markov parameters\n\tmat H1_half(72, 72);\n\n\t/*\n\t * Step singal\n\t */\n\n\tdouble output[144] = { 0.00000, 0.49525, 1.43863, 2.13779, 2.30516, 2.05713,\n\t\t\t1.69220, 1.45608, 1.42777, 1.54146, 1.67927, 1.75624, 1.75400,\n\t\t\t1.70478, 1.65394, 1.62996, 1.63549, 1.65594, 1.67426, 1.68125,\n\t\t\t1.67752, 1.66930, 1.66285, 1.66102, 1.66300, 1.66621, 1.66842,\n\t\t\t1.66880, 1.66786, 1.66664, 1.66591, 1.66588, 1.66629, 1.66675,\n\t\t\t1.66698, 1.66695, 1.66678, 1.66661, 1.66654, 1.66657, 1.66664,\n\t\t\t1.66670, 1.66672, 1.66670, 1.66667, 1.66665, 1.66665, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66666, 1.66666,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667, 1.66667,\n\t\t\t1.66667, 1.66667, 1.66667, 1.66667, 1.66667 };\n\n\tdouble input[144] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n\t\t\t5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };\n\n\t// Insert\n\tfor (int i = 0; i \u003c 144; i++) {\n\t\tu(0, i) = input[i];\n\t\ty(0, i) = output[i];\n\t}\n\n\t// Toeplitz\n\ttoe = toeplitz(u);\n\n\t// Triangular upper\n\ttriup = trimatu(toe);\n\n\t// inverse\n\tinverse = inv(triup);\n\n\t// impulse\n\tg = y * inverse;\n\n\t// Turn it to a vector\n\tg_v = trans(g);\n\n\t// Create a initial matrix\n\tint length = g_v.n_rows;\n\tfor (int i = 0; i \u003c length; i++) {\n\t\tfor (int j = 0; j \u003c length; j++) {\n\t\t\tif (j + i + 1 \u003e= length) {\n\t\t\t\tH1(i, j) = 0;\n\t\t\t} else {\n\t\t\t\tH1(i, j) = g_v(j + i + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t// cut\n\tH1_half = H1(span(0, 71), span(0, 71));\n\n\tmat U;\n\tvec s;\n\tmat V;\n\n\tsvd(U, s, V, H1_half);\n\n\ts.print(\"s-matrix: \"); \n\n\tend = clock();\n\tcpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;\n\tprintf(\"\\nTotal speed  was %f,\", cpu_time_used);\n\n\treturn 0;\n}\n-------------------------------------------------------------------------------------\ns-matrix: \n   4.0768e-01\n   2.3812e-01\n   1.1845e-05\n   1.1666e-05\n   8.8834e-06\n   8.6317e-06\n   7.7350e-06\n   7.5115e-06\n   7.4884e-06\n   7.4074e-06\n   6.1215e-06\n   5.5225e-06\n   5.1160e-06\n   4.7976e-06\n   4.7845e-06\n   4.4735e-06\n   4.3426e-06\n   4.0648e-06\n   4.0636e-06\n   3.8659e-06\n   3.6530e-06\n   3.6378e-06\n   3.3865e-06\n   3.1304e-06\n   2.9772e-06\n   2.8825e-06\n   2.5385e-06\n   2.5058e-06\n   2.3097e-06\n   1.8088e-06\n   1.7971e-06\n   1.5652e-06\n   1.5553e-06\n   1.4083e-06\n   1.3659e-06\n   1.3023e-06\n   1.2376e-06\n   1.1080e-06\n   1.0616e-06\n   9.3740e-07\n   8.7117e-07\n   8.3454e-07\n   7.6028e-07\n   6.7694e-07\n   6.5776e-07\n   6.1248e-07\n   5.4163e-07\n   5.1428e-07\n   4.3907e-07\n   3.7041e-07\n   2.3499e-08\n   1.8764e-08\n   1.4449e-09\n   1.2625e-09\n   8.3608e-10\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n   2.7890e-17\n\nTotal speed  was 0.031486,\n```\n## GNU Octave\n```\nfunction simu()\ntic\n% Input signals\ny =   [0.000000000000000000 \n0.495250000000000024 \n1.438630000000000075 \n2.137789999999999857 \n2.305159999999999876 \n2.057129999999999903 \n1.692199999999999926 \n1.456080000000000041 \n1.427769999999999984 \n1.541460000000000052 \n1.679270000000000040 \n1.756240000000000023 \n1.754000000000000004 \n1.704779999999999962 \n1.653939999999999966 \n1.629960000000000075 \n1.635490000000000110 \n1.655939999999999968 \n1.674260000000000081 \n1.681249999999999911 \n1.677519999999999900 \n1.669300000000000006 \n1.662849999999999939 \n1.661019999999999941 \n1.663000000000000034 \n1.666209999999999969 \n1.668420000000000014 \n1.668800000000000061 \n1.667859999999999898 \n1.666639999999999899 \n1.665910000000000002 \n1.665880000000000027 \n1.666290000000000049 \n1.666749999999999954 \n1.666979999999999906 \n1.666949999999999932 \n1.666779999999999928 \n1.666609999999999925 \n1.666539999999999910 \n1.666570000000000107 \n1.666639999999999899 \n1.666700000000000070 \n1.666719999999999979 \n1.666700000000000070 \n1.666670000000000096 \n1.666649999999999965 \n1.666649999999999965 \n1.666660000000000030 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666660000000000030 \n1.666660000000000030 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096 \n1.666670000000000096];\n      \n% Output signals\nu = linspace(5,5, 144);\n\n% Find impulse response\ng = y'*pinv(triu(toeplitz(u)));\n\n  \n% Create hankel matricies\nH0 = hank(g, 1);\n\n% SVD\n\n[U,S,V] = svd(H0);\ndiag(S)\ntoc\nend\n\n% Create the hankel matrix\nfunction [H] = hank(g, k)\n  H = hankel(g)(1:length(g)/2,1+k:length(g)/2+k);\nendfunction\n\n-----------------------------------------------------------------------------------------\n\u003e\u003e simu\nans =\n\n   4.0768e-01\n   2.3812e-01\n   1.1845e-05\n   1.1666e-05\n   8.8834e-06\n   8.6317e-06\n   7.7350e-06\n   7.5115e-06\n   7.4884e-06\n   7.4074e-06\n   6.1215e-06\n   5.5225e-06\n   5.1160e-06\n   4.7976e-06\n   4.7845e-06\n   4.4735e-06\n   4.3426e-06\n   4.0648e-06\n   4.0636e-06\n   3.8659e-06\n   3.6530e-06\n   3.6378e-06\n   3.3865e-06\n   3.1304e-06\n   2.9772e-06\n   2.8825e-06\n   2.5385e-06\n   2.5058e-06\n   2.3097e-06\n   1.8088e-06\n   1.7971e-06\n   1.5652e-06\n   1.5553e-06\n   1.4083e-06\n   1.3659e-06\n   1.3023e-06\n   1.2376e-06\n   1.1080e-06\n   1.0616e-06\n   9.3740e-07\n   8.7117e-07\n   8.3454e-07\n   7.6028e-07\n   6.7694e-07\n   6.5776e-07\n   6.1248e-07\n   5.4163e-07\n   5.1428e-07\n   4.3907e-07\n   3.7041e-07\n   2.3499e-08\n   1.8764e-08\n   1.4449e-09\n   1.2625e-09\n   8.3608e-10\n   3.9554e-15\n   3.5735e-15\n   3.2392e-15\n   3.0822e-15\n   2.8466e-15\n   2.8323e-15\n   2.4565e-15\n   1.6915e-15\n   1.5164e-15\n   1.2658e-15\n   1.0899e-15\n   1.0884e-15\n   7.1103e-16\n   5.1639e-16\n   4.4834e-16\n   3.3557e-16\n   1.8073e-16\n\nElapsed time is 0.038156 seconds.\n\u003e\u003e\n```\n\n### Result\nEmbeddedLapack is about 6 times faster than Armadillo in this case and EmbeddedLapack is about 7 times faster than GNU Octave\n```\n\u003e\u003e 0.031486/0.005488\nans =  5.7372\n\u003e\u003e 0.038156/0.005488\nans =  6.9526\n```\n\n## Read the .c files\nIf you don't know how to use the function, you can read the .c file of that function that you want to use. It will always be a comment above the function name that describe what you should have as argument, what size and what data type and what it will return. Here is an example.\n```\n#include \"declareFunctions.h\"\n\n/*\n * Cut a matrix A with size row x columns into a matrix B with size (stop_row - start_row + 1) x (stop_column - start_column + 1).\n * Remember! Indexing start and stop are from zero!\n *\n * Example:\n * If you have a matrix A 5 x 6 and you want to cut the values from A to matrix B with size 3 x 3 and you want to start at 0,0 and end at 3,3\n * Code: cut(A, 5, 6, B, 0, 2, 0, 2); // Because indexing from zero\n */\n\nvoid cut(double* A, int row, int column, double* B, int start_row, int stop_row, int start_column, int stop_column) {\n\n\tint in_columns = column;\n\tdouble* data = A + start_row * in_columns + start_column;\n\n\t// Create the output\n\t//double* ptr = B;\n\tint out_columns = stop_column - start_column + 1;\n\n\t// Instead of having two for loops, we just copy the whole row at once.\n\tfor (int i = start_row; i \u003c stop_row + 1; i++) {\n\t\tmemcpy(B, data, sizeof(double) * out_columns);\n\t\tB += out_columns;\n\t\tdata += in_columns;\n\t}\n\n}\n\n```\n\n\n## How can you help and build on this library?\nDownload the clapack.tgz file above, or from here http://www.netlib.org/clapack/. Extract it. Then you can copy and paste the files into the subfolders of folder \"Lapack\" from the EmbeddedLapack -\u003e src folder, so you can have your desire Lapack subroutine to work. You can see how I have done. Just do the same. I just include the Lapack routine I want to use, and then I got lots of errors in the compiling and those errors asking for functions from other .c files located from clapack.tgz file. I copy and paste functions until all errors where gone. \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielmartensson%2Fembeddedlapack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielmartensson%2Fembeddedlapack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielmartensson%2Fembeddedlapack/lists"}