1/*---------------------------------------------------------------------------*
2 *  sh_down.h  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20#ifndef _SH_DOWN_INL_
21#define _SH_DOWN_INL_
22
23#include <limits.h>
24
25#include "fronttyp.h"
26#include "setting.h"
27#include "portable.h"
28
29#define SHIFT_DOWN(X,S) ((S) > 0 ? shift_down_inline ((X), (S)) : (X))
30#define SHIFT_UP(X,S) ((S) > 0 ? shift_up_inline ((X), (S)) : (X))
31
32#define COND_SHIFT_DOWN(X,S) (SHIFT_DOWN(X,S))
33#define COND_SHIFT_UP(X,S) (SHIFT_UP(X,S))
34
35static PINLINE int fixed_point_convert(float xx, int shift);
36static PINLINE int shift_up_inline(int value, unsigned int shift);
37static PINLINE int shift_down_inline(int value, unsigned int shift);
38static PINLINE int fixed_round(float value);
39
40#define TRUNCATE_ON_SHIFT   1
41
42static PINLINE int shift_up_inline(int value, unsigned int shift)
43{
44  /* Shift up using bit operations with max limit */
45  int temp, retval;
46
47  ASSERT(shift > 0);
48  if (value > 0)
49    temp = value;
50  else
51    temp = -value;
52
53  retval = temp << shift;
54
55  if ((retval > (int)LONG_MAX) || (retval < temp)) /* TODO: max_val if LONG_MAX, overflow won't be detected */
56    retval = (int)LONG_MAX;
57  if (value > 0)
58    return retval;
59  else
60    return (-retval);
61}
62
63
64static PINLINE int shift_down_inline(int value, unsigned int shift)
65/* Shift down using bit operations with rounding */
66{
67  if (shift-- == 0)
68    return (value);
69  if (value >= 0)
70    return (((value >> shift) + 1) >> 1);
71  else
72    return (-((((-value) >> shift) + 1) >> 1));
73}
74
75static PINLINE int fixed_point_convert(float xx, int shift)
76{
77  float   scaled_val;
78
79  ASSERT(shift >= 0);
80  scaled_val = xx * (0x01 << shift);
81  if (scaled_val >= 0)
82    if (scaled_val > LONG_MAX)
83      return (LONG_MAX);
84    else
85      return ((int)(scaled_val + 0.5));
86  else
87    if (scaled_val < -LONG_MAX)
88      return (-LONG_MAX);
89    else
90      return ((int)(scaled_val - 0.5));
91}
92
93static PINLINE int fixed_round(float value)
94{
95  if (value > 0)
96    return ((int)(value + 0.5));
97  else
98    return ((int)(value - 0.5));
99}
100
101#endif
102