MATHLIB User Guide
MATHLIB_atan.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the
14  * distribution.
15  *
16  * Neither the name of Texas Instruments Incorporated nor the names of
17  * its contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  ******************************************************************************/
33 
34 #define ELEMENT_COUNT(x) c7x::element_count_of<x>::value
35 /* the type of data that 'type x data structure' (i.e. vecType) holds */
36 #define ELEMENT_TYPE(x) typename c7x::element_type_of<x>::type
37 
38 /******************************************************************************/
39 /* */
40 /* Includes */
41 /* */
42 /******************************************************************************/
43 
44 #include "MATHLIB_types.h"
45 #include "MATHLIB_utility.h"
46 #include <cstddef>
47 
48 /******************************************************************************/
49 /* */
50 /* MATHLIB_atan */
51 /* */
52 /******************************************************************************/
53 
54 template <typename vecType> static inline vecType divspMod_atan_i(vecType a, vecType b);
55 template <typename vecType> static inline vecType atan2f_sr1i_atan_i(vecType g1, vecType s, vecType an);
56 template <typename T> MATHLIB_STATUS MATHLIB_atan(size_t length, T *pSrc, T *pDst);
57 
58 template <typename vecType> static inline vecType divspMod_atan_i(vecType a, vecType b)
59 {
60  vecType res, r0, d0, d1, p0, p1, Two;
61 
62  Two = (vecType) 2.0;
63 
64  p0 = __recip(b);
65  d0 = p0 * b;
66  r0 = p0;
67 
68  p1 = Two - d0;
69  d1 = r0 * p1;
70 
71  res = a * d1;
72 
73  return res;
74 }
75 
76 template <typename vecType, typename vecBool>
77 static inline vecType atan2f_sr1i_atan_i(vecType g1, vecBool s, vecBool an)
78 {
79 
80  /*************************************************************************************/
81  /* Create and assign values for constants and variables for polynomial approximation */
82  /*************************************************************************************/
83  vecType coef, negativeCoef, pih, pol, Zero, g2, g4, g6, g8, g10, g12, tmp1, tmp2, c1, c2, c3, c4, c5, c6, c7, c8,
84  res, res_minus, res_plus;
85  vecBool FALSE;
86 
87  FALSE = (vecBool) 0;
88  Zero = (vecType) 0.0;
89 
90  pih = (vecType) 1.57079632679;
91 
92  c1 = (vecType) 0.00230158202;
93  c2 = (vecType) -0.01394551000;
94  c3 = (vecType) 0.03937087815;
95  c4 = (vecType) -0.07235669163;
96  c5 = (vecType) 0.10521499322;
97  c6 = (vecType) -0.14175076797;
98  c7 = (vecType) 0.19989300877;
99  c8 = (vecType) -0.33332930041;
100 
101  coef = pih;
102 
103  // get coef based on the flags
104  // check 'swap' flag
105  // if (s == FALSE) {
106  // coef = 0.0f;
107  // }
108  __vpred cmp_swap = __cmp_eq_pred(s, FALSE);
109  coef = __select(cmp_swap, Zero, coef);
110 
111  // check if input to atansp_i is negative
112  // if (an != FALSE) {
113  // coef = -coef;
114  // }
115  negativeCoef = -coef;
116  __vpred cmp_sign = __cmp_eq_pred(an, FALSE);
117  coef = __select(cmp_sign, coef, negativeCoef);
118 
119  // calculate polynomial
120  g2 = g1 * g1;
121  g4 = g2 * g2;
122  g6 = g2 * g4;
123  g8 = g4 * g4;
124  g10 = g6 * g4;
125  g12 = g8 * g4;
126 
127  tmp1 = ((c5 * g8) + (c6 * g6)) + ((c7 * g4) + (c8 * g2));
128  tmp2 = ((((c1 * g4) + (c2 * g2)) + c3) * g12) + (c4 * g10);
129 
130  pol = tmp1 + tmp2;
131  pol = (pol * g1) + g1;
132 
133  // return ((s != FALSE) ? (coef - pol) : (coef + pol));
134  res_minus = coef - pol;
135  res_plus = coef + pol;
136  __vpred cmp_res = __cmp_eq_pred(s, FALSE);
137  res = __select(cmp_res, res_plus, res_minus);
138 
139  return res;
140 }
141 
142 // this method performs arc-tangent computation of input vector
143 template <typename T> MATHLIB_STATUS MATHLIB_atan(size_t length, T *pSrc, T *pDst)
144 {
145 
146  // variables
147  MATHLIB_STATUS status = MATHLIB_SUCCESS; // return function status
148  size_t numBlocks = 0; // compute loop's iteration count
149  size_t remNumBlocks = 0; // when numBlocks is not a multiple of SIMD width
150 
151  // derive c7x vector type from template typename
152  typedef typename c7x::make_full_vector<T>::type vec;
153 
154  __SE_TEMPLATE_v1 se0Params = __gen_SE_TEMPLATE_v1();
155  __SA_TEMPLATE_v1 sa0Params = __gen_SA_TEMPLATE_v1();
156 
157  status = MATHLIB_checkParams(length, pSrc, pDst);
158 
159  if (status == MATHLIB_SUCCESS) {
160  MATHLIB_SE0SA01DSequentialInit(&se0Params, &sa0Params, length, pSrc, pDst);
161 
162  // calculate compute loop's iteration counter
163  numBlocks = length / c7x::element_count_of<vec>::value;
164  remNumBlocks = length % c7x::element_count_of<vec>::value;
165  if (remNumBlocks) {
166  numBlocks++;
167  }
168 
169  // open SE0, SE1, and SA0 for reading and writing operands
170  MATHLIB_SE0SA0Open(&se0Params, &sa0Params, pSrc);
171 
172  /***********************************************************************/
173  /* Create and assign values for constants employed on atan computation */
174  /***********************************************************************/
175  vec g, res, b, x_abs, One, Zero;
176  c7x::char_vec an, s, TRUE, FALSE;
177 
178  TRUE = (c7x::char_vec) 1;
179  FALSE = (c7x::char_vec) 0;
180  One = (vec) 1.0;
181  Zero = (vec) 0.0;
182 
183  // compute loop to perform vector atan
184  for (size_t i = 0; i < numBlocks; i++) {
185  vec inVec = c7x::strm_eng<0, vec>::get();
186 
187  s = (c7x::char_vec) 0;
188  b = (vec) 1.0;
189  x_abs = __abs(inVec);
190 
191  // an = (a < 0.0f) ? TRUE : FALSE;
192  __vpred cmp_flag = __cmp_lt_pred(inVec, Zero);
193  an = __select(cmp_flag, TRUE, FALSE);
194 
195  // swap a and b before calling division sub routine if a > b
196  // if (_fabsf(a) > 1.0f) {
197  // temp = a;
198  // a = 1.0f;
199  // s = TRUE;
200  // }
201  vec a = c7x::strm_eng<0, vec>::get_adv();
202 
203  __vpred cmp_div = __cmp_lt_pred(One, x_abs);
204  b = __select(cmp_div, a, b);
205  a = __select(cmp_div, One, a);
206  s = __select(cmp_div, TRUE, s);
207 
208  /***********************************************************************/
209  /* Division computation for atan */
210  /***********************************************************************/
211  g = divspMod_atan_i<vec>(a, b);
212 
213  /***********************************************************************/
214  /* Polynomial computation for atan */
215  /***********************************************************************/
216  res = atan2f_sr1i_atan_i<vec, c7x::char_vec>(g, s, an);
217 
218  /***********************************************************************/
219  /* Bounds Checking */
220  /***********************************************************************/
221 
222  // if (a == 0.0f) {
223  // res = 0.0f;
224  // }
225  __vpred cmp_zero = __cmp_eq_pred(a, Zero);
226  res = __select(cmp_zero, Zero, res);
227 
228  vec outVec = res;
229 
230  __vpred tmp = c7x::strm_agen<0, vec>::get_vpred();
231  vec *addr = c7x::strm_agen<0, vec>::get_adv(pDst);
232  __vstore_pred(tmp, addr, outVec);
233  }
234 
236  }
237 
238  return status;
239 }
240 
241 /******************************************************************************/
242 /* */
243 /* Explicit templatization for datatypes supported by MATHLIB_atan */
244 /* */
245 /******************************************************************************/
246 
247 // single precision
248 template MATHLIB_STATUS MATHLIB_atan<float>(size_t length, float *pSrc, float *pDst);
249 
250 /******************************************************************************/
251 /* */
252 /* C-interface wrapper functions */
253 /* */
254 /******************************************************************************/
255 
256 extern "C" {
257 
258 // single-precision wrapper
259 MATHLIB_STATUS MATHLIB_atan_sp(size_t length, float *pSrc, float *pDst)
260 {
261  MATHLIB_STATUS status = MATHLIB_atan(length, pSrc, pDst);
262  return status;
263 }
264 
265 } // extern "C"
template MATHLIB_STATUS MATHLIB_atan< float >(size_t length, float *pSrc, float *pDst)
static vecType atan2f_sr1i_atan_i(vecType g1, vecType s, vecType an)
static vecType divspMod_atan_i(vecType a, vecType b)
#define TRUE
#define FALSE
MATHLIB_STATUS MATHLIB_atan_sp(size_t length, float *pSrc, float *pDst)
This function is the C interface for MATHLIB_atan. Function accepts float pointers.
MATHLIB_STATUS MATHLIB_atan(size_t length, T *pSrc, T *pDst)
Performs the elementwise arc-tangent of the input vector. Function can be overloaded with float point...
static void MATHLIB_SE0SA0Close()
This method performs SE0 and SA0 close.
static void MATHLIB_SE0SA01DSequentialInit(__SE_TEMPLATE_v1 *se0Params, __SA_TEMPLATE_v1 *sa0Params, size_t length, T *pSrc, T *pDst)
static MATHLIB_STATUS MATHLIB_checkParams(size_t length, T *pSrc, T *pDst)
This method performs parameter checks for MATHLIB function.
static void MATHLIB_SE0SA0Open(__SE_TEMPLATE_v1 *se0Params, __SA_TEMPLATE_v1 *sa0Params, T *pSrc)
This method performs SE0 and SA0 open.
MATHLIB_STATUS_NAME
The enumeration of all status codes.
@ MATHLIB_SUCCESS