/libsensors/mlsdk/mllite/mlMathFunc.c

https://github.com/CyanogenMod/android_device_samsung_tuna · C · 200 lines · 133 code · 14 blank · 53 comment · 15 complexity · 3b1ee2664733a4d33f068b05f8469082 MD5 · raw file

  1. /*
  2. $License:
  3. Copyright 2011 InvenSense, Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. $
  14. */
  15. #include "mlmath.h"
  16. #include "mlMathFunc.h"
  17. #include "mlinclude.h"
  18. /** Performs a multiply and shift by 29. These are good functions to write in assembly on
  19. * with devices with small memory where you want to get rid of the long long which some
  20. * assemblers don't handle well
  21. * @param[in] a
  22. * @param[in] b
  23. * @return ((long long)a*b)>>29
  24. */
  25. long inv_q29_mult(long a, long b)
  26. {
  27. long long temp;
  28. long result;
  29. temp = (long long)a *b;
  30. result = (long)(temp >> 29);
  31. return result;
  32. }
  33. /** Performs a multiply and shift by 30. These are good functions to write in assembly on
  34. * with devices with small memory where you want to get rid of the long long which some
  35. * assemblers don't handle well
  36. * @param[in] a
  37. * @param[in] b
  38. * @return ((long long)a*b)>>30
  39. */
  40. long inv_q30_mult(long a, long b)
  41. {
  42. long long temp;
  43. long result;
  44. temp = (long long)a *b;
  45. result = (long)(temp >> 30);
  46. return result;
  47. }
  48. void inv_q_mult(const long *q1, const long *q2, long *qProd)
  49. {
  50. INVENSENSE_FUNC_START;
  51. qProd[0] = (long)(((long long)q1[0] * q2[0] - (long long)q1[1] * q2[1] -
  52. (long long)q1[2] * q2[2] -
  53. (long long)q1[3] * q2[3]) >> 30);
  54. qProd[1] =
  55. (int)(((long long)q1[0] * q2[1] + (long long)q1[1] * q2[0] +
  56. (long long)q1[2] * q2[3] - (long long)q1[3] * q2[2]) >> 30);
  57. qProd[2] =
  58. (long)(((long long)q1[0] * q2[2] - (long long)q1[1] * q2[3] +
  59. (long long)q1[2] * q2[0] + (long long)q1[3] * q2[1]) >> 30);
  60. qProd[3] =
  61. (long)(((long long)q1[0] * q2[3] + (long long)q1[1] * q2[2] -
  62. (long long)q1[2] * q2[1] + (long long)q1[3] * q2[0]) >> 30);
  63. }
  64. void inv_q_invert(const long *q, long *qInverted)
  65. {
  66. INVENSENSE_FUNC_START;
  67. qInverted[0] = q[0];
  68. qInverted[1] = -q[1];
  69. qInverted[2] = -q[2];
  70. qInverted[3] = -q[3];
  71. }
  72. /**
  73. * Converts a quaternion to a rotation matrix.
  74. * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
  75. * @param[out] rot Rotation matrix in fixed point. One is 2^30. The
  76. * First 3 elements of the rotation matrix, represent
  77. * the first row of the matrix. Rotation matrix multiplied
  78. * by a 3 element column vector transform a vector from Body
  79. * to World.
  80. */
  81. void inv_quaternion_to_rotation(const long *quat, long *rot)
  82. {
  83. rot[0] =
  84. inv_q29_mult(quat[1], quat[1]) + inv_q29_mult(quat[0],
  85. quat[0]) - 1073741824L;
  86. rot[1] = inv_q29_mult(quat[1], quat[2]) - inv_q29_mult(quat[3], quat[0]);
  87. rot[2] = inv_q29_mult(quat[1], quat[3]) + inv_q29_mult(quat[2], quat[0]);
  88. rot[3] = inv_q29_mult(quat[1], quat[2]) + inv_q29_mult(quat[3], quat[0]);
  89. rot[4] =
  90. inv_q29_mult(quat[2], quat[2]) + inv_q29_mult(quat[0],
  91. quat[0]) - 1073741824L;
  92. rot[5] = inv_q29_mult(quat[2], quat[3]) - inv_q29_mult(quat[1], quat[0]);
  93. rot[6] = inv_q29_mult(quat[1], quat[3]) - inv_q29_mult(quat[2], quat[0]);
  94. rot[7] = inv_q29_mult(quat[2], quat[3]) + inv_q29_mult(quat[1], quat[0]);
  95. rot[8] =
  96. inv_q29_mult(quat[3], quat[3]) + inv_q29_mult(quat[0],
  97. quat[0]) - 1073741824L;
  98. }
  99. /** Converts a 32-bit long to a big endian byte stream */
  100. unsigned char *inv_int32_to_big8(long x, unsigned char *big8)
  101. {
  102. big8[0] = (unsigned char)((x >> 24) & 0xff);
  103. big8[1] = (unsigned char)((x >> 16) & 0xff);
  104. big8[2] = (unsigned char)((x >> 8) & 0xff);
  105. big8[3] = (unsigned char)(x & 0xff);
  106. return big8;
  107. }
  108. /** Converts a big endian byte stream into a 32-bit long */
  109. long inv_big8_to_int32(const unsigned char *big8)
  110. {
  111. long x;
  112. x = ((long)big8[0] << 24) | ((long)big8[1] << 16) | ((long)big8[2] << 8) |
  113. ((long)big8[3]);
  114. return x;
  115. }
  116. /** Converts a 16-bit short to a big endian byte stream */
  117. unsigned char *inv_int16_to_big8(short x, unsigned char *big8)
  118. {
  119. big8[0] = (unsigned char)((x >> 8) & 0xff);
  120. big8[1] = (unsigned char)(x & 0xff);
  121. return big8;
  122. }
  123. void inv_matrix_det_inc(float *a, float *b, int *n, int x, int y)
  124. {
  125. int k, l, i, j;
  126. for (i = 0, k = 0; i < *n; i++, k++) {
  127. for (j = 0, l = 0; j < *n; j++, l++) {
  128. if (i == x)
  129. i++;
  130. if (j == y)
  131. j++;
  132. *(b + 10 * k + l) = *(a + 10 * i + j);
  133. }
  134. }
  135. *n = *n - 1;
  136. }
  137. float inv_matrix_det(float *p, int *n)
  138. {
  139. float d[10][10], sum = 0;
  140. int i, j, m;
  141. m = *n;
  142. if (*n == 2)
  143. return (*p ** (p + 11) - *(p + 1) ** (p + 10));
  144. for (i = 0, j = 0; j < m; j++) {
  145. *n = m;
  146. inv_matrix_det_inc(p, &d[0][0], n, i, j);
  147. sum =
  148. sum + *(p + 10 * i + j) * SIGNM(i + j) * inv_matrix_det(&d[0][0],
  149. n);
  150. }
  151. return (sum);
  152. }
  153. /** Wraps angle from (-M_PI,M_PI]
  154. * @param[in] ang Angle in radians to wrap
  155. * @return Wrapped angle from (-M_PI,M_PI]
  156. */
  157. float inv_wrap_angle(float ang)
  158. {
  159. if (ang > M_PI)
  160. return ang - 2 * (float)M_PI;
  161. else if (ang <= -(float)M_PI)
  162. return ang + 2 * (float)M_PI;
  163. else
  164. return ang;
  165. }
  166. /** Finds the minimum angle difference ang1-ang2 such that difference
  167. * is between [-M_PI,M_PI]
  168. * @param[in] ang1
  169. * @param[in] ang2
  170. * @return angle difference ang1-ang2
  171. */
  172. float inv_angle_diff(float ang1, float ang2)
  173. {
  174. float d;
  175. ang1 = inv_wrap_angle(ang1);
  176. ang2 = inv_wrap_angle(ang2);
  177. d = ang1 - ang2;
  178. if (d > M_PI)
  179. d -= 2 * (float)M_PI;
  180. else if (d < -(float)M_PI)
  181. d += 2 * (float)M_PI;
  182. return d;
  183. }