xref: /freebsd/sys/contrib/dev/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c (revision b4c3e9b5b09c829b4135aff738bd2893ed052377)
1*b4c3e9b5SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2*b4c3e9b5SBjoern A. Zeeb /*
3*b4c3e9b5SBjoern A. Zeeb  * Copyright (c) 2010 Broadcom Corporation
4*b4c3e9b5SBjoern A. Zeeb  */
5*b4c3e9b5SBjoern A. Zeeb 
6*b4c3e9b5SBjoern A. Zeeb #include "phy_qmath.h"
7*b4c3e9b5SBjoern A. Zeeb 
8*b4c3e9b5SBjoern A. Zeeb /*
9*b4c3e9b5SBjoern A. Zeeb  * Description: This function make 16 bit unsigned multiplication.
10*b4c3e9b5SBjoern A. Zeeb  * To fit the output into 16 bits the 32 bit multiplication result is right
11*b4c3e9b5SBjoern A. Zeeb  * shifted by 16 bits.
12*b4c3e9b5SBjoern A. Zeeb  */
qm_mulu16(u16 op1,u16 op2)13*b4c3e9b5SBjoern A. Zeeb u16 qm_mulu16(u16 op1, u16 op2)
14*b4c3e9b5SBjoern A. Zeeb {
15*b4c3e9b5SBjoern A. Zeeb 	return (u16) (((u32) op1 * (u32) op2) >> 16);
16*b4c3e9b5SBjoern A. Zeeb }
17*b4c3e9b5SBjoern A. Zeeb 
18*b4c3e9b5SBjoern A. Zeeb /*
19*b4c3e9b5SBjoern A. Zeeb  * Description: This function make 16 bit multiplication and return the result
20*b4c3e9b5SBjoern A. Zeeb  * in 16 bits. To fit the multiplication result into 16 bits the multiplication
21*b4c3e9b5SBjoern A. Zeeb  * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits
22*b4c3e9b5SBjoern A. Zeeb  * is done to remove the extra sign bit formed due to the multiplication.
23*b4c3e9b5SBjoern A. Zeeb  * When both the 16bit inputs are 0x8000 then the output is saturated to
24*b4c3e9b5SBjoern A. Zeeb  * 0x7fffffff.
25*b4c3e9b5SBjoern A. Zeeb  */
qm_muls16(s16 op1,s16 op2)26*b4c3e9b5SBjoern A. Zeeb s16 qm_muls16(s16 op1, s16 op2)
27*b4c3e9b5SBjoern A. Zeeb {
28*b4c3e9b5SBjoern A. Zeeb 	s32 result;
29*b4c3e9b5SBjoern A. Zeeb 	if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
30*b4c3e9b5SBjoern A. Zeeb 		result = 0x7fffffff;
31*b4c3e9b5SBjoern A. Zeeb 	else
32*b4c3e9b5SBjoern A. Zeeb 		result = ((s32) (op1) * (s32) (op2));
33*b4c3e9b5SBjoern A. Zeeb 
34*b4c3e9b5SBjoern A. Zeeb 	return (s16) (result >> 15);
35*b4c3e9b5SBjoern A. Zeeb }
36*b4c3e9b5SBjoern A. Zeeb 
37*b4c3e9b5SBjoern A. Zeeb /*
38*b4c3e9b5SBjoern A. Zeeb  * Description: This function add two 32 bit numbers and return the 32bit
39*b4c3e9b5SBjoern A. Zeeb  * result. If the result overflow 32 bits, the output will be saturated to
40*b4c3e9b5SBjoern A. Zeeb  * 32bits.
41*b4c3e9b5SBjoern A. Zeeb  */
qm_add32(s32 op1,s32 op2)42*b4c3e9b5SBjoern A. Zeeb s32 qm_add32(s32 op1, s32 op2)
43*b4c3e9b5SBjoern A. Zeeb {
44*b4c3e9b5SBjoern A. Zeeb 	s32 result;
45*b4c3e9b5SBjoern A. Zeeb 	result = op1 + op2;
46*b4c3e9b5SBjoern A. Zeeb 	if (op1 < 0 && op2 < 0 && result > 0)
47*b4c3e9b5SBjoern A. Zeeb 		result = 0x80000000;
48*b4c3e9b5SBjoern A. Zeeb 	else if (op1 > 0 && op2 > 0 && result < 0)
49*b4c3e9b5SBjoern A. Zeeb 		result = 0x7fffffff;
50*b4c3e9b5SBjoern A. Zeeb 
51*b4c3e9b5SBjoern A. Zeeb 	return result;
52*b4c3e9b5SBjoern A. Zeeb }
53*b4c3e9b5SBjoern A. Zeeb 
54*b4c3e9b5SBjoern A. Zeeb /*
55*b4c3e9b5SBjoern A. Zeeb  * Description: This function add two 16 bit numbers and return the 16bit
56*b4c3e9b5SBjoern A. Zeeb  * result. If the result overflow 16 bits, the output will be saturated to
57*b4c3e9b5SBjoern A. Zeeb  * 16bits.
58*b4c3e9b5SBjoern A. Zeeb  */
qm_add16(s16 op1,s16 op2)59*b4c3e9b5SBjoern A. Zeeb s16 qm_add16(s16 op1, s16 op2)
60*b4c3e9b5SBjoern A. Zeeb {
61*b4c3e9b5SBjoern A. Zeeb 	s16 result;
62*b4c3e9b5SBjoern A. Zeeb 	s32 temp = (s32) op1 + (s32) op2;
63*b4c3e9b5SBjoern A. Zeeb 	if (temp > (s32) 0x7fff)
64*b4c3e9b5SBjoern A. Zeeb 		result = (s16) 0x7fff;
65*b4c3e9b5SBjoern A. Zeeb 	else if (temp < (s32) 0xffff8000)
66*b4c3e9b5SBjoern A. Zeeb 		result = (s16) 0xffff8000;
67*b4c3e9b5SBjoern A. Zeeb 	else
68*b4c3e9b5SBjoern A. Zeeb 		result = (s16) temp;
69*b4c3e9b5SBjoern A. Zeeb 
70*b4c3e9b5SBjoern A. Zeeb 	return result;
71*b4c3e9b5SBjoern A. Zeeb }
72*b4c3e9b5SBjoern A. Zeeb 
73*b4c3e9b5SBjoern A. Zeeb /*
74*b4c3e9b5SBjoern A. Zeeb  * Description: This function make 16 bit subtraction and return the 16bit
75*b4c3e9b5SBjoern A. Zeeb  * result. If the result overflow 16 bits, the output will be saturated to
76*b4c3e9b5SBjoern A. Zeeb  * 16bits.
77*b4c3e9b5SBjoern A. Zeeb  */
qm_sub16(s16 op1,s16 op2)78*b4c3e9b5SBjoern A. Zeeb s16 qm_sub16(s16 op1, s16 op2)
79*b4c3e9b5SBjoern A. Zeeb {
80*b4c3e9b5SBjoern A. Zeeb 	s16 result;
81*b4c3e9b5SBjoern A. Zeeb 	s32 temp = (s32) op1 - (s32) op2;
82*b4c3e9b5SBjoern A. Zeeb 	if (temp > (s32) 0x7fff)
83*b4c3e9b5SBjoern A. Zeeb 		result = (s16) 0x7fff;
84*b4c3e9b5SBjoern A. Zeeb 	else if (temp < (s32) 0xffff8000)
85*b4c3e9b5SBjoern A. Zeeb 		result = (s16) 0xffff8000;
86*b4c3e9b5SBjoern A. Zeeb 	else
87*b4c3e9b5SBjoern A. Zeeb 		result = (s16) temp;
88*b4c3e9b5SBjoern A. Zeeb 
89*b4c3e9b5SBjoern A. Zeeb 	return result;
90*b4c3e9b5SBjoern A. Zeeb }
91*b4c3e9b5SBjoern A. Zeeb 
92*b4c3e9b5SBjoern A. Zeeb /*
93*b4c3e9b5SBjoern A. Zeeb  * Description: This function make a 32 bit saturated left shift when the
94*b4c3e9b5SBjoern A. Zeeb  * specified shift is +ve. This function will make a 32 bit right shift when
95*b4c3e9b5SBjoern A. Zeeb  * the specified shift is -ve. This function return the result after shifting
96*b4c3e9b5SBjoern A. Zeeb  * operation.
97*b4c3e9b5SBjoern A. Zeeb  */
qm_shl32(s32 op,int shift)98*b4c3e9b5SBjoern A. Zeeb s32 qm_shl32(s32 op, int shift)
99*b4c3e9b5SBjoern A. Zeeb {
100*b4c3e9b5SBjoern A. Zeeb 	int i;
101*b4c3e9b5SBjoern A. Zeeb 	s32 result;
102*b4c3e9b5SBjoern A. Zeeb 	result = op;
103*b4c3e9b5SBjoern A. Zeeb 	if (shift > 31)
104*b4c3e9b5SBjoern A. Zeeb 		shift = 31;
105*b4c3e9b5SBjoern A. Zeeb 	else if (shift < -31)
106*b4c3e9b5SBjoern A. Zeeb 		shift = -31;
107*b4c3e9b5SBjoern A. Zeeb 	if (shift >= 0) {
108*b4c3e9b5SBjoern A. Zeeb 		for (i = 0; i < shift; i++)
109*b4c3e9b5SBjoern A. Zeeb 			result = qm_add32(result, result);
110*b4c3e9b5SBjoern A. Zeeb 	} else {
111*b4c3e9b5SBjoern A. Zeeb 		result = result >> (-shift);
112*b4c3e9b5SBjoern A. Zeeb 	}
113*b4c3e9b5SBjoern A. Zeeb 
114*b4c3e9b5SBjoern A. Zeeb 	return result;
115*b4c3e9b5SBjoern A. Zeeb }
116*b4c3e9b5SBjoern A. Zeeb 
117*b4c3e9b5SBjoern A. Zeeb /*
118*b4c3e9b5SBjoern A. Zeeb  * Description: This function make a 16 bit saturated left shift when the
119*b4c3e9b5SBjoern A. Zeeb  * specified shift is +ve. This function will make a 16 bit right shift when
120*b4c3e9b5SBjoern A. Zeeb  * the specified shift is -ve. This function return the result after shifting
121*b4c3e9b5SBjoern A. Zeeb  * operation.
122*b4c3e9b5SBjoern A. Zeeb  */
qm_shl16(s16 op,int shift)123*b4c3e9b5SBjoern A. Zeeb s16 qm_shl16(s16 op, int shift)
124*b4c3e9b5SBjoern A. Zeeb {
125*b4c3e9b5SBjoern A. Zeeb 	int i;
126*b4c3e9b5SBjoern A. Zeeb 	s16 result;
127*b4c3e9b5SBjoern A. Zeeb 	result = op;
128*b4c3e9b5SBjoern A. Zeeb 	if (shift > 15)
129*b4c3e9b5SBjoern A. Zeeb 		shift = 15;
130*b4c3e9b5SBjoern A. Zeeb 	else if (shift < -15)
131*b4c3e9b5SBjoern A. Zeeb 		shift = -15;
132*b4c3e9b5SBjoern A. Zeeb 	if (shift > 0) {
133*b4c3e9b5SBjoern A. Zeeb 		for (i = 0; i < shift; i++)
134*b4c3e9b5SBjoern A. Zeeb 			result = qm_add16(result, result);
135*b4c3e9b5SBjoern A. Zeeb 	} else {
136*b4c3e9b5SBjoern A. Zeeb 		result = result >> (-shift);
137*b4c3e9b5SBjoern A. Zeeb 	}
138*b4c3e9b5SBjoern A. Zeeb 
139*b4c3e9b5SBjoern A. Zeeb 	return result;
140*b4c3e9b5SBjoern A. Zeeb }
141*b4c3e9b5SBjoern A. Zeeb 
142*b4c3e9b5SBjoern A. Zeeb /*
143*b4c3e9b5SBjoern A. Zeeb  * Description: This function make a 16 bit right shift when shift is +ve.
144*b4c3e9b5SBjoern A. Zeeb  * This function make a 16 bit saturated left shift when shift is -ve. This
145*b4c3e9b5SBjoern A. Zeeb  * function return the result of the shift operation.
146*b4c3e9b5SBjoern A. Zeeb  */
qm_shr16(s16 op,int shift)147*b4c3e9b5SBjoern A. Zeeb s16 qm_shr16(s16 op, int shift)
148*b4c3e9b5SBjoern A. Zeeb {
149*b4c3e9b5SBjoern A. Zeeb 	return qm_shl16(op, -shift);
150*b4c3e9b5SBjoern A. Zeeb }
151*b4c3e9b5SBjoern A. Zeeb 
152*b4c3e9b5SBjoern A. Zeeb /*
153*b4c3e9b5SBjoern A. Zeeb  * Description: This function return the number of redundant sign bits in a
154*b4c3e9b5SBjoern A. Zeeb  * 32 bit number. Example: qm_norm32(0x00000080) = 23
155*b4c3e9b5SBjoern A. Zeeb  */
qm_norm32(s32 op)156*b4c3e9b5SBjoern A. Zeeb s16 qm_norm32(s32 op)
157*b4c3e9b5SBjoern A. Zeeb {
158*b4c3e9b5SBjoern A. Zeeb 	u16 u16extraSignBits;
159*b4c3e9b5SBjoern A. Zeeb 	if (op == 0) {
160*b4c3e9b5SBjoern A. Zeeb 		return 31;
161*b4c3e9b5SBjoern A. Zeeb 	} else {
162*b4c3e9b5SBjoern A. Zeeb 		u16extraSignBits = 0;
163*b4c3e9b5SBjoern A. Zeeb 		while ((op >> 31) == (op >> 30)) {
164*b4c3e9b5SBjoern A. Zeeb 			u16extraSignBits++;
165*b4c3e9b5SBjoern A. Zeeb 			op = op << 1;
166*b4c3e9b5SBjoern A. Zeeb 		}
167*b4c3e9b5SBjoern A. Zeeb 	}
168*b4c3e9b5SBjoern A. Zeeb 	return u16extraSignBits;
169*b4c3e9b5SBjoern A. Zeeb }
170*b4c3e9b5SBjoern A. Zeeb 
171*b4c3e9b5SBjoern A. Zeeb /* This table is log2(1+(i/32)) where i=[0:1:32], in q.15 format */
172*b4c3e9b5SBjoern A. Zeeb static const s16 log_table[] = {
173*b4c3e9b5SBjoern A. Zeeb 	0,
174*b4c3e9b5SBjoern A. Zeeb 	1455,
175*b4c3e9b5SBjoern A. Zeeb 	2866,
176*b4c3e9b5SBjoern A. Zeeb 	4236,
177*b4c3e9b5SBjoern A. Zeeb 	5568,
178*b4c3e9b5SBjoern A. Zeeb 	6863,
179*b4c3e9b5SBjoern A. Zeeb 	8124,
180*b4c3e9b5SBjoern A. Zeeb 	9352,
181*b4c3e9b5SBjoern A. Zeeb 	10549,
182*b4c3e9b5SBjoern A. Zeeb 	11716,
183*b4c3e9b5SBjoern A. Zeeb 	12855,
184*b4c3e9b5SBjoern A. Zeeb 	13968,
185*b4c3e9b5SBjoern A. Zeeb 	15055,
186*b4c3e9b5SBjoern A. Zeeb 	16117,
187*b4c3e9b5SBjoern A. Zeeb 	17156,
188*b4c3e9b5SBjoern A. Zeeb 	18173,
189*b4c3e9b5SBjoern A. Zeeb 	19168,
190*b4c3e9b5SBjoern A. Zeeb 	20143,
191*b4c3e9b5SBjoern A. Zeeb 	21098,
192*b4c3e9b5SBjoern A. Zeeb 	22034,
193*b4c3e9b5SBjoern A. Zeeb 	22952,
194*b4c3e9b5SBjoern A. Zeeb 	23852,
195*b4c3e9b5SBjoern A. Zeeb 	24736,
196*b4c3e9b5SBjoern A. Zeeb 	25604,
197*b4c3e9b5SBjoern A. Zeeb 	26455,
198*b4c3e9b5SBjoern A. Zeeb 	27292,
199*b4c3e9b5SBjoern A. Zeeb 	28114,
200*b4c3e9b5SBjoern A. Zeeb 	28922,
201*b4c3e9b5SBjoern A. Zeeb 	29717,
202*b4c3e9b5SBjoern A. Zeeb 	30498,
203*b4c3e9b5SBjoern A. Zeeb 	31267,
204*b4c3e9b5SBjoern A. Zeeb 	32024,
205*b4c3e9b5SBjoern A. Zeeb 	32767
206*b4c3e9b5SBjoern A. Zeeb };
207*b4c3e9b5SBjoern A. Zeeb 
208*b4c3e9b5SBjoern A. Zeeb #define LOG_TABLE_SIZE 32       /* log_table size */
209*b4c3e9b5SBjoern A. Zeeb #define LOG2_LOG_TABLE_SIZE 5   /* log2(log_table size) */
210*b4c3e9b5SBjoern A. Zeeb #define Q_LOG_TABLE 15          /* qformat of log_table */
211*b4c3e9b5SBjoern A. Zeeb #define LOG10_2         19728   /* log10(2) in q.16 */
212*b4c3e9b5SBjoern A. Zeeb 
213*b4c3e9b5SBjoern A. Zeeb /*
214*b4c3e9b5SBjoern A. Zeeb  * Description:
215*b4c3e9b5SBjoern A. Zeeb  * This routine takes the input number N and its q format qN and compute
216*b4c3e9b5SBjoern A. Zeeb  * the log10(N). This routine first normalizes the input no N.	Then N is in
217*b4c3e9b5SBjoern A. Zeeb  * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1).
218*b4c3e9b5SBjoern A. Zeeb  * Then log2(mag * 2^x) = log2(mag) + x is computed. From that
219*b4c3e9b5SBjoern A. Zeeb  * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
220*b4c3e9b5SBjoern A. Zeeb  * This routine looks the log2 value in the table considering
221*b4c3e9b5SBjoern A. Zeeb  * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next
222*b4c3e9b5SBjoern A. Zeeb  * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used
223*b4c3e9b5SBjoern A. Zeeb  * for interpolation.
224*b4c3e9b5SBjoern A. Zeeb  * Inputs:
225*b4c3e9b5SBjoern A. Zeeb  * N - number to which log10 has to be found.
226*b4c3e9b5SBjoern A. Zeeb  * qN - q format of N
227*b4c3e9b5SBjoern A. Zeeb  * log10N - address where log10(N) will be written.
228*b4c3e9b5SBjoern A. Zeeb  * qLog10N - address where log10N qformat will be written.
229*b4c3e9b5SBjoern A. Zeeb  * Note/Problem:
230*b4c3e9b5SBjoern A. Zeeb  * For accurate results input should be in normalized or near normalized form.
231*b4c3e9b5SBjoern A. Zeeb  */
qm_log10(s32 N,s16 qN,s16 * log10N,s16 * qLog10N)232*b4c3e9b5SBjoern A. Zeeb void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
233*b4c3e9b5SBjoern A. Zeeb {
234*b4c3e9b5SBjoern A. Zeeb 	s16 s16norm, s16tableIndex, s16errorApproximation;
235*b4c3e9b5SBjoern A. Zeeb 	u16 u16offset;
236*b4c3e9b5SBjoern A. Zeeb 	s32 s32log;
237*b4c3e9b5SBjoern A. Zeeb 
238*b4c3e9b5SBjoern A. Zeeb 	/* normalize the N. */
239*b4c3e9b5SBjoern A. Zeeb 	s16norm = qm_norm32(N);
240*b4c3e9b5SBjoern A. Zeeb 	N = N << s16norm;
241*b4c3e9b5SBjoern A. Zeeb 
242*b4c3e9b5SBjoern A. Zeeb 	/* The qformat of N after normalization.
243*b4c3e9b5SBjoern A. Zeeb 	 * -30 is added to treat the no as between 1.0 to 2.0
244*b4c3e9b5SBjoern A. Zeeb 	 * i.e. after adding the -30 to the qformat the decimal point will be
245*b4c3e9b5SBjoern A. Zeeb 	 * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
246*b4c3e9b5SBjoern A. Zeeb 	 * at the right side of 30th bit.
247*b4c3e9b5SBjoern A. Zeeb 	 */
248*b4c3e9b5SBjoern A. Zeeb 	qN = qN + s16norm - 30;
249*b4c3e9b5SBjoern A. Zeeb 
250*b4c3e9b5SBjoern A. Zeeb 	/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the
251*b4c3e9b5SBjoern A. Zeeb 	 * MSB */
252*b4c3e9b5SBjoern A. Zeeb 	s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
253*b4c3e9b5SBjoern A. Zeeb 
254*b4c3e9b5SBjoern A. Zeeb 	/* remove the MSB. the MSB is always 1 after normalization. */
255*b4c3e9b5SBjoern A. Zeeb 	s16tableIndex =
256*b4c3e9b5SBjoern A. Zeeb 		s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
257*b4c3e9b5SBjoern A. Zeeb 
258*b4c3e9b5SBjoern A. Zeeb 	/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
259*b4c3e9b5SBjoern A. Zeeb 	N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
260*b4c3e9b5SBjoern A. Zeeb 
261*b4c3e9b5SBjoern A. Zeeb 	/* take the offset as the 16 MSBS after table index.
262*b4c3e9b5SBjoern A. Zeeb 	 */
263*b4c3e9b5SBjoern A. Zeeb 	u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
264*b4c3e9b5SBjoern A. Zeeb 
265*b4c3e9b5SBjoern A. Zeeb 	/* look the log value in the table. */
266*b4c3e9b5SBjoern A. Zeeb 	s32log = log_table[s16tableIndex];      /* q.15 format */
267*b4c3e9b5SBjoern A. Zeeb 
268*b4c3e9b5SBjoern A. Zeeb 	/* interpolate using the offset. q.15 format. */
269*b4c3e9b5SBjoern A. Zeeb 	s16errorApproximation = (s16) qm_mulu16(u16offset,
270*b4c3e9b5SBjoern A. Zeeb 				(u16) (log_table[s16tableIndex + 1] -
271*b4c3e9b5SBjoern A. Zeeb 				       log_table[s16tableIndex]));
272*b4c3e9b5SBjoern A. Zeeb 
273*b4c3e9b5SBjoern A. Zeeb 	 /* q.15 format */
274*b4c3e9b5SBjoern A. Zeeb 	s32log = qm_add16((s16) s32log, s16errorApproximation);
275*b4c3e9b5SBjoern A. Zeeb 
276*b4c3e9b5SBjoern A. Zeeb 	/* adjust for the qformat of the N as
277*b4c3e9b5SBjoern A. Zeeb 	 * log2(mag * 2^x) = log2(mag) + x
278*b4c3e9b5SBjoern A. Zeeb 	 */
279*b4c3e9b5SBjoern A. Zeeb 	s32log = qm_add32(s32log, ((s32) -qN) << 15);   /* q.15 format */
280*b4c3e9b5SBjoern A. Zeeb 
281*b4c3e9b5SBjoern A. Zeeb 	/* normalize the result. */
282*b4c3e9b5SBjoern A. Zeeb 	s16norm = qm_norm32(s32log);
283*b4c3e9b5SBjoern A. Zeeb 
284*b4c3e9b5SBjoern A. Zeeb 	/* bring all the important bits into lower 16 bits */
285*b4c3e9b5SBjoern A. Zeeb 	/* q.15+s16norm-16 format */
286*b4c3e9b5SBjoern A. Zeeb 	s32log = qm_shl32(s32log, s16norm - 16);
287*b4c3e9b5SBjoern A. Zeeb 
288*b4c3e9b5SBjoern A. Zeeb 	/* compute the log10(N) by multiplying log2(N) with log10(2).
289*b4c3e9b5SBjoern A. Zeeb 	 * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
290*b4c3e9b5SBjoern A. Zeeb 	 * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
291*b4c3e9b5SBjoern A. Zeeb 	 */
292*b4c3e9b5SBjoern A. Zeeb 	*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
293*b4c3e9b5SBjoern A. Zeeb 
294*b4c3e9b5SBjoern A. Zeeb 	/* write the q format of the result. */
295*b4c3e9b5SBjoern A. Zeeb 	*qLog10N = 15 + s16norm - 16 + 1;
296*b4c3e9b5SBjoern A. Zeeb 
297*b4c3e9b5SBjoern A. Zeeb 	return;
298*b4c3e9b5SBjoern A. Zeeb }
299