arm_atan2_q15.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_atan2_q15.c
  4. * Description: float32 Arc tangent of y/x
  5. *
  6. * $Date: 22 April 2022
  7. * $Revision: V1.10.0
  8. *
  9. * Target Processor: Cortex-M and Cortex-A cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #include "dsp/fast_math_functions.h"
  29. #include "dsp/utils.h"
  30. /*
  31. atan for argument between in [0, 1.0]
  32. */
  33. /* Q2.13 */
  34. #define ATANHALFQ13 0xed6
  35. #define PIHALFQ13 0x3244
  36. #define PIQ13 0x6488
  37. #define ATAN2_NB_COEFS_Q15 10
  38. static const q15_t atan2_coefs_q15[ATAN2_NB_COEFS_Q15]={
  39. 0, // 0x0000
  40. 32767, // 0x7fff
  41. -1, // 0xffff
  42. -10905, // 0xd567
  43. -144, // 0xff70
  44. 7085, // 0x1bad
  45. -680, // 0xfd58
  46. -5719, // 0xe9a9
  47. 4393, // 0x1129
  48. -1061 // 0xfbdb
  49. };
  50. __STATIC_FORCEINLINE q15_t arm_atan_limited_q15(q15_t x)
  51. {
  52. q31_t res=(q31_t)atan2_coefs_q15[ATAN2_NB_COEFS_Q15-1];
  53. int i=1;
  54. for(i=1;i<ATAN2_NB_COEFS_Q15;i++)
  55. {
  56. res = ((q31_t) x * res) >> 15U;
  57. res = res + ((q31_t) atan2_coefs_q15[ATAN2_NB_COEFS_Q15-1-i]) ;
  58. }
  59. res = __SSAT(res>>2,16);
  60. return(res);
  61. }
  62. __STATIC_FORCEINLINE q15_t arm_atan_q15(q15_t y,q15_t x)
  63. {
  64. int sign=0;
  65. q15_t res=0;
  66. if (y<0)
  67. {
  68. /* Negate y */
  69. #if defined (ARM_MATH_DSP)
  70. y = __QSUB16(0, y);
  71. #else
  72. y = (y == (q15_t) 0x8000) ? (q15_t) 0x7fff : -y;
  73. #endif
  74. sign=1-sign;
  75. }
  76. if (x < 0)
  77. {
  78. sign=1 - sign;
  79. /* Negate x */
  80. #if defined (ARM_MATH_DSP)
  81. x = __QSUB16(0, x);
  82. #else
  83. x = (x == (q15_t) 0x8000) ? (q15_t) 0x7fff : -x;
  84. #endif
  85. }
  86. if (y > x)
  87. {
  88. q15_t ratio;
  89. int16_t shift;
  90. arm_divide_q15(x,y,&ratio,&shift);
  91. /* Shift ratio by shift */
  92. if (shift >=0)
  93. {
  94. ratio = __SSAT(((q31_t) ratio << shift), 16);
  95. }
  96. else
  97. {
  98. ratio = (ratio >> -shift);
  99. }
  100. res = PIHALFQ13 - arm_atan_limited_q15(ratio);
  101. }
  102. else
  103. {
  104. q15_t ratio;
  105. int16_t shift;
  106. arm_divide_q15(y,x,&ratio,&shift);
  107. /* Shift ratio by shift */
  108. if (shift >=0)
  109. {
  110. ratio = __SSAT(((q31_t) ratio << shift), 16);
  111. }
  112. else
  113. {
  114. ratio = (ratio >> -shift);
  115. }
  116. res = arm_atan_limited_q15(ratio);
  117. }
  118. if (sign)
  119. {
  120. /* Negate res */
  121. #if defined (ARM_MATH_DSP)
  122. res = __QSUB16(0, res);
  123. #else
  124. res = (res == (q15_t) 0x8000) ? (q15_t) 0x7fff : -res;
  125. #endif
  126. }
  127. return(res);
  128. }
  129. /**
  130. @ingroup groupFastMath
  131. */
  132. /**
  133. @addtogroup atan2
  134. @{
  135. */
  136. /**
  137. @brief Arc Tangent of y/x using sign of y and x to get right quadrant
  138. @param[in] y y coordinate
  139. @param[in] x x coordinate
  140. @param[out] result Result in Q2.13
  141. @return error status.
  142. @par Compute the Arc tangent of y/x:
  143. The sign of y and x are used to determine the right quadrant
  144. and compute the right angle.
  145. */
  146. arm_status arm_atan2_q15(q15_t y,q15_t x,q15_t *result)
  147. {
  148. if (x > 0)
  149. {
  150. *result=arm_atan_q15(y,x);
  151. return(ARM_MATH_SUCCESS);
  152. }
  153. if (x < 0)
  154. {
  155. if (y > 0)
  156. {
  157. *result=arm_atan_q15(y,x) + PIQ13;
  158. }
  159. else if (y < 0)
  160. {
  161. *result=arm_atan_q15(y,x) - PIQ13;
  162. }
  163. else
  164. {
  165. if (y<0)
  166. {
  167. *result= -PIQ13;
  168. }
  169. else
  170. {
  171. *result= PIQ13;
  172. }
  173. }
  174. return(ARM_MATH_SUCCESS);
  175. }
  176. if (x == 0)
  177. {
  178. if (y > 0)
  179. {
  180. *result=PIHALFQ13;
  181. return(ARM_MATH_SUCCESS);
  182. }
  183. if (y < 0)
  184. {
  185. *result=-PIHALFQ13;
  186. return(ARM_MATH_SUCCESS);
  187. }
  188. }
  189. return(ARM_MATH_NANINF);
  190. }
  191. /**
  192. @} end of atan2 group
  193. */