division_operations.c revision c55a96383497a772a307b346368133960b02ad03
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 "signal_processing_library.h"
25
26WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den)
27{
28    // Guard against division with 0
29    if (den != 0)
30    {
31        return (WebRtc_UWord32)(num / den);
32    } else
33    {
34        return (WebRtc_UWord32)0xFFFFFFFF;
35    }
36}
37
38WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den)
39{
40    // Guard against division with 0
41    if (den != 0)
42    {
43        return (WebRtc_Word32)(num / den);
44    } else
45    {
46        return (WebRtc_Word32)0x7FFFFFFF;
47    }
48}
49
50WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den)
51{
52    // Guard against division with 0
53    if (den != 0)
54    {
55        return (WebRtc_Word16)(num / den);
56    } else
57    {
58        return (WebRtc_Word16)0x7FFF;
59    }
60}
61
62WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den)
63{
64    WebRtc_Word32 L_num = num;
65    WebRtc_Word32 L_den = den;
66    WebRtc_Word32 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
100WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
101                                    WebRtc_Word16 den_low)
102{
103    WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low;
104    WebRtc_Word32 tmpW32;
105
106    approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi);
107    // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
108
109    // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
110    tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1)
111            + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1);
112    // tmpW32 = den * approx
113
114    tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
115
116    // Store tmpW32 in hi and low format
117    tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
118    tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
119            - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
120
121    // tmpW32 = 1/den in Q29
122    tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx)
123            >> 15)) << 1);
124
125    // 1/den in hi and low format
126    tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
127    tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
128            - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
129
130    // Store num in hi and low format
131    num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16);
132    num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num
133            - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1);
134
135    // num * (1/den) by 32 bit multiplication (result in Q28)
136
137    tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low)
138            >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15));
139
140    // Put result in Q31 (convert from Q28)
141    tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
142
143    return tmpW32;
144}
145