1 /* --------------------------------------------------------------  */
2 /* (C)Copyright 2007,2008,                                         */
3 /* International Business Machines Corporation                     */
4 /* All Rights Reserved.                                            */
5 /*                                                                 */
6 /* Redistribution and use in source and binary forms, with or      */
7 /* without modification, are permitted provided that the           */
8 /* following conditions are met:                                   */
9 /*                                                                 */
10 /* - Redistributions of source code must retain the above copyright*/
11 /*   notice, this list of conditions and the following disclaimer. */
12 /*                                                                 */
13 /* - Redistributions in binary form must reproduce the above       */
14 /*   copyright notice, this list of conditions and the following   */
15 /*   disclaimer in the documentation and/or other materials        */
16 /*   provided with the distribution.                               */
17 /*                                                                 */
18 /* - Neither the name of IBM Corporation nor the names of its      */
19 /*   contributors may be used to endorse or promote products       */
20 /*   derived from this software without specific prior written     */
21 /*   permission.                                                   */
22 /*                                                                 */
23 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND          */
24 /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,     */
25 /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF        */
26 /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE        */
27 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR            */
28 /* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    */
29 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT    */
30 /* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;    */
31 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)        */
32 /* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN       */
33 /* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR    */
34 /* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  */
35 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              */
36 /* --------------------------------------------------------------  */
37 /* PROLOG END TAG zYx                                              */
38 #ifdef __SPU__
39 #ifndef _ASINHF4_H_
40 #define _ASINHF4_H_	1
41 
42 #include <spu_intrinsics.h>
43 
44 #include "logf4.h"
45 #include "sqrtf4.h"
46 
47 /*
48  * FUNCTION
49  *  vector float _asinhf4(vector float x)
50  *
51  * DESCRIPTION
52  *  The asinhf4 function returns a vector containing the hyperbolic
53  *  arcsines of the corresponding elements of the input vector.
54  *
55  *  We are using the formula:
56  *    asinh = ln(|x| + sqrt(x^2 + 1))
57  *  and the anti-symmetry of asinh.
58  *
59  *  For x near zero, we use the Taylor series:
60  *
61  *                infinity
62  *                 ------
63  *                  -   '  P  (0)
64  *                   -      k-1    k
65  *    asinh x =       -    -----  x
66  *                   -       k
67  *                  -   ,
68  *                 ------
69  *                 k = 1
70  *
71  *  Special Cases:
72  *   - asinh(+0)        returns +0
73  *   - asinh(-0)        returns -0
74  *   - Normally,  asinh(+/- infinity) returns +/- infinity,
75  *	   but on the SPU, single-precision infinity is not supported,
76  *	   so it is treated as a normal number here.
77  *
78  */
79 
80 /*
81  * Maclaurin Series Coefficients
82  * for x near 0.
83  */
84 #define ASINH_MAC01     1.0000000000000000000000000000000000000000000000000000000000000000000000E0
85 #define ASINH_MAC03     -1.6666666666666666666666666666666666666666666666666666666666666666666667E-1
86 #define ASINH_MAC05     7.5000000000000000000000000000000000000000000000000000000000000000000000E-2
87 #define ASINH_MAC07     -4.4642857142857142857142857142857142857142857142857142857142857142857143E-2
88 #define ASINH_MAC09     3.0381944444444444444444444444444444444444444444444444444444444444444444E-2
89 #define ASINH_MAC11     -2.2372159090909090909090909090909090909090909090909090909090909090909091E-2
90 #define ASINH_MAC13     1.7352764423076923076923076923076923076923076923076923076923076923076923E-2
91 #define ASINH_MAC15     -1.3964843750000000000000000000000000000000000000000000000000000000000000E-2
92 #define ASINH_MAC17     1.1551800896139705882352941176470588235294117647058823529411764705882353E-2
93 #define ASINH_MAC19     -9.7616095291940789473684210526315789473684210526315789473684210526315789E-3
94 #define ASINH_MAC21     8.3903358096168154761904761904761904761904761904761904761904761904761905E-3
95 #define ASINH_MAC23     -7.3125258735988451086956521739130434782608695652173913043478260869565217E-3
96 #define ASINH_MAC25     6.4472103118896484375000000000000000000000000000000000000000000000000000E-3
97 #define ASINH_MAC27     -5.7400376708419234664351851851851851851851851851851851851851851851851852E-3
98 #define ASINH_MAC29     5.1533096823199041958512931034482758620689655172413793103448275862068966E-3
99 #define ASINH_MAC31     -4.6601434869150961599042338709677419354838709677419354838709677419354839E-3
100 #if 0
101 #define ASINH_MAC33     4.2409070936793630773370916193181818181818181818181818181818181818181818E-3
102 #define ASINH_MAC35     -3.8809645588376692363194056919642857142857142857142857142857142857142857E-3
103 #define ASINH_MAC37     3.5692053938259345454138678473395270270270270270270270270270270270270270E-3
104 #define ASINH_MAC39     -3.2970595034734847453924325796274038461538461538461538461538461538461538E-3
105 #define ASINH_MAC41     3.0578216492580306693548109473251714939024390243902439024390243902439024E-3
106 #define ASINH_MAC43     -2.8461784011089421678767647854117460029069767441860465116279069767441860E-3
107 #endif
108 
109 
_asinhf4(vector float x)110 static __inline vector float _asinhf4(vector float x)
111 {
112     vec_float4 sign_mask = spu_splats(-0.0f);
113     vec_float4 onef      = spu_splats(1.0f);
114     vec_uint4  oneu      = spu_splats(1u);
115     vec_uint4  twou      = spu_splats(2u);
116     vec_uint4  threeu    = spu_splats(3u);
117     vec_float4 ln2       = spu_splats(6.931471805599453094172321E-1f);
118     vec_float4 largef    = spu_splats(9.21e18f);
119     vec_float4 result, fresult, mresult;
120     vec_float4 xabs, xsqu;
121     /* Where we switch from maclaurin to formula */
122     vec_float4  switch_approx = spu_splats(0.74f);
123     vec_float4  trunc_part2   = spu_splats(20.0f);
124     vec_uint4   truncadd;
125     vec_uint4   islarge;
126     vec_uint4   use_form;
127 
128     xabs = spu_andc(x, sign_mask);
129     xsqu = spu_mul(x, x);
130     islarge = spu_cmpgt(xabs, largef);
131 
132     /*
133      * Formula:
134      *   asinh = ln(|x| + sqrt(x^2 + 1))
135      */
136 
137     vec_float4 logarg = spu_add(xabs, _sqrtf4(spu_madd(xabs, xabs, onef)));
138     logarg = spu_sel(logarg, xabs, islarge);
139     fresult = _logf4(logarg);
140     fresult = spu_sel(fresult, spu_add(fresult, ln2), islarge);
141 
142     /*
143      * Maclaurin Series
144      */
145     mresult = spu_madd(xsqu, spu_splats((float)ASINH_MAC31), spu_splats((float)ASINH_MAC29));
146     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC27));
147     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC25));
148     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC23));
149     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC21));
150     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC19));
151     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC17));
152     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC15));
153     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC13));
154     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC11));
155     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC09));
156     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC07));
157     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC05));
158     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC03));
159     mresult = spu_madd(xsqu, mresult, spu_splats((float)ASINH_MAC01));
160     mresult = spu_mul(xabs, mresult);
161 
162     /*
163      * Choose between series and formula
164      */
165     use_form  = spu_cmpgt(xabs, switch_approx);
166     result = spu_sel(mresult, fresult, use_form);
167 
168     /*
169      * Truncation correction on spu
170      */
171     truncadd = spu_sel(oneu, threeu, use_form);
172     truncadd = spu_sel(truncadd, twou, spu_cmpgt(xabs, trunc_part2));
173     result = (vec_float4)spu_add((vec_uint4)result, truncadd);
174 
175     /* Preserve sign - asinh is anti-symmetric */
176     result = spu_sel(result, x, (vec_uint4)sign_mask);
177 
178     return result;
179 }
180 
181 #endif /* _ASINHF4_H_ */
182 #endif /* __SPU__ */
183