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