1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Copyright 2003-2010, VisualOn, Inc.
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **     http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard **
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ** limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*___________________________________________________________________________
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  This file contains mathematic operations in fixed point.                 |
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
21e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Isqrt()              : inverse square root (16 bits precision).          |
22e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Pow2()               : 2^x  (16 bits precision).                         |
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Log2()               : log2 (16 bits precision).                         |
24e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Dot_product()        : scalar product of <x[],y[]>                       |
25e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
26e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  These operations are not standard double precision operations.           |
27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  They are used where low complexity is important and the full 32 bits     |
28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  precision is not necessary. For example, the function Div_32() has a     |
29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  24 bits precision which is enough for our purposes.                      |
30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  In this file, the values use theses representations:                     |
32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Word32 L_32     : standard signed 32 bits format                         |
34e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Word16 hi, lo   : L_32 = hi<<16 + lo<<1  (DPF - Double Precision Format) |
35e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Word32 frac, Word16 exp : L_32 = frac << exp-31  (normalised format)     |
36e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Word16 int, frac        : L_32 = int.frac        (fractional format)     |
37e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|___________________________________________________________________________|
38e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*/
39e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "typedef.h"
40e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "basic_op.h"
41e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "math_op.h"
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*___________________________________________________________________________
44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   Function Name : Isqrt                                                   |
46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       Compute 1/sqrt(L_x).                                                |
48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       if L_x is negative or zero, result is 1 (7fffffff).                 |
49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|---------------------------------------------------------------------------|
50e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Algorithm:                                                               |
51e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   1- Normalization of L_x.                                                |
53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   2- call Isqrt_n(L_x, exponant)                                          |
54e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   3- L_y = L_x << exponant                                                |
55e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|___________________________________________________________________________|
56e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*/
57e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord32 Isqrt(                              /* (o) Q31 : output value (range: 0<=val<1)         */
585d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 L_x                            /* (i) Q0  : input value  (range: 0<=val<=7fffffff) */
595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
60e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 exp;
625d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_y;
635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp = norm_l(L_x);
645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x = (L_x << exp);                 /* L_x is normalized */
655d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp = (31 - exp);
665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Isqrt_n(&L_x, &exp);
675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_y = (L_x << exp);                 /* denormalization   */
685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (L_y);
69e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
70e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
71e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*___________________________________________________________________________
72e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   Function Name : Isqrt_n                                                 |
74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       Compute 1/sqrt(value).                                              |
76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       if value is negative or zero, result is 1 (frac=7fffffff, exp=0).   |
77e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|---------------------------------------------------------------------------|
78e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Algorithm:                                                               |
79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   The function 1/sqrt(value) is approximated by a table and linear        |
81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   interpolation.                                                          |
82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   1- If exponant is odd then shift fraction right once.                   |
84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   2- exponant = -((exponant-1)>>1)                                        |
85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |
86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   4- a = bit10-b24                                                        |
87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   5- i -=16                                                               |
88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2            |
89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|___________________________________________________________________________|
90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*/
91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 table_isqrt[49] =
92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
935d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214,
945d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155,
955d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539,
965d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674,
975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384
98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard};
99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid Isqrt_n(
1015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word32 * frac,                        /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
1025d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * exp                          /* (i/o)    : exponent (value = frac x 2^exponent) */
1035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
104e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 i, a, tmp;
1065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if (*frac <= (Word32) 0)
1085d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
1095d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        *exp = 0;
1105d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        *frac = 0x7fffffffL;
1115d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        return;
1125d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
1135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1145d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    if((*exp & 1) == 1)                       /*If exponant odd -> shift right */
1155d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        *frac = (*frac) >> 1;
1165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *exp = negate((*exp - 1) >> 1);
1185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *frac = (*frac >> 9);
1205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    i = extract_h(*frac);                  /* Extract b25-b31 */
1215d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *frac = (*frac >> 1);
1225d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    a = (Word16)(*frac);                  /* Extract b10-b24 */
1235d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    a = (Word16) (a & (Word16) 0x7fff);
1245d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    i -= 16;
1255d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *frac = L_deposit_h(table_isqrt[i]);   /* table[i] << 16         */
1265d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    tmp = vo_sub(table_isqrt[i], table_isqrt[i + 1]);      /* table[i] - table[i+1]) */
1275d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *frac = vo_L_msu(*frac, tmp, a);          /* frac -=  tmp*a*2       */
1285d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen
1295d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return;
130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*___________________________________________________________________________
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   Function Name : Pow2()                                                  |
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|     L_x = pow(2.0, exponant.fraction)         (exponant = interger part)  |
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|         = pow(2.0, 0.fraction) << exponant                                |
138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|---------------------------------------------------------------------------|
139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Algorithm:                                                               |
140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   The function Pow2(L_x) is approximated by a table and linear            |
142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   interpolation.                                                          |
143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
144e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   1- i = bit10-b15 of fraction,   0 <= i <= 31                            |
145e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   2- a = bit0-b9   of fraction                                            |
146e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2                 |
147e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   4- L_x = L_x >> (30-exponant)     (with rounding)                       |
148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|___________________________________________________________________________|
149e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*/
150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatic Word16 table_pow2[33] =
151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1525d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
1535d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
1545d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
1555d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    31379, 32066, 32767
156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard};
157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
158e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord32 Pow2(                               /* (o) Q0  : result       (range: 0<=val<=0x7fffffff) */
1595d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 exponant,                      /* (i) Q0  : Integer part.      (range: 0<=val<=30)   */
1605d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 fraction                       /* (i) Q15 : Fractionnal part.  (range: 0.0<=val<1.0) */
1615d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen       )
162e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
1635d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 exp, i, a, tmp;
1645d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 L_x;
165e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1665d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x = vo_L_mult(fraction, 32);            /* L_x = fraction<<6           */
1675d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    i = extract_h(L_x);                    /* Extract b10-b16 of fraction */
1685d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x =L_x >> 1;
1695d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    a = (Word16)(L_x);                    /* Extract b0-b9   of fraction */
1705d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    a = (Word16) (a & (Word16) 0x7fff);
171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1725d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x = L_deposit_h(table_pow2[i]);      /* table[i] << 16        */
1735d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    tmp = vo_sub(table_pow2[i], table_pow2[i + 1]);        /* table[i] - table[i+1] */
1745d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x -= (tmp * a)<<1;              /* L_x -= tmp*a*2        */
175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1765d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    exp = vo_sub(30, exponant);
1775d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_x = vo_L_shr_r(L_x, exp);
178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
1795d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (L_x);
180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
182e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*___________________________________________________________________________
183e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
184e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|   Function Name : Dot_product12()                                         |
185e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
186e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       Compute scalar product of <x[],y[]> using accumulator.              |
187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
188e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       The result is normalized (in Q31) with exponent (0..30).            |
189e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|---------------------------------------------------------------------------|
190e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|  Algorithm:                                                               |
191e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|                                                                           |
192e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|       dot_product = sum(x[i]*y[i])     i=0..N-1                           |
193e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard|___________________________________________________________________________|
194e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard*/
195e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
196e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardWord32 Dot_product12(                      /* (o) Q31: normalized result (1 < val <= -1) */
1975d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 x[],                           /* (i) 12bits: x vector                       */
1985d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 y[],                           /* (i) 12bits: y vector                       */
1995d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 lg,                            /* (i)    : vector length                     */
2005d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        Word16 * exp                          /* (o)    : exponent of result (0..+30)       */
2015d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen        )
202e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard{
2035d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word16 sft;
2045d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    Word32 i, L_sum;
2055d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_sum = 0;
2065d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    for (i = 0; i < lg; i++)
2075d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    {
20858996b6fa078bde4b8a68891962b43383848c190Marco Nelissen        Word32 tmp = (Word32) x[i] * (Word32) y[i];
20958996b6fa078bde4b8a68891962b43383848c190Marco Nelissen        if (tmp == (Word32) 0x40000000L) {
21058996b6fa078bde4b8a68891962b43383848c190Marco Nelissen            tmp = MAX_32;
21158996b6fa078bde4b8a68891962b43383848c190Marco Nelissen        }
21258996b6fa078bde4b8a68891962b43383848c190Marco Nelissen        L_sum = L_add(L_sum, tmp);
2135d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    }
21458996b6fa078bde4b8a68891962b43383848c190Marco Nelissen    L_sum = L_shl2(L_sum, 1);
21558996b6fa078bde4b8a68891962b43383848c190Marco Nelissen    L_sum = L_add(L_sum, 1);
2165d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    /* Normalize acc in Q31 */
2175d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    sft = norm_l(L_sum);
2185d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    L_sum = L_sum << sft;
2195d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    *exp = 30 - sft;            /* exponent = 0..30 */
2205d5c3a132bb446ac78a37dfaac24a46cacf0dd73Marco Nelissen    return (L_sum);
221e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
222e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
223e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
224e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
225