1c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*
2c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro $License:
3c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
4c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    See included License.txt for License information.
5c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro $
6c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
7c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
8c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*******************************************************************************
9c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *
10c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * $Id:$
11c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *
12c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro ******************************************************************************/
13c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
14c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
15c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @defgroup  ML_MATH_FUNC ml_math_func
16c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @brief     Motion Library - Math Functions
17c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Common math functions the Motion Library
18c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *
19c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @{
20c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *       @file ml_math_func.c
21c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *       @brief Math Functions.
22c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
23c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
24c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "mlmath.h"
25c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "ml_math_func.h"
26c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "mlinclude.h"
27c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include <string.h>
28c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
29c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** @internal
30c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * Does the cross product of compass by gravity, then converts that
31c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * to the world frame using the quaternion, then computes the angle that
32c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * is made.
33c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *
34c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] compass Compass Vector (Body Frame), length 3
35c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] grav Gravity Vector (Body Frame), length 3
36c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] quat Quaternion, Length 4
37c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return Angle Cross Product makes after quaternion rotation.
38c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
39c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarofloat inv_compass_angle(const long *compass, const long *grav, const float *quat)
40c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
41c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float cgcross[4], q1[4], q2[4], qi[4];
42c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float angW;
43c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
44c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Compass cross Gravity
45c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[0] = 0.f;
46c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[1] = (float)compass[1] * grav[2] - (float)compass[2] * grav[1];
47c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[2] = (float)compass[2] * grav[0] - (float)compass[0] * grav[2];
48c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[3] = (float)compass[0] * grav[1] - (float)compass[1] * grav[0];
49c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
50c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Now convert cross product into world frame
51c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_multf(quat, cgcross, q1);
52c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_invertf(quat, qi);
53c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_multf(q1, qi, q2);
54c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
55c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Protect against atan2 of 0,0
56c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((q2[2] == 0.f) && (q2[1] == 0.f))
57c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0.f;
58c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
59c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // This is the unfiltered heading correction
60c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    angW = -atan2f(q2[2], q2[1]);
61c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return angW;
62c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
63c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
64c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
65c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @brief  The gyro data magnitude squared :
66c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *          (1 degree per second)^2 = 2^6 = 2^GYRO_MAG_SQR_SHIFT.
67c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] gyro Gyro data scaled with 1 dps = 2^16
68c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @return the computed magnitude squared output of the gyroscope.
69c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
70c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarounsigned long inv_get_gyro_sum_of_sqr(const long *gyro)
71c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
72c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    unsigned long gmag = 0;
73c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long temp;
74c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int kk;
75c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
76c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (kk = 0; kk < 3; ++kk) {
77c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        temp = gyro[kk] >> (16 - (GYRO_MAG_SQR_SHIFT / 2));
78c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        gmag += temp * temp;
79c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
80c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
81c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return gmag;
82c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
83c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
84c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a multiply and shift by 29. These are good functions to write in assembly on
85c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * with devices with small memory where you want to get rid of the long long which some
86c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * assemblers don't handle well
87c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] a
88c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] b
89c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return ((long long)a*b)>>29
90c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
91c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_q29_mult(long a, long b)
92c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
93c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef UMPL_ELIMINATE_64BIT
94c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
95c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)((float)a * b / (1L << 29));
96c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
97c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#else
98c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long long temp;
99c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
100c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    temp = (long long)a * b;
101c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)(temp >> 29);
102c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
103c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
104c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
105c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
106c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a multiply and shift by 30. These are good functions to write in assembly on
107c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * with devices with small memory where you want to get rid of the long long which some
108c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * assemblers don't handle well
109c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] a
110c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] b
111c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return ((long long)a*b)>>30
112c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
113c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_q30_mult(long a, long b)
114c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
115c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef UMPL_ELIMINATE_64BIT
116c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
117c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)((float)a * b / (1L << 30));
118c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
119c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#else
120c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long long temp;
121c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
122c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    temp = (long long)a * b;
123c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)(temp >> 30);
124c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
125c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
126c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
127c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
128c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifndef UMPL_ELIMINATE_64BIT
129c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_q30_div(long a, long b)
130c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
131c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long long temp;
132c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
133c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    temp = (((long long)a) << 30) / b;
134c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)temp;
135c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
136c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
137c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
138c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
139c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a multiply and shift by shift. These are good functions to write
140c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * in assembly on with devices with small memory where you want to get rid of
141c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * the long long which some assemblers don't handle well
142c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] a First multicand
143c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] b Second multicand
144c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] shift Shift amount after multiplying
145c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return ((long long)a*b)<<shift
146c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
147c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifndef UMPL_ELIMINATE_64BIT
148c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_q_shift_mult(long a, long b, int shift)
149c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
150c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long result;
151c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    result = (long)(((long long)a * b) >> shift);
152c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
153c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
154c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
155c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
156c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a fixed point quaternion multiply.
157c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] q1 First Quaternion Multicand, length 4. 1.0 scaled
158c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to 2^30
159c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] q2 Second Quaternion Multicand, length 4. 1.0 scaled
160c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to 2^30
161c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] qProd Product after quaternion multiply. Length 4.
162c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             1.0 scaled to 2^30.
163c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
164c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_mult(const long *q1, const long *q2, long *qProd)
165c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
166c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
167c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[0] = inv_q30_mult(q1[0], q2[0]) - inv_q30_mult(q1[1], q2[1]) -
168c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               inv_q30_mult(q1[2], q2[2]) - inv_q30_mult(q1[3], q2[3]);
169c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
170c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[1] = inv_q30_mult(q1[0], q2[1]) + inv_q30_mult(q1[1], q2[0]) +
171c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               inv_q30_mult(q1[2], q2[3]) - inv_q30_mult(q1[3], q2[2]);
172c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
173c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[2] = inv_q30_mult(q1[0], q2[2]) - inv_q30_mult(q1[1], q2[3]) +
174c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               inv_q30_mult(q1[2], q2[0]) + inv_q30_mult(q1[3], q2[1]);
175c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
176c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[3] = inv_q30_mult(q1[0], q2[3]) + inv_q30_mult(q1[1], q2[2]) -
177c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               inv_q30_mult(q1[2], q2[1]) + inv_q30_mult(q1[3], q2[0]);
178c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
179c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
180c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a fixed point quaternion addition.
181c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] q1 First Quaternion term, length 4. 1.0 scaled
182c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to 2^30
183c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] q2 Second Quaternion term, length 4. 1.0 scaled
184c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to 2^30
185c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] qSum Sum after quaternion summation. Length 4.
186c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             1.0 scaled to 2^30.
187c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
188c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_add(long *q1, long *q2, long *qSum)
189c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
190c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
191c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[0] = q1[0] + q2[0];
192c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[1] = q1[1] + q2[1];
193c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[2] = q1[2] + q2[2];
194c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[3] = q1[3] + q2[3];
195c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
196c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
197c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_vector_normalize(long *vec, int length)
198c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
199c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
200c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    double normSF = 0;
201c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int ii;
202c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (ii = 0; ii < length; ii++) {
203c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF +=
204c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_q30_to_double(vec[ii]) * inv_q30_to_double(vec[ii]);
205c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
206c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (normSF > 0) {
207c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF = 1 / sqrt(normSF);
208c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (ii = 0; ii < length; ii++) {
209c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            vec[ii] = (int)((double)vec[ii] * normSF);
210c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
211c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
212c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        vec[0] = 1073741824L;
213c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (ii = 1; ii < length; ii++) {
214c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            vec[ii] = 0;
215c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
216c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
217c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
218c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
219c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_normalize(long *q)
220c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
221c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
222c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_vector_normalize(q, 4);
223c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
224c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
225c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_invert(const long *q, long *qInverted)
226c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
227c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
228c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[0] = q[0];
229c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[1] = -q[1];
230c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[2] = -q[2];
231c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[3] = -q[3];
232c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
233c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
234c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarodouble quaternion_to_rotation_angle(const long *quat) {
235c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    double quat0 = (double )quat[0] / 1073741824;
236c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (quat0 > 1.0f) {
237c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        quat0 = 1.0;
238c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else if (quat0 < -1.0f) {
239c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        quat0 = -1.0;
240c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
241c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
242c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return acos(quat0)*2*180/M_PI;
243c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
244c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
245c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Rotates a 3-element vector by Rotation defined by Q
246c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
247c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_rotate(const long *q, const long *in, long *out)
248c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
249c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long q_temp1[4], q_temp2[4];
250c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long in4[4], out4[4];
251c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
252c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Fixme optimize
253c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    in4[0] = 0;
254c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(&in4[1], in, 3 * sizeof(long));
255c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_mult(q, in4, q_temp1);
256c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_invert(q, q_temp2);
257c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_q_mult(q_temp1, q_temp2, out4);
258c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(out, &out4[1], 3 * sizeof(long));
259c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
260c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
261c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_multf(const float *q1, const float *q2, float *qProd)
262c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
263c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
264c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[0] =
265c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        (q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]);
266c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[1] =
267c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        (q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]);
268c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[2] =
269c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        (q1[0] * q2[2] - q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1]);
270c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qProd[3] =
271c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        (q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0]);
272c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
273c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
274c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_addf(const float *q1, const float *q2, float *qSum)
275c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
276c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
277c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[0] = q1[0] + q2[0];
278c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[1] = q1[1] + q2[1];
279c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[2] = q1[2] + q2[2];
280c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qSum[3] = q1[3] + q2[3];
281c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
282c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
283c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_normalizef(float *q)
284c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
285c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
286c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float normSF = 0;
287c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float xHalf = 0;
288c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
289c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (normSF < 2) {
290c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        xHalf = 0.5f * normSF;
291c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF = normSF * (1.5f - xHalf * normSF * normSF);
292c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF = normSF * (1.5f - xHalf * normSF * normSF);
293c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF = normSF * (1.5f - xHalf * normSF * normSF);
294c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        normSF = normSF * (1.5f - xHalf * normSF * normSF);
295c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[0] *= normSF;
296c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[1] *= normSF;
297c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[2] *= normSF;
298c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[3] *= normSF;
299c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
300c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[0] = 1.0;
301c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[1] = 0.0;
302c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[2] = 0.0;
303c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[3] = 0.0;
304c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
305c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    normSF = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
306c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
307c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
308c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Performs a length 4 vector normalization with a square root.
309c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in,out] q vector to normalize. Returns [1,0,0,0] is magnitude is zero.
310c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
311c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_norm4(float *q)
312c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
313c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float mag;
314c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    mag = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
315c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (mag) {
316c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[0] /= mag;
317c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[1] /= mag;
318c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[2] /= mag;
319c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[3] /= mag;
320c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
321c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[0] = 1.f;
322c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[1] = 0.f;
323c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[2] = 0.f;
324c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        q[3] = 0.f;
325c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
326c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
327c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
328c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_q_invertf(const float *q, float *qInverted)
329c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
330c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    INVENSENSE_FUNC_START;
331c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[0] = q[0];
332c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[1] = -q[1];
333c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[2] = -q[2];
334c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    qInverted[3] = -q[3];
335c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
336c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
337c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
338c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * Converts a quaternion to a rotation matrix.
339c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
340c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] rot Rotation matrix in fixed point. One is 2^30. The
341c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             First 3 elements of the rotation matrix, represent
342c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             the first row of the matrix. Rotation matrix multiplied
343c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             by a 3 element column vector transform a vector from Body
344c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             to World.
345c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
346c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_quaternion_to_rotation(const long *quat, long *rot)
347c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
348c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[0] =
349c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[1], quat[1]) + inv_q29_mult(quat[0],
350c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                quat[0]) -
351c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        1073741824L;
352c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[1] =
353c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[1], quat[2]) - inv_q29_mult(quat[3], quat[0]);
354c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[2] =
355c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[1], quat[3]) + inv_q29_mult(quat[2], quat[0]);
356c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[3] =
357c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[1], quat[2]) + inv_q29_mult(quat[3], quat[0]);
358c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[4] =
359c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[2], quat[2]) + inv_q29_mult(quat[0],
360c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                quat[0]) -
361c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        1073741824L;
362c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[5] =
363c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[2], quat[3]) - inv_q29_mult(quat[1], quat[0]);
364c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[6] =
365c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[1], quat[3]) - inv_q29_mult(quat[2], quat[0]);
366c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[7] =
367c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[2], quat[3]) + inv_q29_mult(quat[1], quat[0]);
368c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[8] =
369c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_q29_mult(quat[3], quat[3]) + inv_q29_mult(quat[0],
370c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                quat[0]) -
371c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        1073741824L;
372c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
373c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
374c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
375c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * Converts a quaternion to a rotation vector. A rotation vector is
376c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * a method to represent a 4-element quaternion vector in 3-elements.
377c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * To get the quaternion from the 3-elements, The last 3-elements of
378c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * the quaternion will be the given rotation vector. The first element
379c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * of the quaternion will be the positive value that will be required
380c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * to make the magnitude of the quaternion 1.0 or 2^30 in fixed point units.
381c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] quat 4-element quaternion in fixed point. One is 2^30.
382c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] rot Rotation vector in fixed point. One is 2^30.
383c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
384c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_quaternion_to_rotation_vector(const long *quat, long *rot)
385c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
386c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[0] = quat[1];
387c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[1] = quat[2];
388c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    rot[2] = quat[3];
389c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
390c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (quat[0] < 0.0) {
391c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        rot[0] = -rot[0];
392c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        rot[1] = -rot[1];
393c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        rot[2] = -rot[2];
394c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
395c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
396c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
397c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts a 32-bit long to a big endian byte stream */
398c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarounsigned char *inv_int32_to_big8(long x, unsigned char *big8)
399c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
400c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[0] = (unsigned char)((x >> 24) & 0xff);
401c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[1] = (unsigned char)((x >> 16) & 0xff);
402c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[2] = (unsigned char)((x >> 8) & 0xff);
403c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[3] = (unsigned char)(x & 0xff);
404c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return big8;
405c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
406c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
407c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts a big endian byte stream into a 32-bit long */
408c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_big8_to_int32(const unsigned char *big8)
409c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
410c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long x;
411c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    x = ((long)big8[0] << 24) | ((long)big8[1] << 16) | ((long)big8[2] << 8)
412c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        | ((long)big8[3]);
413c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return x;
414c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
415c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
416c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts a big endian byte stream into a 16-bit integer (short) */
417c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroshort inv_big8_to_int16(const unsigned char *big8)
418c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
419c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    short x;
420c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    x = ((short)big8[0] << 8) | ((short)big8[1]);
421c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return x;
422c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
423c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
424c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts a little endian byte stream into a 16-bit integer (short) */
425c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroshort inv_little8_to_int16(const unsigned char *little8)
426c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
427c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    short x;
428c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    x = ((short)little8[1] << 8) | ((short)little8[0]);
429c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return x;
430c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
431c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
432c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts a 16-bit short to a big endian byte stream */
433c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarounsigned char *inv_int16_to_big8(short x, unsigned char *big8)
434c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
435c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[0] = (unsigned char)((x >> 8) & 0xff);
436c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    big8[1] = (unsigned char)(x & 0xff);
437c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return big8;
438c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
439c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
440c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_matrix_det_inc(float *a, float *b, int *n, int x, int y)
441c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
442c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int k, l, i, j;
443c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i = 0, k = 0; i < *n; i++, k++) {
444c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (j = 0, l = 0; j < *n; j++, l++) {
445c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (i == x)
446c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                i++;
447c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (j == y)
448c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                j++;
449c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            *(b + 6 * k + l) = *(a + 6 * i + j);
450c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
451c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
452c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    *n = *n - 1;
453c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
454c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
455c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_matrix_det_incd(double *a, double *b, int *n, int x, int y)
456c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
457c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int k, l, i, j;
458c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i = 0, k = 0; i < *n; i++, k++) {
459c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (j = 0, l = 0; j < *n; j++, l++) {
460c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (i == x)
461c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                i++;
462c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (j == y)
463c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                j++;
464c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            *(b + 6 * k + l) = *(a + 6 * i + j);
465c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
466c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
467c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    *n = *n - 1;
468c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
469c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
470c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarofloat inv_matrix_det(float *p, int *n)
471c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
472c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float d[6][6], sum = 0;
473c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i, j, m;
474c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    m = *n;
475c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (*n == 2)
476c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return (*p ** (p + 7) - *(p + 1) ** (p + 6));
477c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i = 0, j = 0; j < m; j++) {
478c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *n = m;
479c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_matrix_det_inc(p, &d[0][0], n, i, j);
480c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sum =
481c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            sum + *(p + 6 * i + j) * SIGNM(i +
482c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                            j) *
483c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_matrix_det(&d[0][0], n);
484c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
485c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
486c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return (sum);
487c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
488c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
489c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarodouble inv_matrix_detd(double *p, int *n)
490c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
491c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    double d[6][6], sum = 0;
492c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i, j, m;
493c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    m = *n;
494c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (*n == 2)
495c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return (*p ** (p + 7) - *(p + 1) ** (p + 6));
496c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i = 0, j = 0; j < m; j++) {
497c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *n = m;
498c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_matrix_det_incd(p, &d[0][0], n, i, j);
499c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sum =
500c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            sum + *(p + 6 * i + j) * SIGNM(i +
501c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                            j) *
502c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_matrix_detd(&d[0][0], n);
503c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
504c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
505c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return (sum);
506c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
507c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
508c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Wraps angle from (-M_PI,M_PI]
509c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] ang Angle in radians to wrap
510c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return Wrapped angle from (-M_PI,M_PI]
511c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
512c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarofloat inv_wrap_angle(float ang)
513c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
514c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (ang > M_PI)
515c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return ang - 2 * (float)M_PI;
516c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (ang <= -(float)M_PI)
517c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return ang + 2 * (float)M_PI;
518c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else
519c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return ang;
520c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
521c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
522c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Finds the minimum angle difference ang1-ang2 such that difference
523c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * is between [-M_PI,M_PI]
524c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] ang1
525c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] ang2
526c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return angle difference ang1-ang2
527c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
528c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarofloat inv_angle_diff(float ang1, float ang2)
529c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
530c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float d;
531c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    ang1 = inv_wrap_angle(ang1);
532c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    ang2 = inv_wrap_angle(ang2);
533c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    d = ang1 - ang2;
534c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (d > M_PI)
535c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        d -= 2 * (float)M_PI;
536c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (d < -(float)M_PI)
537c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        d += 2 * (float)M_PI;
538c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return d;
539c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
540c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
541c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** bernstein hash, derived from public domain source */
542c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarouint32_t inv_checksum(const unsigned char *str, int len)
543c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
544c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    uint32_t hash = 5381;
545c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i, c;
546c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
547c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i = 0; i < len; i++) {
548c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        c = *(str + i);
549c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        hash = ((hash << 5) + hash) + c;    /* hash * 33 + c */
550c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
551c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
552c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return hash;
553c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
554c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
555c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic unsigned short inv_row_2_scale(const signed char *row)
556c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
557c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    unsigned short b;
558c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
559c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (row[0] > 0)
560c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 0;
561c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (row[0] < 0)
562c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 4;
563c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (row[1] > 0)
564c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 1;
565c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (row[1] < 0)
566c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 5;
567c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (row[2] > 0)
568c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 2;
569c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else if (row[2] < 0)
570c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 6;
571c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else
572c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        b = 7;  // error
573c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return b;
574c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
575c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
576c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
577c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Converts an orientation matrix made up of 0,+1,and -1 to a scalar representation.
578c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] mtx Orientation matrix to convert to a scalar.
579c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Description of orientation matrix. The lowest 2 bits (0 and 1) represent the column the one is on for the
580c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* first row, with the bit number 2 being the sign. The next 2 bits (3 and 4) represent
581c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* the column the one is on for the second row with bit number 5 being the sign.
582c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* The next 2 bits (6 and 7) represent the column the one is on for the third row with
583c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* bit number 8 being the sign. In binary the identity matrix would therefor be:
584c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* 010_001_000 or 0x88 in hex.
585c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
586c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarounsigned short inv_orientation_matrix_to_scalar(const signed char *mtx)
587c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
588c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
589c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    unsigned short scalar;
590c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
591c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /*
592c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       XYZ  010_001_000 Identity Matrix
593c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       XZY  001_010_000
594c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       YXZ  010_000_001
595c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       YZX  000_010_001
596c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       ZXY  001_000_010
597c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       ZYX  000_001_010
598c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro     */
599c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
600c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    scalar = inv_row_2_scale(mtx);
601c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    scalar |= inv_row_2_scale(mtx + 3) << 3;
602c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    scalar |= inv_row_2_scale(mtx + 6) << 6;
603c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
604c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return scalar;
605c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
606c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
607c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Uses the scalar orientation value to convert from chip frame to body frame
608c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar that represent how to go from chip to body frame
609c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] input Input vector, length 3
610c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] output Output vector, length 3
611c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
612c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_convert_to_body(unsigned short orientation, const long *input, long *output)
613c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
614c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[0] = input[orientation      & 0x03] * SIGNSET(orientation & 0x004);
615c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[1] = input[(orientation>>3) & 0x03] * SIGNSET(orientation & 0x020);
616c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[2] = input[(orientation>>6) & 0x03] * SIGNSET(orientation & 0x100);
617c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
618c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
619c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Uses the scalar orientation value to convert from body frame to chip frame
620c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar that represent how to go from chip to body frame
621c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] input Input vector, length 3
622c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] output Output vector, length 3
623c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
624c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_convert_to_chip(unsigned short orientation, const long *input, long *output)
625c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
626c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[orientation & 0x03]      = input[0] * SIGNSET(orientation & 0x004);
627c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[(orientation>>3) & 0x03] = input[1] * SIGNSET(orientation & 0x020);
628c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[(orientation>>6) & 0x03] = input[2] * SIGNSET(orientation & 0x100);
629c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
630c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
631c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
632c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Uses the scalar orientation value to convert from chip frame to body frame and
633c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* apply appropriate scaling.
634c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar that represent how to go from chip to body frame
635c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensitivity Sensitivity scale
636c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] input Input vector, length 3
637c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] output Output vector, length 3
638c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
639c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_convert_to_body_with_scale(unsigned short orientation,
640c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                    long sensitivity,
641c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                    const long *input, long *output)
642c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
643c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[0] = inv_q30_mult(input[orientation & 0x03] *
644c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                             SIGNSET(orientation & 0x004), sensitivity);
645c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[1] = inv_q30_mult(input[(orientation>>3) & 0x03] *
646c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                             SIGNSET(orientation & 0x020), sensitivity);
647c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    output[2] = inv_q30_mult(input[(orientation>>6) & 0x03] *
648c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                             SIGNSET(orientation & 0x100), sensitivity);
649c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
650c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
651c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** find a norm for a vector
652c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] a vector [3x1]
653c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] output the norm of the input vector
654c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
655c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarodouble inv_vector_norm(const float *x)
656c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
657c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
658c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
659c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
660c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_init_biquad_filter(inv_biquad_filter_t *pFilter, float *pBiquadCoeff) {
661c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
662c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // initial state to zero
663c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[0] = 0;
664c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[1] = 0;
665c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
666c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // set up coefficients
667c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<5; i++) {
668c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        pFilter->c[i] = pBiquadCoeff[i];
669c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
670c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
671c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
672c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_calc_state_to_match_output(inv_biquad_filter_t *pFilter, float input)
673c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
674c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->input = input;
675c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->output = input;
676c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[0] = input / (1 + pFilter->c[2] + pFilter->c[3]);
677c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[1] = pFilter->state[0];
678c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
679c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
680c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarofloat inv_biquad_filter_process(inv_biquad_filter_t *pFilter, float input)  {
681c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    float stateZero;
682c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
683c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->input = input;
684c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // calculate the new state;
685c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    stateZero = pFilter->input - pFilter->c[2]*pFilter->state[0]
686c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                               - pFilter->c[3]*pFilter->state[1];
687c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
688c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->output = stateZero + pFilter->c[0]*pFilter->state[0]
689c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                + pFilter->c[1]*pFilter->state[1];
690c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
691c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // update the output and state
692c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->output = pFilter->output * pFilter->c[4];
693c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[1] = pFilter->state[0];
694c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    pFilter->state[0] = stateZero;
695c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return pFilter->output;
696c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
697c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
698c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_cross_product_vec(float *cgcross, float compass[3], float grav[3])  {
699c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
700c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[0] = (float)compass[1] * grav[2] - (float)compass[2] * grav[1];
701c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[1] = (float)compass[2] * grav[0] - (float)compass[0] * grav[2];
702c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    cgcross[2] = (float)compass[0] * grav[1] - (float)compass[1] * grav[0];
703c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
704c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
705c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid mlMatrixVectorMult(long matrix[9], const long vecIn[3], long *vecOut)  {
706c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // matrix format
707c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        //  [ 0  3  6;
708c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        //    1  4  7;
709c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        //    2  5  8]
710c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
711c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // vector format:  [0  1  2]^T;
712c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int i, j;
713c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        long temp;
714c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
715c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (i=0; i<3; i++)	{
716c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                temp = 0;
717c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                for (j=0; j<3; j++)  {
718c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                        temp += inv_q30_mult(matrix[i+j*3], vecIn[j]);
719c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                }
720c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                vecOut[i] = temp;
721c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
722c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
723c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
724c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro//============== 1/sqrt(x), 1/x, sqrt(x) Functions ================================
725c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
726c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Calculates 1/square-root of a fixed-point number (30 bit mantissa, positive): Q1.30
727c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Input must be a positive scaled (2^30) integer
728c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* The number is scaled to lie between a range in which a Newton-Raphson
729c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* iteration works best. Corresponding square root of the power of two is returned.
730c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*  Caller must scale final result by 2^rempow (while avoiding overflow).
731c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] x0, length 1
732c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] rempow, length 1
733c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return scaledSquareRoot on success or zero.
734c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
735c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_inverse_sqrt(long x0, int*rempow)
736c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
737c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% Inverse sqrt NR in the neighborhood of 1.3>x>=0.65
738c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% x(k+1) = x(k)*(3 - x0*x(k)^2)
739c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
740c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% Seed equals 1. Works best in this region.
741c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//xx0 = int32(1*2^30);
742c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
743c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long oneoversqrt2, oneandhalf, x0_2;
744c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	unsigned long xx;
745c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	int pow2, sq2scale, nr_iters;
746c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//long upscale, sqrt_upscale, upsclimit;
747c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//long downscale, sqrt_downscale, downsclimit;
748c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
749c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Precompute some constants for efficiency
750c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% int32(2^30*1/sqrt(2))
751c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	oneoversqrt2=759250125L;
752c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% int32(1.5*2^30);
753c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	oneandhalf=1610612736L;
754c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
755c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//// Further scaling into optimal region saves one or more NR iterations. Maps into region (.9, 1.1)
756c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//// int32(0.9/log(2)*2^30)
757c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//upscale = 1394173804L;
758c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//// int32(sqrt(0.9/log(2))*2^30)
759c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//sqrt_upscale = 1223512453L;
760c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// // int32(1.1*log(2)/.9*2^30)
761c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//upsclimit = 909652478L;
762c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//// int32(1.1/log(4)*2^30)
763c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//downscale = 851995103L;
764c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//// int32(sqrt(1.1/log(4))*2^30)
765c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//sqrt_downscale = 956463682L;
766c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// // int32(0.9*log(4)/1.1*2^30)
767c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//downsclimit = 1217881829L;
768c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
769c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	nr_iters = test_limits_and_scale(&x0, &pow2);
770c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
771c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	sq2scale=pow2%2;  // Find remainder. Is it even or odd?
772c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
773c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
774c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Further scaling to decrease NR iterations
775c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// With the mapping below, 89% of calculations will require 2 NR iterations or less.
776c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// TBD
777c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
778c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
779c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	x0_2 = x0 >>1; // This scaling incorporates factor of 2 in NR iteration below.
780c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Initial condition starts at 1: xx=(1L<<30);
781c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// First iteration is simple: Instead of initializing xx=1, assign to result of first iteration:
782c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// xx= (3/2-x0/2);
783c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% NR formula: xx=xx*(3/2-x0*xx*xx/2); = xx*(1.5 - (x0/2)*xx*xx)
784c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Initialize NR (first iteration). Note we are starting with xx=1, so the first iteration becomes an initialization.
785c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	xx = oneandhalf - x0_2;
786c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro 	if ( nr_iters>=2 ) {
787c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Second NR iteration
788c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult( xx, ( oneandhalf - inv_q30_mult(x0_2, inv_q30_mult(xx,xx) ) ) );
789c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if ( nr_iters==3 ) {
790c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Third NR iteration.
791c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			xx = inv_q30_mult( xx, ( oneandhalf - inv_q30_mult(x0_2, inv_q30_mult(xx,xx) ) ) );
792c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Fourth NR iteration: Not needed due to single precision.
793c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		}
794c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
795c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (sq2scale) {
796c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*rempow = (pow2>>1) + 1; // Account for sqrt(2) in denominator, note we multiply if s2scale is true
797c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return (inv_q30_mult(xx,oneoversqrt2));
798c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
799c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	else {
800c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*rempow = pow2>>1;
801c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return xx;
802c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
803c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
804c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
805c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
806c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Calculates square-root of a fixed-point number (30 bit mantissa, positive)
807c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Input must be a positive scaled (2^30) integer
808c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* The number is scaled to lie between a range in which a Newton-Raphson
809c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* iteration works best.
810c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] x0, length 1
811c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return scaledSquareRoot on success or zero. **/
812c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_fast_sqrt(long x0)
813c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
814c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
815c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% Square-Root with NR in the neighborhood of 1.3>x>=0.65 (log(2) <= x <= log(4) )
816c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Two-variable NR iteration:
817c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Initialize: a=x; c=x-1;
818c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // 1st Newton Step:  a=a-a*c/2; ( or: a = x - x*(x-1)/2  )
819c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Iterate: c = c*c*(c-3)/4
820c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    //          a = a - a*c/2    --> reevaluating c at this step gives error of approximation
821c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
822c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% Seed equals 1. Works best in this region.
823c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//xx0 = int32(1*2^30);
824c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
825c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long sqrt2, oneoversqrt2, one_pt5;
826c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long xx, cc;
827c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	int pow2, sq2scale, nr_iters;
828c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
829c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Return if input is zero. Negative should really error out.
830c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (x0 <= 0L) {
831c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return 0L;
832c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
833c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
834c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	sqrt2 =1518500250L;
835c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	oneoversqrt2=759250125L;
836c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	one_pt5=1610612736L;
837c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
838c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	nr_iters = test_limits_and_scale(&x0, &pow2);
839c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
840c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	sq2scale = 0;
841c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (pow2 > 0)
842c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		sq2scale=pow2%2;  // Find remainder. Is it even or odd?
843c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	pow2 = pow2-sq2scale; // Now pow2 is even. Note we are adding because result is scaled with sqrt(2)
844c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
845c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Sqrt 1st NR iteration
846c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	cc = x0 - (1L<<30);
847c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	xx = x0 - (inv_q30_mult(x0, cc)>>1);
848c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro 	if ( nr_iters>=2 ) {
849c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Sqrt second NR iteration
850c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// cc = cc*cc*(cc-3)/4; = cc*cc*(cc/2 - 3/2)/2;
851c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// cc = ( cc*cc*((cc>>1) - onePt5) ) >> 1
852c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		cc = inv_q30_mult( cc, inv_q30_mult(cc, (cc>>1) - one_pt5) ) >> 1;
853c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = xx - (inv_q30_mult(xx, cc)>>1);
854c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if ( nr_iters==3 ) {
855c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Sqrt third NR iteration
856c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			cc = inv_q30_mult( cc, inv_q30_mult(cc, (cc>>1) - one_pt5) ) >> 1;
857c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			xx = xx - (inv_q30_mult(xx, cc)>>1);
858c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		}
859c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
860c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (sq2scale)
861c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult(xx,oneoversqrt2);
862c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Scale the number with the half of the power of 2 scaling
863c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (pow2>0)
864c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = (xx >> (pow2>>1));
865c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	else if (pow2 == -1)
866c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult(xx,sqrt2);
867c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	return xx;
868c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
869c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
870c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Calculates 1/x of a fixed-point number (30 bit mantissa)
871c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Input must be a scaled (2^30) integer (+/-)
872c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* The number is scaled to lie between a range in which a Newton-Raphson
873c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* iteration works best. Corresponding multiplier power of two is returned.
874c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*  Caller must scale final result by 2^pow (while avoiding overflow).
875c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] x, length 1
876c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] pow, length 1
877c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return scaledOneOverX on success or zero.
878c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
879c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_one_over_x(long x0, int*pow)
880c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
881c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//% NR for 1/x in the neighborhood of log(2) => x => log(4)
882c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//%    y(k+1)=y(k)*(2 \ 96 x0*y(k))
883c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    //% with y(0) = 1 as the starting value for NR
884c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
885c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long two, xx;
886c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	int numberwasnegative, nr_iters, did_upscale, did_downscale;
887c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
888c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long upscale, downscale, upsclimit, downsclimit;
889c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
890c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	*pow = 0;
891c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Return if input is zero.
892c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (x0 == 0L) {
893c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return 0L;
894c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
895c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
896c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// This is really (2^31-1), i.e. 1.99999... .
897c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Approximation error is 1e-9. Note 2^31 will overflow to sign bit, so it can't be used here.
898c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	two = 2147483647L;
899c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
900c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(0.92/log(2)*2^30)
901c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	upscale = 1425155444L;
902c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(1.08/upscale*2^30)
903c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	upsclimit = 873697834L;
904c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
905c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(1.08/log(4)*2^30)
906c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	downscale = 836504283L;
907c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(0.92/downscale*2^30)
908c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	downsclimit = 1268000423L;
909c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
910c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Algorithm is intended to work with positive numbers only. Change sign:
911c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	numberwasnegative = 0;
912c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (x0 < 0L) {
913c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		numberwasnegative = 1;
914c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		x0 = -x0;
915c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
916c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
917c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	nr_iters = test_limits_and_scale(&x0, pow);
918c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
919c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	did_upscale=0;
920c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	did_downscale=0;
921c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Pre-scaling to reduce NR iterations and improve accuracy:
922c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (x0<=upsclimit) {
923c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		x0 = inv_q30_mult(x0, upscale);
924c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		did_upscale = 1;
925c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// The scaling ALWAYS leaves the number in the 2-NR iterations region:
926c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		nr_iters = 2;
927c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Is x0 in the single NR iteration region (0.994, 1.006) ?
928c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if (x0 > 1067299373 && x0 < 1080184275)
929c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			nr_iters = 1;
930c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	} else if (x0>=downsclimit) {
931c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		x0 = inv_q30_mult(x0, downscale);
932c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		did_downscale = 1;
933c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// The scaling ALWAYS leaves the number in the 2-NR iterations region:
934c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		nr_iters = 2;
935c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Is x0 in the single NR iteration region (0.994, 1.006) ?
936c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if (x0 > 1067299373 && x0 < 1080184275)
937c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			nr_iters = 1;
938c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
939c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
940c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	xx = (two - x0) + 1; // Note 2 will overflow so the computation (2-x) is done with "two" == (2^30-1)
941c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// First NR iteration
942c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	xx = inv_q30_mult( xx, (two - inv_q30_mult(x0, xx)) + 1 );
943c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro 	if ( nr_iters>=2 ) {
944c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Second NR iteration
945c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult( xx, (two - inv_q30_mult(x0, xx)) + 1 );
946c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if ( nr_iters==3 ) {
947c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// THird NR iteration.
948c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			xx = inv_q30_mult( xx, (two - inv_q30_mult(x0, xx)) + 1 );
949c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Fourth NR iteration: Not needed due to single precision.
950c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		}
951c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
952c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
953c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Post-scaling
954c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (did_upscale)
955c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult( xx, upscale);
956c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	else if (did_downscale)
957c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = inv_q30_mult( xx, downscale);
958c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
959c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (numberwasnegative)
960c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		xx = -xx;
961c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	return xx;
962c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
963c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
964c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Auxiliary function used by inv_OneOverX(), inv_fastSquareRoot(), inv_inverseSqrt().
965c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Finds the range of the argument, determines the optimal number of Newton-Raphson
966c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* iterations and . Corresponding square root of the power of two is returned.
967c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Restrictions: Number is represented as Q1.30.
968c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*               Number is betweeen the range 2<x<=0
969c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] x, length 1
970c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] pow, length 1
971c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return # of NR iterations, x0 scaled between log(2) and log(4) and 2^N scaling (N=pow)
972c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
973c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint test_limits_and_scale(long *x0, int *pow)
974c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
975c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	long lowerlimit, upperlimit, oneiterlothr, oneiterhithr, zeroiterlothr, zeroiterhithr;
976c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
977c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Lower Limit: ll = int32(log(2)*2^30);
978c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	lowerlimit = 744261118L;
979c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//Upper Limit ul = int32(log(4)*2^30);
980c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	upperlimit = 1488522236L;
981c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//  int32(0.9*2^30)
982c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	oneiterlothr = 966367642L;
983c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(1.1*2^30)
984c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	oneiterhithr = 1181116006L;
985c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// int32(0.99*2^30)
986c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	zeroiterlothr=1063004406L;
987c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	//int32(1.01*2^30)
988c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	zeroiterhithr=1084479242L;
989c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
990c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Scale number such that Newton Raphson iteration works best:
991c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// Find the power of two scaling that leaves the number in the optimal range,
992c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// ll <= number <= ul. Note odd powers have special scaling further below
993c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if (*x0 > upperlimit) {
994c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Halving the number will push it in the optimal range since largest value is 2
995c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*x0 = *x0>>1;
996c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*pow=-1;
997c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	} else if (*x0 < lowerlimit) {
998c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		// Find position of highest bit, counting from left, and scale number
999c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*pow=get_highest_bit_position((unsigned long*)x0);
1000c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		if (*x0 >= upperlimit) {
1001c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Halving the number will push it in the optimal range
1002c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			*x0 = *x0>>1;
1003c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			*pow=*pow-1;
1004c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		}
1005c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		else if (*x0 < lowerlimit) {
1006c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			// Doubling the number will push it in the optimal range
1007c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			*x0 = *x0<<1;
1008c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			*pow=*pow+1;
1009c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		}
1010c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	} else {
1011c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*pow = 0;
1012c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1013c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1014c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if ( *x0<oneiterlothr || *x0>oneiterhithr )
1015c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return 3; // 3 NR iterations
1016c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	if ( *x0<zeroiterlothr || *x0>zeroiterhithr )
1017c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		return 2; // 2 NR iteration
1018c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1019c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	return 1; // 1 NR iteration
1020c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1021c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1022c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Auxiliary function used by testLimitsAndScale()
1023c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Find the highest nonzero bit in an unsigned 32 bit integer:
1024c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] value, length 1.
1025c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return highes bit position.
1026c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro**/int get_highest_bit_position(unsigned long *value)
1027c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1028c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int position;
1029c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    position = 0;
1030c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (*value == 0) return 0;
1031c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1032c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((*value & 0xFFFF0000) == 0) {
1033c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		position += 16;
1034c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*value=*value<<16;
1035c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1036c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((*value & 0xFF000000) == 0) {
1037c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		position += 8;
1038c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*value=*value<<8;
1039c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1040c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((*value & 0xF0000000) == 0) {
1041c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		position += 4;
1042c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*value=*value<<4;
1043c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1044c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((*value & 0xC0000000) == 0) {
1045c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		position += 2;
1046c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*value=*value<<2;
1047c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1048c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1049c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// If we got too far into sign bit, shift back. Note we are using an
1050c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	// unsigned long here, so right shift is going to shift all the bits.
1051c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((*value & 0x80000000)) {
1052c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		position -= 1;
1053c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro		*value=*value>>1;
1054c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	}
1055c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return position;
1056c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1057c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1058c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/* compute real part of quaternion, element[0]
1059c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro@param[in]  inQuat, 3 elements gyro quaternion
1060c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro@param[out] outquat, 4 elements gyro quaternion
1061c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1062c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_compute_scalar_part(const long * inQuat, long* outQuat)
1063c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1064c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long scalarPart = 0;
1065c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1066c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    scalarPart = inv_fast_sqrt((1L<<30) - inv_q30_mult(inQuat[0], inQuat[0])
1067c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                        - inv_q30_mult(inQuat[1], inQuat[1])
1068c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                        - inv_q30_mult(inQuat[2], inQuat[2]) );
1069c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                outQuat[0] = scalarPart;
1070c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                outQuat[1] = inQuat[0];
1071c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                outQuat[2] = inQuat[1];
1072c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                outQuat[3] = inQuat[2];
1073c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1074c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                return 0;
1075c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1076c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
1077c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @}
1078c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1079