1*b843c749SSergey Zigachev /*
2*b843c749SSergey Zigachev * Copyright 2012-15 Advanced Micro Devices, Inc.
3*b843c749SSergey Zigachev *
4*b843c749SSergey Zigachev * Permission is hereby granted, free of charge, to any person obtaining a
5*b843c749SSergey Zigachev * copy of this software and associated documentation files (the "Software"),
6*b843c749SSergey Zigachev * to deal in the Software without restriction, including without limitation
7*b843c749SSergey Zigachev * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*b843c749SSergey Zigachev * and/or sell copies of the Software, and to permit persons to whom the
9*b843c749SSergey Zigachev * Software is furnished to do so, subject to the following conditions:
10*b843c749SSergey Zigachev *
11*b843c749SSergey Zigachev * The above copyright notice and this permission notice shall be included in
12*b843c749SSergey Zigachev * all copies or substantial portions of the Software.
13*b843c749SSergey Zigachev *
14*b843c749SSergey Zigachev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*b843c749SSergey Zigachev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*b843c749SSergey Zigachev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17*b843c749SSergey Zigachev * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*b843c749SSergey Zigachev * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*b843c749SSergey Zigachev * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*b843c749SSergey Zigachev * OTHER DEALINGS IN THE SOFTWARE.
21*b843c749SSergey Zigachev *
22*b843c749SSergey Zigachev * Authors: AMD
23*b843c749SSergey Zigachev *
24*b843c749SSergey Zigachev */
25*b843c749SSergey Zigachev
26*b843c749SSergey Zigachev #ifndef __DAL_FIXED31_32_H__
27*b843c749SSergey Zigachev #define __DAL_FIXED31_32_H__
28*b843c749SSergey Zigachev
29*b843c749SSergey Zigachev #ifndef LLONG_MAX
30*b843c749SSergey Zigachev #define LLONG_MAX 9223372036854775807ll
31*b843c749SSergey Zigachev #endif
32*b843c749SSergey Zigachev #ifndef LLONG_MIN
33*b843c749SSergey Zigachev #define LLONG_MIN (-LLONG_MAX - 1ll)
34*b843c749SSergey Zigachev #endif
35*b843c749SSergey Zigachev
36*b843c749SSergey Zigachev #define FIXED31_32_BITS_PER_FRACTIONAL_PART 32
37*b843c749SSergey Zigachev #ifndef LLONG_MIN
38*b843c749SSergey Zigachev #define LLONG_MIN (1LL<<63)
39*b843c749SSergey Zigachev #endif
40*b843c749SSergey Zigachev #ifndef LLONG_MAX
41*b843c749SSergey Zigachev #define LLONG_MAX (-1LL>>1)
42*b843c749SSergey Zigachev #endif
43*b843c749SSergey Zigachev
44*b843c749SSergey Zigachev /*
45*b843c749SSergey Zigachev * @brief
46*b843c749SSergey Zigachev * Arithmetic operations on real numbers
47*b843c749SSergey Zigachev * represented as fixed-point numbers.
48*b843c749SSergey Zigachev * There are: 1 bit for sign,
49*b843c749SSergey Zigachev * 31 bit for integer part,
50*b843c749SSergey Zigachev * 32 bits for fractional part.
51*b843c749SSergey Zigachev *
52*b843c749SSergey Zigachev * @note
53*b843c749SSergey Zigachev * Currently, overflows and underflows are asserted;
54*b843c749SSergey Zigachev * no special result returned.
55*b843c749SSergey Zigachev */
56*b843c749SSergey Zigachev
57*b843c749SSergey Zigachev struct fixed31_32 {
58*b843c749SSergey Zigachev long long value;
59*b843c749SSergey Zigachev };
60*b843c749SSergey Zigachev
61*b843c749SSergey Zigachev
62*b843c749SSergey Zigachev /*
63*b843c749SSergey Zigachev * @brief
64*b843c749SSergey Zigachev * Useful constants
65*b843c749SSergey Zigachev */
66*b843c749SSergey Zigachev
67*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_zero = { 0 };
68*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };
69*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };
70*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };
71*b843c749SSergey Zigachev
72*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_pi = { 13493037705LL };
73*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_two_pi = { 26986075409LL };
74*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_e = { 11674931555LL };
75*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_ln2 = { 2977044471LL };
76*b843c749SSergey Zigachev static const struct fixed31_32 dc_fixpt_ln2_div_2 = { 1488522236LL };
77*b843c749SSergey Zigachev
78*b843c749SSergey Zigachev /*
79*b843c749SSergey Zigachev * @brief
80*b843c749SSergey Zigachev * Initialization routines
81*b843c749SSergey Zigachev */
82*b843c749SSergey Zigachev
83*b843c749SSergey Zigachev /*
84*b843c749SSergey Zigachev * @brief
85*b843c749SSergey Zigachev * result = numerator / denominator
86*b843c749SSergey Zigachev */
87*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_from_fraction(long long numerator, long long denominator);
88*b843c749SSergey Zigachev
89*b843c749SSergey Zigachev /*
90*b843c749SSergey Zigachev * @brief
91*b843c749SSergey Zigachev * result = arg
92*b843c749SSergey Zigachev */
dc_fixpt_from_int(int arg)93*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_from_int(int arg)
94*b843c749SSergey Zigachev {
95*b843c749SSergey Zigachev struct fixed31_32 res;
96*b843c749SSergey Zigachev
97*b843c749SSergey Zigachev res.value = (long long) arg << FIXED31_32_BITS_PER_FRACTIONAL_PART;
98*b843c749SSergey Zigachev
99*b843c749SSergey Zigachev return res;
100*b843c749SSergey Zigachev }
101*b843c749SSergey Zigachev
102*b843c749SSergey Zigachev /*
103*b843c749SSergey Zigachev * @brief
104*b843c749SSergey Zigachev * Unary operators
105*b843c749SSergey Zigachev */
106*b843c749SSergey Zigachev
107*b843c749SSergey Zigachev /*
108*b843c749SSergey Zigachev * @brief
109*b843c749SSergey Zigachev * result = -arg
110*b843c749SSergey Zigachev */
dc_fixpt_neg(struct fixed31_32 arg)111*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_neg(struct fixed31_32 arg)
112*b843c749SSergey Zigachev {
113*b843c749SSergey Zigachev struct fixed31_32 res;
114*b843c749SSergey Zigachev
115*b843c749SSergey Zigachev res.value = -arg.value;
116*b843c749SSergey Zigachev
117*b843c749SSergey Zigachev return res;
118*b843c749SSergey Zigachev }
119*b843c749SSergey Zigachev
120*b843c749SSergey Zigachev /*
121*b843c749SSergey Zigachev * @brief
122*b843c749SSergey Zigachev * result = abs(arg) := (arg >= 0) ? arg : -arg
123*b843c749SSergey Zigachev */
dc_fixpt_abs(struct fixed31_32 arg)124*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_abs(struct fixed31_32 arg)
125*b843c749SSergey Zigachev {
126*b843c749SSergey Zigachev if (arg.value < 0)
127*b843c749SSergey Zigachev return dc_fixpt_neg(arg);
128*b843c749SSergey Zigachev else
129*b843c749SSergey Zigachev return arg;
130*b843c749SSergey Zigachev }
131*b843c749SSergey Zigachev
132*b843c749SSergey Zigachev /*
133*b843c749SSergey Zigachev * @brief
134*b843c749SSergey Zigachev * Binary relational operators
135*b843c749SSergey Zigachev */
136*b843c749SSergey Zigachev
137*b843c749SSergey Zigachev /*
138*b843c749SSergey Zigachev * @brief
139*b843c749SSergey Zigachev * result = arg1 < arg2
140*b843c749SSergey Zigachev */
dc_fixpt_lt(struct fixed31_32 arg1,struct fixed31_32 arg2)141*b843c749SSergey Zigachev static inline bool dc_fixpt_lt(struct fixed31_32 arg1, struct fixed31_32 arg2)
142*b843c749SSergey Zigachev {
143*b843c749SSergey Zigachev return arg1.value < arg2.value;
144*b843c749SSergey Zigachev }
145*b843c749SSergey Zigachev
146*b843c749SSergey Zigachev /*
147*b843c749SSergey Zigachev * @brief
148*b843c749SSergey Zigachev * result = arg1 <= arg2
149*b843c749SSergey Zigachev */
dc_fixpt_le(struct fixed31_32 arg1,struct fixed31_32 arg2)150*b843c749SSergey Zigachev static inline bool dc_fixpt_le(struct fixed31_32 arg1, struct fixed31_32 arg2)
151*b843c749SSergey Zigachev {
152*b843c749SSergey Zigachev return arg1.value <= arg2.value;
153*b843c749SSergey Zigachev }
154*b843c749SSergey Zigachev
155*b843c749SSergey Zigachev /*
156*b843c749SSergey Zigachev * @brief
157*b843c749SSergey Zigachev * result = arg1 == arg2
158*b843c749SSergey Zigachev */
dc_fixpt_eq(struct fixed31_32 arg1,struct fixed31_32 arg2)159*b843c749SSergey Zigachev static inline bool dc_fixpt_eq(struct fixed31_32 arg1, struct fixed31_32 arg2)
160*b843c749SSergey Zigachev {
161*b843c749SSergey Zigachev return arg1.value == arg2.value;
162*b843c749SSergey Zigachev }
163*b843c749SSergey Zigachev
164*b843c749SSergey Zigachev /*
165*b843c749SSergey Zigachev * @brief
166*b843c749SSergey Zigachev * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
167*b843c749SSergey Zigachev */
dc_fixpt_min(struct fixed31_32 arg1,struct fixed31_32 arg2)168*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_min(struct fixed31_32 arg1, struct fixed31_32 arg2)
169*b843c749SSergey Zigachev {
170*b843c749SSergey Zigachev if (arg1.value <= arg2.value)
171*b843c749SSergey Zigachev return arg1;
172*b843c749SSergey Zigachev else
173*b843c749SSergey Zigachev return arg2;
174*b843c749SSergey Zigachev }
175*b843c749SSergey Zigachev
176*b843c749SSergey Zigachev /*
177*b843c749SSergey Zigachev * @brief
178*b843c749SSergey Zigachev * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
179*b843c749SSergey Zigachev */
dc_fixpt_max(struct fixed31_32 arg1,struct fixed31_32 arg2)180*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_max(struct fixed31_32 arg1, struct fixed31_32 arg2)
181*b843c749SSergey Zigachev {
182*b843c749SSergey Zigachev if (arg1.value <= arg2.value)
183*b843c749SSergey Zigachev return arg2;
184*b843c749SSergey Zigachev else
185*b843c749SSergey Zigachev return arg1;
186*b843c749SSergey Zigachev }
187*b843c749SSergey Zigachev
188*b843c749SSergey Zigachev /*
189*b843c749SSergey Zigachev * @brief
190*b843c749SSergey Zigachev * | min_value, when arg <= min_value
191*b843c749SSergey Zigachev * result = | arg, when min_value < arg < max_value
192*b843c749SSergey Zigachev * | max_value, when arg >= max_value
193*b843c749SSergey Zigachev */
dc_fixpt_clamp(struct fixed31_32 arg,struct fixed31_32 min_value,struct fixed31_32 max_value)194*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_clamp(
195*b843c749SSergey Zigachev struct fixed31_32 arg,
196*b843c749SSergey Zigachev struct fixed31_32 min_value,
197*b843c749SSergey Zigachev struct fixed31_32 max_value)
198*b843c749SSergey Zigachev {
199*b843c749SSergey Zigachev if (dc_fixpt_le(arg, min_value))
200*b843c749SSergey Zigachev return min_value;
201*b843c749SSergey Zigachev else if (dc_fixpt_le(max_value, arg))
202*b843c749SSergey Zigachev return max_value;
203*b843c749SSergey Zigachev else
204*b843c749SSergey Zigachev return arg;
205*b843c749SSergey Zigachev }
206*b843c749SSergey Zigachev
207*b843c749SSergey Zigachev /*
208*b843c749SSergey Zigachev * @brief
209*b843c749SSergey Zigachev * Binary shift operators
210*b843c749SSergey Zigachev */
211*b843c749SSergey Zigachev
212*b843c749SSergey Zigachev /*
213*b843c749SSergey Zigachev * @brief
214*b843c749SSergey Zigachev * result = arg << shift
215*b843c749SSergey Zigachev */
dc_fixpt_shl(struct fixed31_32 arg,unsigned char shift)216*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_shl(struct fixed31_32 arg, unsigned char shift)
217*b843c749SSergey Zigachev {
218*b843c749SSergey Zigachev ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
219*b843c749SSergey Zigachev ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift))));
220*b843c749SSergey Zigachev
221*b843c749SSergey Zigachev arg.value = arg.value << shift;
222*b843c749SSergey Zigachev
223*b843c749SSergey Zigachev return arg;
224*b843c749SSergey Zigachev }
225*b843c749SSergey Zigachev
226*b843c749SSergey Zigachev /*
227*b843c749SSergey Zigachev * @brief
228*b843c749SSergey Zigachev * result = arg >> shift
229*b843c749SSergey Zigachev */
dc_fixpt_shr(struct fixed31_32 arg,unsigned char shift)230*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_shr(struct fixed31_32 arg, unsigned char shift)
231*b843c749SSergey Zigachev {
232*b843c749SSergey Zigachev bool negative = arg.value < 0;
233*b843c749SSergey Zigachev
234*b843c749SSergey Zigachev if (negative)
235*b843c749SSergey Zigachev arg.value = -arg.value;
236*b843c749SSergey Zigachev arg.value = arg.value >> shift;
237*b843c749SSergey Zigachev if (negative)
238*b843c749SSergey Zigachev arg.value = -arg.value;
239*b843c749SSergey Zigachev return arg;
240*b843c749SSergey Zigachev }
241*b843c749SSergey Zigachev
242*b843c749SSergey Zigachev /*
243*b843c749SSergey Zigachev * @brief
244*b843c749SSergey Zigachev * Binary additive operators
245*b843c749SSergey Zigachev */
246*b843c749SSergey Zigachev
247*b843c749SSergey Zigachev /*
248*b843c749SSergey Zigachev * @brief
249*b843c749SSergey Zigachev * result = arg1 + arg2
250*b843c749SSergey Zigachev */
dc_fixpt_add(struct fixed31_32 arg1,struct fixed31_32 arg2)251*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_add(struct fixed31_32 arg1, struct fixed31_32 arg2)
252*b843c749SSergey Zigachev {
253*b843c749SSergey Zigachev struct fixed31_32 res;
254*b843c749SSergey Zigachev
255*b843c749SSergey Zigachev ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
256*b843c749SSergey Zigachev ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
257*b843c749SSergey Zigachev
258*b843c749SSergey Zigachev res.value = arg1.value + arg2.value;
259*b843c749SSergey Zigachev
260*b843c749SSergey Zigachev return res;
261*b843c749SSergey Zigachev }
262*b843c749SSergey Zigachev
263*b843c749SSergey Zigachev /*
264*b843c749SSergey Zigachev * @brief
265*b843c749SSergey Zigachev * result = arg1 + arg2
266*b843c749SSergey Zigachev */
dc_fixpt_add_int(struct fixed31_32 arg1,int arg2)267*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_add_int(struct fixed31_32 arg1, int arg2)
268*b843c749SSergey Zigachev {
269*b843c749SSergey Zigachev return dc_fixpt_add(arg1, dc_fixpt_from_int(arg2));
270*b843c749SSergey Zigachev }
271*b843c749SSergey Zigachev
272*b843c749SSergey Zigachev /*
273*b843c749SSergey Zigachev * @brief
274*b843c749SSergey Zigachev * result = arg1 - arg2
275*b843c749SSergey Zigachev */
dc_fixpt_sub(struct fixed31_32 arg1,struct fixed31_32 arg2)276*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_sub(struct fixed31_32 arg1, struct fixed31_32 arg2)
277*b843c749SSergey Zigachev {
278*b843c749SSergey Zigachev struct fixed31_32 res;
279*b843c749SSergey Zigachev
280*b843c749SSergey Zigachev ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
281*b843c749SSergey Zigachev ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
282*b843c749SSergey Zigachev
283*b843c749SSergey Zigachev res.value = arg1.value - arg2.value;
284*b843c749SSergey Zigachev
285*b843c749SSergey Zigachev return res;
286*b843c749SSergey Zigachev }
287*b843c749SSergey Zigachev
288*b843c749SSergey Zigachev /*
289*b843c749SSergey Zigachev * @brief
290*b843c749SSergey Zigachev * result = arg1 - arg2
291*b843c749SSergey Zigachev */
dc_fixpt_sub_int(struct fixed31_32 arg1,int arg2)292*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_sub_int(struct fixed31_32 arg1, int arg2)
293*b843c749SSergey Zigachev {
294*b843c749SSergey Zigachev return dc_fixpt_sub(arg1, dc_fixpt_from_int(arg2));
295*b843c749SSergey Zigachev }
296*b843c749SSergey Zigachev
297*b843c749SSergey Zigachev
298*b843c749SSergey Zigachev /*
299*b843c749SSergey Zigachev * @brief
300*b843c749SSergey Zigachev * Binary multiplicative operators
301*b843c749SSergey Zigachev */
302*b843c749SSergey Zigachev
303*b843c749SSergey Zigachev /*
304*b843c749SSergey Zigachev * @brief
305*b843c749SSergey Zigachev * result = arg1 * arg2
306*b843c749SSergey Zigachev */
307*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);
308*b843c749SSergey Zigachev
309*b843c749SSergey Zigachev
310*b843c749SSergey Zigachev /*
311*b843c749SSergey Zigachev * @brief
312*b843c749SSergey Zigachev * result = arg1 * arg2
313*b843c749SSergey Zigachev */
dc_fixpt_mul_int(struct fixed31_32 arg1,int arg2)314*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_mul_int(struct fixed31_32 arg1, int arg2)
315*b843c749SSergey Zigachev {
316*b843c749SSergey Zigachev return dc_fixpt_mul(arg1, dc_fixpt_from_int(arg2));
317*b843c749SSergey Zigachev }
318*b843c749SSergey Zigachev
319*b843c749SSergey Zigachev /*
320*b843c749SSergey Zigachev * @brief
321*b843c749SSergey Zigachev * result = square(arg) := arg * arg
322*b843c749SSergey Zigachev */
323*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg);
324*b843c749SSergey Zigachev
325*b843c749SSergey Zigachev /*
326*b843c749SSergey Zigachev * @brief
327*b843c749SSergey Zigachev * result = arg1 / arg2
328*b843c749SSergey Zigachev */
dc_fixpt_div_int(struct fixed31_32 arg1,long long arg2)329*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_div_int(struct fixed31_32 arg1, long long arg2)
330*b843c749SSergey Zigachev {
331*b843c749SSergey Zigachev return dc_fixpt_from_fraction(arg1.value, dc_fixpt_from_int(arg2).value);
332*b843c749SSergey Zigachev }
333*b843c749SSergey Zigachev
334*b843c749SSergey Zigachev /*
335*b843c749SSergey Zigachev * @brief
336*b843c749SSergey Zigachev * result = arg1 / arg2
337*b843c749SSergey Zigachev */
dc_fixpt_div(struct fixed31_32 arg1,struct fixed31_32 arg2)338*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_div(struct fixed31_32 arg1, struct fixed31_32 arg2)
339*b843c749SSergey Zigachev {
340*b843c749SSergey Zigachev return dc_fixpt_from_fraction(arg1.value, arg2.value);
341*b843c749SSergey Zigachev }
342*b843c749SSergey Zigachev
343*b843c749SSergey Zigachev /*
344*b843c749SSergey Zigachev * @brief
345*b843c749SSergey Zigachev * Reciprocal function
346*b843c749SSergey Zigachev */
347*b843c749SSergey Zigachev
348*b843c749SSergey Zigachev /*
349*b843c749SSergey Zigachev * @brief
350*b843c749SSergey Zigachev * result = reciprocal(arg) := 1 / arg
351*b843c749SSergey Zigachev *
352*b843c749SSergey Zigachev * @note
353*b843c749SSergey Zigachev * No special actions taken in case argument is zero.
354*b843c749SSergey Zigachev */
355*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_recip(struct fixed31_32 arg);
356*b843c749SSergey Zigachev
357*b843c749SSergey Zigachev /*
358*b843c749SSergey Zigachev * @brief
359*b843c749SSergey Zigachev * Trigonometric functions
360*b843c749SSergey Zigachev */
361*b843c749SSergey Zigachev
362*b843c749SSergey Zigachev /*
363*b843c749SSergey Zigachev * @brief
364*b843c749SSergey Zigachev * result = sinc(arg) := sin(arg) / arg
365*b843c749SSergey Zigachev *
366*b843c749SSergey Zigachev * @note
367*b843c749SSergey Zigachev * Argument specified in radians,
368*b843c749SSergey Zigachev * internally it's normalized to [-2pi...2pi] range.
369*b843c749SSergey Zigachev */
370*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_sinc(struct fixed31_32 arg);
371*b843c749SSergey Zigachev
372*b843c749SSergey Zigachev /*
373*b843c749SSergey Zigachev * @brief
374*b843c749SSergey Zigachev * result = sin(arg)
375*b843c749SSergey Zigachev *
376*b843c749SSergey Zigachev * @note
377*b843c749SSergey Zigachev * Argument specified in radians,
378*b843c749SSergey Zigachev * internally it's normalized to [-2pi...2pi] range.
379*b843c749SSergey Zigachev */
380*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_sin(struct fixed31_32 arg);
381*b843c749SSergey Zigachev
382*b843c749SSergey Zigachev /*
383*b843c749SSergey Zigachev * @brief
384*b843c749SSergey Zigachev * result = cos(arg)
385*b843c749SSergey Zigachev *
386*b843c749SSergey Zigachev * @note
387*b843c749SSergey Zigachev * Argument specified in radians
388*b843c749SSergey Zigachev * and should be in [-2pi...2pi] range -
389*b843c749SSergey Zigachev * passing arguments outside that range
390*b843c749SSergey Zigachev * will cause incorrect result!
391*b843c749SSergey Zigachev */
392*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_cos(struct fixed31_32 arg);
393*b843c749SSergey Zigachev
394*b843c749SSergey Zigachev /*
395*b843c749SSergey Zigachev * @brief
396*b843c749SSergey Zigachev * Transcendent functions
397*b843c749SSergey Zigachev */
398*b843c749SSergey Zigachev
399*b843c749SSergey Zigachev /*
400*b843c749SSergey Zigachev * @brief
401*b843c749SSergey Zigachev * result = exp(arg)
402*b843c749SSergey Zigachev *
403*b843c749SSergey Zigachev * @note
404*b843c749SSergey Zigachev * Currently, function is verified for abs(arg) <= 1.
405*b843c749SSergey Zigachev */
406*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_exp(struct fixed31_32 arg);
407*b843c749SSergey Zigachev
408*b843c749SSergey Zigachev /*
409*b843c749SSergey Zigachev * @brief
410*b843c749SSergey Zigachev * result = log(arg)
411*b843c749SSergey Zigachev *
412*b843c749SSergey Zigachev * @note
413*b843c749SSergey Zigachev * Currently, abs(arg) should be less than 1.
414*b843c749SSergey Zigachev * No normalization is done.
415*b843c749SSergey Zigachev * Currently, no special actions taken
416*b843c749SSergey Zigachev * in case of invalid argument(s). Take care!
417*b843c749SSergey Zigachev */
418*b843c749SSergey Zigachev struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg);
419*b843c749SSergey Zigachev
420*b843c749SSergey Zigachev /*
421*b843c749SSergey Zigachev * @brief
422*b843c749SSergey Zigachev * Power function
423*b843c749SSergey Zigachev */
424*b843c749SSergey Zigachev
425*b843c749SSergey Zigachev /*
426*b843c749SSergey Zigachev * @brief
427*b843c749SSergey Zigachev * result = pow(arg1, arg2)
428*b843c749SSergey Zigachev *
429*b843c749SSergey Zigachev * @note
430*b843c749SSergey Zigachev * Currently, abs(arg1) should be less than 1. Take care!
431*b843c749SSergey Zigachev */
dc_fixpt_pow(struct fixed31_32 arg1,struct fixed31_32 arg2)432*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)
433*b843c749SSergey Zigachev {
434*b843c749SSergey Zigachev if (arg1.value == 0)
435*b843c749SSergey Zigachev return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero;
436*b843c749SSergey Zigachev
437*b843c749SSergey Zigachev return dc_fixpt_exp(
438*b843c749SSergey Zigachev dc_fixpt_mul(
439*b843c749SSergey Zigachev dc_fixpt_log(arg1),
440*b843c749SSergey Zigachev arg2));
441*b843c749SSergey Zigachev }
442*b843c749SSergey Zigachev
443*b843c749SSergey Zigachev /*
444*b843c749SSergey Zigachev * @brief
445*b843c749SSergey Zigachev * Rounding functions
446*b843c749SSergey Zigachev */
447*b843c749SSergey Zigachev
448*b843c749SSergey Zigachev /*
449*b843c749SSergey Zigachev * @brief
450*b843c749SSergey Zigachev * result = floor(arg) := greatest integer lower than or equal to arg
451*b843c749SSergey Zigachev */
dc_fixpt_floor(struct fixed31_32 arg)452*b843c749SSergey Zigachev static inline int dc_fixpt_floor(struct fixed31_32 arg)
453*b843c749SSergey Zigachev {
454*b843c749SSergey Zigachev unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
455*b843c749SSergey Zigachev
456*b843c749SSergey Zigachev if (arg.value >= 0)
457*b843c749SSergey Zigachev return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
458*b843c749SSergey Zigachev else
459*b843c749SSergey Zigachev return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
460*b843c749SSergey Zigachev }
461*b843c749SSergey Zigachev
462*b843c749SSergey Zigachev /*
463*b843c749SSergey Zigachev * @brief
464*b843c749SSergey Zigachev * result = round(arg) := integer nearest to arg
465*b843c749SSergey Zigachev */
dc_fixpt_round(struct fixed31_32 arg)466*b843c749SSergey Zigachev static inline int dc_fixpt_round(struct fixed31_32 arg)
467*b843c749SSergey Zigachev {
468*b843c749SSergey Zigachev unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
469*b843c749SSergey Zigachev
470*b843c749SSergey Zigachev const long long summand = dc_fixpt_half.value;
471*b843c749SSergey Zigachev
472*b843c749SSergey Zigachev ASSERT(LLONG_MAX - (long long)arg_value >= summand);
473*b843c749SSergey Zigachev
474*b843c749SSergey Zigachev arg_value += summand;
475*b843c749SSergey Zigachev
476*b843c749SSergey Zigachev if (arg.value >= 0)
477*b843c749SSergey Zigachev return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
478*b843c749SSergey Zigachev else
479*b843c749SSergey Zigachev return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
480*b843c749SSergey Zigachev }
481*b843c749SSergey Zigachev
482*b843c749SSergey Zigachev /*
483*b843c749SSergey Zigachev * @brief
484*b843c749SSergey Zigachev * result = ceil(arg) := lowest integer greater than or equal to arg
485*b843c749SSergey Zigachev */
dc_fixpt_ceil(struct fixed31_32 arg)486*b843c749SSergey Zigachev static inline int dc_fixpt_ceil(struct fixed31_32 arg)
487*b843c749SSergey Zigachev {
488*b843c749SSergey Zigachev unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
489*b843c749SSergey Zigachev
490*b843c749SSergey Zigachev const long long summand = dc_fixpt_one.value -
491*b843c749SSergey Zigachev dc_fixpt_epsilon.value;
492*b843c749SSergey Zigachev
493*b843c749SSergey Zigachev ASSERT(LLONG_MAX - (long long)arg_value >= summand);
494*b843c749SSergey Zigachev
495*b843c749SSergey Zigachev arg_value += summand;
496*b843c749SSergey Zigachev
497*b843c749SSergey Zigachev if (arg.value >= 0)
498*b843c749SSergey Zigachev return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
499*b843c749SSergey Zigachev else
500*b843c749SSergey Zigachev return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
501*b843c749SSergey Zigachev }
502*b843c749SSergey Zigachev
503*b843c749SSergey Zigachev /* the following two function are used in scaler hw programming to convert fixed
504*b843c749SSergey Zigachev * point value to format 2 bits from integer part and 19 bits from fractional
505*b843c749SSergey Zigachev * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
506*b843c749SSergey Zigachev * fractional
507*b843c749SSergey Zigachev */
508*b843c749SSergey Zigachev
509*b843c749SSergey Zigachev unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);
510*b843c749SSergey Zigachev
511*b843c749SSergey Zigachev unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);
512*b843c749SSergey Zigachev
513*b843c749SSergey Zigachev unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);
514*b843c749SSergey Zigachev
515*b843c749SSergey Zigachev unsigned int dc_fixpt_clamp_u0d14(struct fixed31_32 arg);
516*b843c749SSergey Zigachev
517*b843c749SSergey Zigachev unsigned int dc_fixpt_clamp_u0d10(struct fixed31_32 arg);
518*b843c749SSergey Zigachev
519*b843c749SSergey Zigachev int dc_fixpt_s4d19(struct fixed31_32 arg);
520*b843c749SSergey Zigachev
dc_fixpt_truncate(struct fixed31_32 arg,unsigned int frac_bits)521*b843c749SSergey Zigachev static inline struct fixed31_32 dc_fixpt_truncate(struct fixed31_32 arg, unsigned int frac_bits)
522*b843c749SSergey Zigachev {
523*b843c749SSergey Zigachev bool negative = arg.value < 0;
524*b843c749SSergey Zigachev
525*b843c749SSergey Zigachev if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) {
526*b843c749SSergey Zigachev ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART);
527*b843c749SSergey Zigachev return arg;
528*b843c749SSergey Zigachev }
529*b843c749SSergey Zigachev
530*b843c749SSergey Zigachev if (negative)
531*b843c749SSergey Zigachev arg.value = -arg.value;
532*b843c749SSergey Zigachev arg.value &= (~0LL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
533*b843c749SSergey Zigachev if (negative)
534*b843c749SSergey Zigachev arg.value = -arg.value;
535*b843c749SSergey Zigachev return arg;
536*b843c749SSergey Zigachev }
537*b843c749SSergey Zigachev
538*b843c749SSergey Zigachev #endif
539