1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12/*
13 * This file contains implementations of the divisions
14 * WebRtcSpl_DivU32U16()
15 * WebRtcSpl_DivW32W16()
16 * WebRtcSpl_DivW32W16ResW16()
17 * WebRtcSpl_DivResultInQ31()
18 * WebRtcSpl_DivW32HiLow()
19 *
20 * The description header can be found in signal_processing_library.h
21 *
22 */
23
24#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
25
26uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den)
27{
28    // Guard against division with 0
29    if (den != 0)
30    {
31        return (uint32_t)(num / den);
32    } else
33    {
34        return (uint32_t)0xFFFFFFFF;
35    }
36}
37
38int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den)
39{
40    // Guard against division with 0
41    if (den != 0)
42    {
43        return (int32_t)(num / den);
44    } else
45    {
46        return (int32_t)0x7FFFFFFF;
47    }
48}
49
50int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den)
51{
52    // Guard against division with 0
53    if (den != 0)
54    {
55        return (int16_t)(num / den);
56    } else
57    {
58        return (int16_t)0x7FFF;
59    }
60}
61
62int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den)
63{
64    int32_t L_num = num;
65    int32_t L_den = den;
66    int32_t div = 0;
67    int k = 31;
68    int change_sign = 0;
69
70    if (num == 0)
71        return 0;
72
73    if (num < 0)
74    {
75        change_sign++;
76        L_num = -num;
77    }
78    if (den < 0)
79    {
80        change_sign++;
81        L_den = -den;
82    }
83    while (k--)
84    {
85        div <<= 1;
86        L_num <<= 1;
87        if (L_num >= L_den)
88        {
89            L_num -= L_den;
90            div++;
91        }
92    }
93    if (change_sign == 1)
94    {
95        div = -div;
96    }
97    return div;
98}
99
100int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
101{
102    int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
103    int32_t tmpW32;
104
105    approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi);
106    // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
107
108    // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
109    tmpW32 = (den_hi * approx << 1) + ((den_low * approx >> 15) << 1);
110    // tmpW32 = den * approx
111
112    tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
113
114    // Store tmpW32 in hi and low format
115    tmp_hi = (int16_t)(tmpW32 >> 16);
116    tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1);
117
118    // tmpW32 = 1/den in Q29
119    tmpW32 = (tmp_hi * approx + (tmp_low * approx >> 15)) << 1;
120
121    // 1/den in hi and low format
122    tmp_hi = (int16_t)(tmpW32 >> 16);
123    tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1);
124
125    // Store num in hi and low format
126    num_hi = (int16_t)(num >> 16);
127    num_low = (int16_t)((num - ((int32_t)num_hi << 16)) >> 1);
128
129    // num * (1/den) by 32 bit multiplication (result in Q28)
130
131    tmpW32 = num_hi * tmp_hi + (num_hi * tmp_low >> 15) +
132        (num_low * tmp_hi >> 15);
133
134    // Put result in Q31 (convert from Q28)
135    tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
136
137    return tmpW32;
138}
139