00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #ifndef __small_linalg_h__
00034 #define __small_linalg_h__
00035
00036
00037
00038 #include <stdio.h>
00039 #include <math.h>
00040
00041 #ifdef __cplusplus
00042 extern "C" {
00043 #endif
00044
00045 static inline double
00046 matrix_determinant_3x3d (const double m[9])
00047 {
00048 return m[0]*(m[4]*m[8] - m[5]*m[7])
00049 - m[1]*(m[3]*m[8] - m[5]*m[6])
00050 + m[2]*(m[3]*m[7] - m[4]*m[6]);
00051 }
00052
00053 int matrix_inverse_4x4d (const double m[16], double inv[16]);
00054
00055
00056 static inline int
00057 matrix_inverse_3x3d (const double m[9], double inverse[9])
00058 {
00059 double det = matrix_determinant_3x3d (m);
00060 if (det == 0) return -1;
00061 double det_inv = 1.0 / det;
00062 inverse[0] = det_inv * (m[4]*m[8] - m[5]*m[7]);
00063 inverse[1] = det_inv * (m[2]*m[7] - m[1]*m[8]);
00064 inverse[2] = det_inv * (m[1]*m[5] - m[2]*m[4]);
00065 inverse[3] = det_inv * (m[5]*m[6] - m[3]*m[8]);
00066 inverse[4] = det_inv * (m[0]*m[8] - m[2]*m[6]);
00067 inverse[5] = det_inv * (m[2]*m[3] - m[0]*m[5]);
00068 inverse[6] = det_inv * (m[3]*m[7] - m[4]*m[6]);
00069 inverse[7] = det_inv * (m[1]*m[6] - m[0]*m[7]);
00070 inverse[8] = det_inv * (m[0]*m[4] - m[1]*m[3]);
00071
00072 return 0;
00073 }
00074
00075 static inline int
00076 matrix_inverse_2x2d(const double m[4], double inverse[4])
00077 {
00078 double det = m[0]*m[3] - m[1]*m[2];
00079 if (det == 0) return -1;
00080
00081 inverse[0] = m[3] / det;
00082 inverse[1] = -m[1] / det;
00083 inverse[2] = -m[2] / det;
00084 inverse[3] = m[0] / det;
00085 return 0;
00086 }
00087
00088 static inline void
00089 matrix_vector_multiply_2x2_2d (const double m[4], const double v[2],
00090 double result[2])
00091 {
00092 result[0] = m[0]*v[0] + m[1]*v[1];
00093 result[1] = m[2]*v[0] + m[3]*v[1];
00094 }
00095
00096 static inline void
00097 matrix_vector_multiply_3x3_3d (const double m[9], const double v[3],
00098 double result[3])
00099 {
00100 result[0] = m[0]*v[0] + m[1]*v[1] + m[2]*v[2];
00101 result[1] = m[3]*v[0] + m[4]*v[1] + m[5]*v[2];
00102 result[2] = m[6]*v[0] + m[7]*v[1] + m[8]*v[2];
00103 }
00104
00105 static inline void
00106 matrix_vector_multiply_4x4_4d (const double m[16], const double v[4],
00107 double result[4])
00108 {
00109 result[0] = m[0]*v[0] + m[1]*v[1] + m[2]*v[2] + m[3]*v[3];
00110 result[1] = m[4]*v[0] + m[5]*v[1] + m[6]*v[2] + m[7]*v[3];
00111 result[2] = m[8]*v[0] + m[9]*v[1] + m[10]*v[2] + m[11]*v[3];
00112 result[3] = m[12]*v[0] + m[13]*v[1] + m[14]*v[2] + m[15]*v[3];
00113 }
00114
00115 static inline void
00116 vector_add_3d (const double v1[3], const double v2[3], double result[3])
00117 {
00118 result[0] = v1[0] + v2[0];
00119 result[1] = v1[1] + v2[1];
00120 result[2] = v1[2] + v2[2];
00121 }
00122
00123 static inline void
00124 vector_add_nd (const double * v1, const double * v2, int N, double * result)
00125 {
00126 int i;
00127 for (i = 0; i < N; i++)
00128 result[i] = v1[i] + v2[i];
00129 }
00130
00131 static inline void
00132 vector_sub_nd (const double * v1, const double * v2, int N, double * result)
00133 {
00134 int i;
00135 for (i = 0; i < N; i++)
00136 result[i] = v1[i] - v2[i];
00137 }
00138
00144 static inline void
00145 vector_subtract_3d (const double v1[3], const double v2[3], double result[3])
00146 {
00147 result[0] = v1[0] - v2[0];
00148 result[1] = v1[1] - v2[1];
00149 result[2] = v1[2] - v2[2];
00150 }
00151
00152 static inline double
00153 vector_dot_2d (const double v1[2], const double v2[2])
00154 {
00155 return v1[0]*v2[0] + v1[1]*v2[1];
00156 }
00157
00158 static inline double
00159 vector_dot_3d (const double v1[3], const double v2[3])
00160 {
00161 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
00162 }
00163
00164 static inline void
00165 vector_cross_3d (const double v1[3], const double v2[3], double result[3])
00166 {
00167 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
00168 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
00169 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
00170 }
00171
00172 static inline double
00173 vector_magnitude_squared_2d (const double v[2])
00174 {
00175 return v[0]*v[0] + v[1]*v[1];
00176 }
00177
00178 static inline double
00179 vector_magnitude_2d (const double v[2])
00180 {
00181 return sqrt(v[0]*v[0] + v[1]*v[1]);
00182 }
00183
00184 static inline double
00185 vector_magnitude_3d (const double v[3])
00186 {
00187 return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00188 }
00189
00190 static inline double
00191 vector_magnitude_squared_3d (const double v[3])
00192 {
00193 return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00194 }
00195
00196 static inline double
00197 vector_dist_3d (const double v1[3], const double v2[3])
00198 {
00199 double v[3];
00200 vector_subtract_3d (v1, v2, v);
00201 return vector_magnitude_3d (v);
00202 }
00203
00204 static inline double
00205 vector_dist_squared_3d (const double v1[3], const double v2[3])
00206 {
00207 double v[3];
00208 vector_subtract_3d (v1, v2, v);
00209 return vector_magnitude_squared_3d (v);
00210 }
00211
00212 static inline double
00213 vector_dist_2d (const double v1[2], const double v2[2])
00214 {
00215 double v[2];
00216 vector_sub_nd (v1, v2, 2, v);
00217 return vector_magnitude_2d (v);
00218 }
00219
00220 static inline void
00221 vector_normalize_2d (double v[2])
00222 {
00223 double mag = vector_magnitude_2d (v);
00224 v[0] /= mag;
00225 v[1] /= mag;
00226 }
00227
00228 static inline void
00229 vector_normalize_3d (double v[3])
00230 {
00231 double mag = vector_magnitude_3d (v);
00232 v[0] /= mag;
00233 v[1] /= mag;
00234 v[2] /= mag;
00235 }
00236
00237 static inline void
00238 vector_scale_2d (double v[2], double s)
00239 {
00240 v[0] *= s;
00241 v[1] *= s;
00242 }
00243
00244 static inline void
00245 vector_scale_3d (double v[2], double s)
00246 {
00247 v[0] *= s;
00248 v[1] *= s;
00249 v[2] *= s;
00250 }
00251
00252
00253 static inline void
00254 vector_saxpy_3d (double a, const double x[3], const double y[3], double z[3])
00255 {
00256 double t[3] = { a * x[0] + y[0], a * x[1] + y[1], a * x[2] + y[2] };
00257 z[0] = t[0]; z[1] = t[1]; z[2] = t[2];
00258 }
00259
00260 static inline double
00261 vector_angle_2d (const double v1[2], const double v2[2])
00262 {
00263 double mag1 = vector_magnitude_2d (v1);
00264 double mag2 = vector_magnitude_2d (v2);
00265 double dot = vector_dot_2d (v1, v2);
00266
00267 double costheta = dot / ( mag1 * mag2);
00268 if (costheta > 1) return 0;
00269 double theta = acos (costheta);
00270
00271 if ( (v1[0]*v2[1] - v1[1]*v2[0]) < 0) {
00272 return -theta;
00273 }
00274
00275 return theta;
00276 }
00277
00278 static inline double
00279 vector_angle_3d (const double v1[3], const double v2[3])
00280 {
00281 double mag1 = vector_magnitude_3d (v1);
00282 double mag2 = vector_magnitude_3d (v2);
00283 double dot = vector_dot_3d (v1, v2);
00284 double costheta = dot / (mag1*mag2);
00285 if (costheta > 1) return 0;
00286 return acos (costheta);
00287 }
00288
00289 static inline void
00290 matrix_transpose_3x3d (const double m[9], double result[9])
00291 {
00292 result[0] = m[0];
00293 result[1] = m[3];
00294 result[2] = m[6];
00295 result[3] = m[1];
00296 result[4] = m[4];
00297 result[5] = m[7];
00298 result[6] = m[2];
00299 result[7] = m[5];
00300 result[8] = m[8];
00301 }
00302
00303 static inline void
00304 matrix_transpose_4x4d (const double m[16], double result[16])
00305 {
00306 result[0] = m[0];
00307 result[1] = m[4];
00308 result[2] = m[8];
00309 result[3] = m[12];
00310 result[4] = m[1];
00311 result[5] = m[5];
00312 result[6] = m[9];
00313 result[7] = m[13];
00314 result[8] = m[2];
00315 result[9] = m[6];
00316 result[10] = m[10];
00317 result[11] = m[14];
00318 result[12] = m[3];
00319 result[13] = m[7];
00320 result[14] = m[11];
00321 result[15] = m[15];
00322 }
00323
00324 static inline void
00325 matrix_multiply_4x4_4x4 (const double a[16], const double b[16], double r[16])
00326 {
00327 int i, j;
00328 for (i = 0; i < 4; i++) {
00329 for (j = 0; j < 4; j++) {
00330 double acc = 0;
00331 int k;
00332 for (k = 0; k < 4; k++)
00333 acc += a[4*i + k] * b[j + 4*k];
00334 r[i*4+j] = acc;
00335 }
00336 }
00337 }
00338
00339 static inline void
00340 matrix_multiply_3x3_3x3 (const double a[9], const double b[9], double r[9])
00341 {
00342 int i, j;
00343 for (i = 0; i < 3; i++) {
00344 for (j = 0; j < 3; j++) {
00345 double acc = 0;
00346 int k;
00347 for (k = 0; k < 3; k++)
00348 acc += a[3*i + k] * b[j + 3*k];
00349 r[i*3+j] = acc;
00350 }
00351 }
00352 }
00353
00354 static inline void
00355 matrix_multiply (const double *a, int a_nrows, int a_ncols,
00356 const double *b, int b_nrows, int b_ncols,
00357 double *result)
00358 {
00359 int i, j;
00360 for (i=0; i<a_nrows; i++) {
00361 for (j=0; j<b_ncols; j++) {
00362 double acc = 0;
00363 int r;
00364 for (r=0; r<a_ncols; r++) {
00365 acc += a[i*a_ncols + r] * b[r*b_ncols + j];
00366 }
00367 result[i*b_ncols + j] = acc;
00368 }
00369 }
00370 }
00371
00372 static inline int
00373 matrix_rigid_body_transform_inverse_4x4d (const double m[16], double inv[16])
00374 {
00375
00376
00377 double rot_inv_1[3] = { m[0], m[4], m[8] };
00378 double rot_inv_2[3] = { m[1], m[5], m[9] };
00379 double rot_inv_3[3] = { m[2], m[6], m[10] };
00380 double t_inv[3] = { -m[3], -m[7], -m[11] };
00381
00382 inv[0] = m[0];
00383 inv[1] = m[4];
00384 inv[2] = m[8];
00385 inv[3] = vector_dot_3d (rot_inv_1, t_inv);
00386 inv[4] = m[1];
00387 inv[5] = m[5];
00388 inv[6] = m[9];
00389 inv[7] = vector_dot_3d (rot_inv_2, t_inv);
00390 inv[8] = m[2];
00391 inv[9] = m[6];
00392 inv[10] = m[10];
00393 inv[11] = vector_dot_3d (rot_inv_3, t_inv);
00394 inv[12] = inv[13] = inv[14] = 0;
00395 inv[15] = m[15];
00396 return 0;
00397 }
00398
00399 static inline void
00400 matrix_rigid_body_transform_get_rotation_matrix_4x4d (const double m[16],
00401 double rot[16])
00402 {
00403 rot[0] = m[0]; rot[1] = m[1]; rot[2] = m[2]; rot[3] = 0;
00404 rot[4] = m[4]; rot[5] = m[5]; rot[6] = m[6]; rot[7] = 0;
00405 rot[8] = m[8]; rot[9] = m[9]; rot[10] = m[10]; rot[11] = 0;
00406 rot[12] = rot[13] = rot[14] = 0; rot[15] = 1;
00407 }
00408
00409 static inline void
00410 matrix_rigid_body_transform_get_translation_matrix_4x4d (const double m[16],
00411 double t[16])
00412 {
00413 t[0] = 1; t[1] = 0; t[2] = 0; t[3] = m[3];
00414 t[4] = 0; t[5] = 1; t[6] = 0; t[7] = m[7];
00415 t[8] = 0; t[9] = 0; t[10] = 1; t[11] = m[11];
00416 t[12] = t[13] = t[14] = 0; t[15] = 1;
00417 }
00418
00419 static inline void
00420 matrix_print(const double *a, int rows, int cols)
00421 {
00422 int r, c;
00423 for (r = 0; r < rows; r++) {
00424 for (c = 0; c < cols; c++) {
00425 printf("%10f ", a[r*cols + c]);
00426 }
00427 printf("\n");
00428 }
00429 }
00430
00431 static inline void
00432 vector_print_3d(const double a[3])
00433 {
00434 int i;
00435 for (i = 0; i < 3; i++)
00436 printf("%15f\n", a[i]);
00437 printf("\n");
00438 }
00439
00440 static inline void
00441 vector_vector_outer_product_3d (const double v1[3], const double v2[3],
00442 double result[9])
00443 {
00444 result[0] = v1[0] * v2[0];
00445 result[1] = v1[1] * v2[0];
00446 result[2] = v1[2] * v2[0];
00447 result[3] = result[1];
00448 result[4] = v1[1] * v2[1];
00449 result[5] = v1[2] * v2[1];
00450 result[6] = result[2];
00451 result[7] = result[5];
00452 result[8] = v1[2] * v2[2];
00453 }
00454
00455 #ifdef __cplusplus
00456 }
00457 #endif
00458
00459 #endif
00460