arm_atan2_q15.c
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 29 #include "dsp/fast_math_functions.h" 30 #include "dsp/utils.h" 31 32 /* 33 34 atan for argument between in [0, 1.0] 35 36 */ 37 38 39 /* Q2.13 */ 40 #define ATANHALFQ13 0xed6 41 #define PIHALFQ13 0x3244 42 #define PIQ13 0x6488 43 44 #define ATAN2_NB_COEFS_Q15 10 45 46 static const q15_t atan2_coefs_q15[ATAN2_NB_COEFS_Q15]={0x0000 47 ,0x7fff 48 ,0xffff 49 ,0xd567 50 ,0xff70 51 ,0x1bad 52 ,0xfd58 53 ,0xe9a9 54 ,0x1129 55 ,0xfbdb 56 }; 57 58 __STATIC_FORCEINLINE q15_t arm_atan_limited_q15(q15_t x) 59 { 60 q31_t res=(q31_t)atan2_coefs_q15[ATAN2_NB_COEFS_Q15-1]; 61 int i=1; 62 for(i=1;i<ATAN2_NB_COEFS_Q15;i++) 63 { 64 res = ((q31_t) x * res) >> 15U; 65 res = res + ((q31_t) atan2_coefs_q15[ATAN2_NB_COEFS_Q15-1-i]) ; 66 } 67 68 res = __SSAT(res>>2,16); 69 70 71 return(res); 72 } 73 74 75 __STATIC_FORCEINLINE q15_t arm_atan_q15(q15_t y,q15_t x) 76 { 77 int sign=0; 78 q15_t res=0; 79 80 if (y<0) 81 { 82 arm_negate_q15(&y,&y,1); 83 sign=1-sign; 84 } 85 86 if (x < 0) 87 { 88 sign=1 - sign; 89 arm_negate_q15(&x,&x,1); 90 } 91 92 if (y > x) 93 { 94 q15_t ratio; 95 int16_t shift; 96 97 arm_divide_q15(x,y,&ratio,&shift); 98 99 arm_shift_q15(&ratio,shift,&ratio,1); 100 101 res = PIHALFQ13 - arm_atan_limited_q15(ratio); 102 103 } 104 else 105 { 106 q15_t ratio; 107 int16_t shift; 108 109 arm_divide_q15(y,x,&ratio,&shift); 110 111 arm_shift_q15(&ratio,shift,&ratio,1); 112 113 res = arm_atan_limited_q15(ratio); 114 115 } 116 117 118 if (sign) 119 { 120 arm_negate_q15(&res,&res,1); 121 } 122 123 return(res); 124 } 125 126 127 /** 128 @ingroup groupFastMath 129 */ 130 131 132 /** 133 @addtogroup atan2 134 @{ 135 */ 136 137 /** 138 @brief Arc Tangent of y/x using sign of y and x to get right quadrant 139 @param[in] y y coordinate 140 @param[in] x x coordinate 141 @param[out] result Result in Q2.13 142 @return error status. 143 144 @par Compute the Arc tangent of y/x: 145 The sign of y and x are used to determine the right quadrant 146 and compute the right angle. 147 */ 148 149 150 arm_status arm_atan2_q15(q15_t y,q15_t x,q15_t *result) 151 { 152 if (x > 0) 153 { 154 *result=arm_atan_q15(y,x); 155 return(ARM_MATH_SUCCESS); 156 } 157 if (x < 0) 158 { 159 if (y > 0) 160 { 161 *result=arm_atan_q15(y,x) + PIQ13; 162 } 163 else if (y < 0) 164 { 165 *result=arm_atan_q15(y,x) - PIQ13; 166 } 167 else 168 { 169 if (y<0) 170 { 171 *result= -PIQ13; 172 } 173 else 174 { 175 *result= PIQ13; 176 } 177 } 178 return(ARM_MATH_SUCCESS); 179 } 180 if (x == 0) 181 { 182 if (y > 0) 183 { 184 *result=PIHALFQ13; 185 return(ARM_MATH_SUCCESS); 186 } 187 if (y < 0) 188 { 189 *result=-PIHALFQ13; 190 return(ARM_MATH_SUCCESS); 191 } 192 } 193 194 195 return(ARM_MATH_NANINF); 196 197 } 198 199 /** 200 @} end of atan2 group 201 */