/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
- /*
- $License:
- Copyright 2011 InvenSense, Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- $
- */
- #include "mlmath.h"
- #include "mlMathFunc.h"
- #include "mlinclude.h"
- /** Performs a multiply and shift by 29. These are good functions to write in assembly on
- * with devices with small memory where you want to get rid of the long long which some
- * assemblers don't handle well
- * @param[in] a
- * @param[in] b
- * @return ((long long)a*b)>>29
- */
- long inv_q29_mult(long a, long b)
- {
- long long temp;
- long result;
- temp = (long long)a *b;
- result = (long)(temp >> 29);
- return result;
- }
- /** Performs a multiply and shift by 30. These are good functions to write in assembly on
- * with devices with small memory where you want to get rid of the long long which some
- * assemblers don't handle well
- * @param[in] a
- * @param[in] b
- * @return ((long long)a*b)>>30
- */
- long inv_q30_mult(long a, long b)
- {
- long long temp;
- long result;
- temp = (long long)a *b;
- result = (long)(temp >> 30);
- return result;
- }
- void inv_q_mult(const long *q1, const long *q2, long *qProd)
- {
- INVENSENSE_FUNC_START;
- qProd[0] = (long)(((long long)q1[0] * q2[0] - (long long)q1[1] * q2[1] -
- (long long)q1[2] * q2[2] -
- (long long)q1[3] * q2[3]) >> 30);
- qProd[1] =
- (int)(((long long)q1[0] * q2[1] + (long long)q1[1] * q2[0] +
- (long long)q1[2] * q2[3] - (long long)q1[3] * q2[2]) >> 30);
- qProd[2] =
- (long)(((long long)q1[0] * q2[2] - (long long)q1[1] * q2[3] +
- (long long)q1[2] * q2[0] + (long long)q1[3] * q2[1]) >> 30);
- qProd[3] =
- (long)(((long long)q1[0] * q2[3] + (long long)q1[1] * q2[2] -
- (long long)q1[2] * q2[1] + (long long)q1[3] * q2[0]) >> 30);
- }
- void inv_q_invert(const long *q, long *qInverted)
- {
- INVENSENSE_FUNC_START;
- qInverted[0] = q[0];
- qInverted[1] = -q[1];
- qInverted[2] = -q[2];
- qInverted[3] = -q[3];
- }
- /**
- * Converts a quaternion to a rotation matrix.
- * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
- * @param[out] rot Rotation matrix in fixed point. One is 2^30. The
- * First 3 elements of the rotation matrix, represent
- * the first row of the matrix. Rotation matrix multiplied
- * by a 3 element column vector transform a vector from Body
- * to World.
- */
- void inv_quaternion_to_rotation(const long *quat, long *rot)
- {
- rot[0] =
- inv_q29_mult(quat[1], quat[1]) + inv_q29_mult(quat[0],
- quat[0]) - 1073741824L;
- rot[1] = inv_q29_mult(quat[1], quat[2]) - inv_q29_mult(quat[3], quat[0]);
- rot[2] = inv_q29_mult(quat[1], quat[3]) + inv_q29_mult(quat[2], quat[0]);
- rot[3] = inv_q29_mult(quat[1], quat[2]) + inv_q29_mult(quat[3], quat[0]);
- rot[4] =
- inv_q29_mult(quat[2], quat[2]) + inv_q29_mult(quat[0],
- quat[0]) - 1073741824L;
- rot[5] = inv_q29_mult(quat[2], quat[3]) - inv_q29_mult(quat[1], quat[0]);
- rot[6] = inv_q29_mult(quat[1], quat[3]) - inv_q29_mult(quat[2], quat[0]);
- rot[7] = inv_q29_mult(quat[2], quat[3]) + inv_q29_mult(quat[1], quat[0]);
- rot[8] =
- inv_q29_mult(quat[3], quat[3]) + inv_q29_mult(quat[0],
- quat[0]) - 1073741824L;
- }
- /** Converts a 32-bit long to a big endian byte stream */
- unsigned char *inv_int32_to_big8(long x, unsigned char *big8)
- {
- big8[0] = (unsigned char)((x >> 24) & 0xff);
- big8[1] = (unsigned char)((x >> 16) & 0xff);
- big8[2] = (unsigned char)((x >> 8) & 0xff);
- big8[3] = (unsigned char)(x & 0xff);
- return big8;
- }
- /** Converts a big endian byte stream into a 32-bit long */
- long inv_big8_to_int32(const unsigned char *big8)
- {
- long x;
- x = ((long)big8[0] << 24) | ((long)big8[1] << 16) | ((long)big8[2] << 8) |
- ((long)big8[3]);
- return x;
- }
- /** Converts a 16-bit short to a big endian byte stream */
- unsigned char *inv_int16_to_big8(short x, unsigned char *big8)
- {
- big8[0] = (unsigned char)((x >> 8) & 0xff);
- big8[1] = (unsigned char)(x & 0xff);
- return big8;
- }
- void inv_matrix_det_inc(float *a, float *b, int *n, int x, int y)
- {
- int k, l, i, j;
- for (i = 0, k = 0; i < *n; i++, k++) {
- for (j = 0, l = 0; j < *n; j++, l++) {
- if (i == x)
- i++;
- if (j == y)
- j++;
- *(b + 10 * k + l) = *(a + 10 * i + j);
- }
- }
- *n = *n - 1;
- }
- float inv_matrix_det(float *p, int *n)
- {
- float d[10][10], sum = 0;
- int i, j, m;
- m = *n;
- if (*n == 2)
- return (*p ** (p + 11) - *(p + 1) ** (p + 10));
- for (i = 0, j = 0; j < m; j++) {
- *n = m;
- inv_matrix_det_inc(p, &d[0][0], n, i, j);
- sum =
- sum + *(p + 10 * i + j) * SIGNM(i + j) * inv_matrix_det(&d[0][0],
- n);
- }
- return (sum);
- }
- /** Wraps angle from (-M_PI,M_PI]
- * @param[in] ang Angle in radians to wrap
- * @return Wrapped angle from (-M_PI,M_PI]
- */
- float inv_wrap_angle(float ang)
- {
- if (ang > M_PI)
- return ang - 2 * (float)M_PI;
- else if (ang <= -(float)M_PI)
- return ang + 2 * (float)M_PI;
- else
- return ang;
- }
- /** Finds the minimum angle difference ang1-ang2 such that difference
- * is between [-M_PI,M_PI]
- * @param[in] ang1
- * @param[in] ang2
- * @return angle difference ang1-ang2
- */
- float inv_angle_diff(float ang1, float ang2)
- {
- float d;
- ang1 = inv_wrap_angle(ang1);
- ang2 = inv_wrap_angle(ang2);
- d = ang1 - ang2;
- if (d > M_PI)
- d -= 2 * (float)M_PI;
- else if (d < -(float)M_PI)
- d += 2 * (float)M_PI;
- return d;
- }