MATHLIB User Guide
MATHLIB_tan.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 
36 /******************************************************************************/
37 /* */
38 /* Includes */
39 /* */
40 /******************************************************************************/
41 
42 #include "MATHLIB_types.h"
43 #include "MATHLIB_utility.h"
44 #include <cstddef>
45 
46 /******************************************************************************/
47 /* */
48 /* MATHLIB_tan */
49 /* */
50 /******************************************************************************/
51 
52 template <typename vecType> static inline vecType recipsp_tansp_i(vecType a)
53 {
54  vecType two, zero;
55 
56  two = (vecType) 2.0;
57  zero = (vecType) 0.0;
58 
59  vecType x1, y;
60 
61  x1 = __recip(a);
62  x1 = x1 * (two - (a * x1));
63  y = x1 * (two - (a * x1));
64 
65  // if (a == zero) {
66  // y = zero;
67  // }
68  __vpred cmp_eqzero = __cmp_eq_pred((vecType) a, zero);
69  y = __select(cmp_eqzero, zero, y);
70 
71  return (y);
72 } /* End of recipsp_tansp_i */
73 
74 template <typename vecType> static inline vecType pol_est_tansp_i(vecType x)
75 {
76  vecType c12, c10, c8, c6, c4, c2;
77 
78  // coefficients for the polynomial for tan(x)
79  c12 = (vecType) 0.00457708084094171;
80  c10 = (vecType) 0.00867365970442499;
81  c8 = (vecType) 0.0236488997700456;
82  c6 = (vecType) 0.0523817525811416;
83  c4 = (vecType) 0.133766510899828;
84  c2 = (vecType) 0.333299506194791;
85 
86  vecType x2, x4, x6, x8, pol;
87  vecType tmp1, tmp2;
88 
89  // calculate the powers of x
90  x2 = x * x;
91  x4 = x2 * x2;
92  x6 = x2 * x4;
93  x8 = x4 * x4;
94 
95  /**************************************************************************/
96  /* The polynomial calculation is done in two separate parts. */
97  /* tmp1 = c2 x^2 + c4 x^4 + c6 x^6 + c8 x^8 */
98  /* tmp2 = c10 x^10 + c12 x^12 */
99  /* In order to reduce the number of multiplications x is factored out of */
100  /* the polynomial and multiplied by later. */
101  /**************************************************************************/
102 
103  tmp1 = ((c8 * x8) + (c6 * x6)) + ((c4 * x4) + (c2 * x2));
104  tmp2 = x8 * ((c10 * x2) + (c12 * x4));
105 
106  pol = ((tmp1 + tmp2) * x) + x;
107 
108  return pol;
109 }
110 
111 // this method performs tangent computation of input vector
112 template <typename T> MATHLIB_STATUS MATHLIB_tan(size_t length, T *pSrc, T *pDst)
113 {
114 
115  // variables
116  MATHLIB_STATUS status = MATHLIB_SUCCESS; // return function status
117  size_t numBlocks = 0; // compute loop's iteration count
118  size_t remNumBlocks = 0; // when numBlocks is not a multiple of SIMD width
119 
120  // derive c7x vector type from template typename
121  typedef typename c7x::make_full_vector<T>::type vec;
122 
123  // Compile-time decision: float_vec => int_vec and double_vec=> long_vec
124  typedef
125  typename std::conditional<ELEMENT_COUNT(c7x::float_vec) == ELEMENT_COUNT(vec), c7x::int_vec, c7x::long_vec>::type
126  vec_type;
127 
128  __SE_TEMPLATE_v1 se0Params = __gen_SE_TEMPLATE_v1();
129  __SA_TEMPLATE_v1 sa0Params = __gen_SA_TEMPLATE_v1();
130 
131  // check for null pointers and non-zero length
132  status = MATHLIB_checkParams(length, pSrc, pDst);
133 
134  if (status == MATHLIB_SUCCESS) {
135  MATHLIB_SE0SA01DSequentialInit(&se0Params, &sa0Params, length, pSrc, pDst);
136 
137  // calculate compute loop's iteration counter
138  numBlocks = length / c7x::element_count_of<vec>::value;
139  remNumBlocks = length % c7x::element_count_of<vec>::value;
140  if (remNumBlocks) {
141  numBlocks++;
142  }
143 
144  // open SE0, SE1, and SA0 for reading and writing operands
145  MATHLIB_SE0SA0Open(&se0Params, &sa0Params, pSrc);
146 
147  vec pi4, pi2_h, pi2_l, pi, invPI, C1, C2, C3, one, zero, negativeOne, res, y, temp, temp_gtPI4, res_gtPI4,
148  y_gtPI4;
149 
150  pi4 = (vec) 0.785398163; // pi/4
151  pi2_h = (vec) 1.570796;
152  pi2_l = (vec) 3.26794896476912e-7; // pi2_h + pi2_l = pi/2
153  pi = (vec) 3.14159265358979;
154  C1 = (vec) 3.140625;
155  C2 = (vec) 9.676535e-4;
156  C3 = (vec) 8.97930618748433e-11; // C1 + C2 + C3 = PI
157  invPI = (vec) 0.318309886183791; // 1/pi
158  one = (vec) 1.0;
159  zero = (vec) 0.0;
160  negativeOne = (vec) -1.0;
161 
162  vec_type N;
163 
164  // compute loop to perform vector tan
165  for (size_t i = 0; i < numBlocks; i++) {
166  vec a = c7x::strm_eng<0, vec>::get_adv();
167 
168  vec sign = one;
169  // extract multiples of pi
170  temp = a * invPI;
171 
172  // N = multiple of pi in x
173  N = __float_to_int(temp);
174 
175  y = ((a - (c7x::convert<vec>(N) * C1)) - (c7x::convert<vec>(N) * C2)) - (c7x::convert<vec>(N) * C3);
176 
177  // if(y > pi2_h){
178  // y = y - pi; // x is in the range [-pi/2, pi/2]
179  // }
180  vec yminusPi = y - pi;
181  __vpred cmp_gt = __cmp_lt_pred((vec) pi2_h, y);
182  y = __select(cmp_gt, yminusPi, y);
183 
184  // if(y < zero){
185  // sign = -sign; // sign variable
186  // y = -y;
187  // }
188  vec negativeY = -y;
189  __vpred cmp_zero = __cmp_lt_pred(y, zero);
190  y = __select(cmp_zero, negativeY, y);
191 
192  vec Sign_vec = __select(cmp_zero, negativeOne, sign);
193 
194  __vpred cmp_yPI4 = __cmp_lt_pred(pi4, y);
195 
196  y_gtPI4 = (pi2_h - y) + pi2_l; // pi/2 - y
197  temp_gtPI4 = pol_est_tansp_i<vec>(y_gtPI4);
198  res_gtPI4 = recipsp_tansp_i<vec>(temp_gtPI4); // 1/tan(pi/2 - y)
199  res = pol_est_tansp_i<vec>(y);
200 
201  res = __select(cmp_yPI4, res_gtPI4, res);
202 
203  res = res * Sign_vec;
204 
205  __vpred tmp = c7x::strm_agen<0, vec>::get_vpred();
206  vec *VB1 = c7x::strm_agen<0, vec>::get_adv(pDst);
207 
208  __vstore_pred(tmp, VB1, res);
209  }
210 
212  }
213 
214  return status;
215 }
216 
217 /******************************************************************************/
218 /* */
219 /* Explicit templatization for datatypes supported by MATHLIB_tan */
220 /* */
221 /******************************************************************************/
222 
223 // single precision
224 template MATHLIB_STATUS MATHLIB_tan<float>(size_t length, float *pSrc, float *pDst);
225 
226 /******************************************************************************/
227 /* */
228 /* C-interface wrapper functions */
229 /* */
230 /******************************************************************************/
231 
232 extern "C" {
233 
234 // single-precision wrapper
235 MATHLIB_STATUS MATHLIB_tan_sp(size_t length, float *pSrc, float *pDst)
236 {
237  MATHLIB_STATUS status = MATHLIB_tan(length, pSrc, pDst);
238  return status;
239 }
240 
241 } // extern "C"
static vecType pol_est_tansp_i(vecType x)
Definition: MATHLIB_tan.cpp:74
#define ELEMENT_COUNT(x)
Definition: MATHLIB_tan.cpp:34
static vecType recipsp_tansp_i(vecType a)
Definition: MATHLIB_tan.cpp:52
template MATHLIB_STATUS MATHLIB_tan< float >(size_t length, float *pSrc, float *pDst)
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 MATHLIB_tan_sp(size_t length, float *pSrc, float *pDst)
This function is the C interface for MATHLIB_tan. Function accepts float pointers.
MATHLIB_STATUS MATHLIB_tan(size_t length, T *pSrc, T *pDst)
Performs the elementwise tangent of an input vector. Function can be overloaded with float pointers,...
MATHLIB_STATUS_NAME
The enumeration of all status codes.
@ MATHLIB_SUCCESS