comparison spandsp-0.0.6pre17/src/spandsp/saturated.h @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * saturated.h - General saturated arithmetic routines.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2001, 2008 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: saturated.h,v 1.4 2009/02/05 12:21:36 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if !defined(_SPANDSP_SATURATED_H_)
31 #define _SPANDSP_SATURATED_H_
32
33 /*! \page saturated_page Saturated arithmetic
34
35 \section saturated_page_sec_1 What does it do?
36
37
38 \section saturated_page_sec_2 How does it work?
39
40 */
41
42 #if defined(__cplusplus)
43 extern "C"
44 {
45 #endif
46
47 static __inline__ int16_t saturate(int32_t amp)
48 {
49 int16_t amp16;
50
51 /* Hopefully this is optimised for the common case - not clipping */
52 amp16 = (int16_t) amp;
53 if (amp == amp16)
54 return amp16;
55 if (amp > INT16_MAX)
56 return INT16_MAX;
57 return INT16_MIN;
58 }
59 /*- End of function --------------------------------------------------------*/
60
61 /*! Saturate to 15 bits, rather than the usual 16 bits. This is often a useful function. */
62 static __inline__ int16_t saturate15(int32_t amp)
63 {
64 if (amp > 16383)
65 return 16383;
66 if (amp < -16384)
67 return -16384;
68 return (int16_t) amp;
69 }
70 /*- End of function --------------------------------------------------------*/
71
72 static __inline__ int16_t fsaturatef(float famp)
73 {
74 if (famp > (float) INT16_MAX)
75 return INT16_MAX;
76 if (famp < (float) INT16_MIN)
77 return INT16_MIN;
78 return (int16_t) lrintf(famp);
79 }
80 /*- End of function --------------------------------------------------------*/
81
82 static __inline__ int16_t fsaturate(double damp)
83 {
84 if (damp > (double) INT16_MAX)
85 return INT16_MAX;
86 if (damp < (double) INT16_MIN)
87 return INT16_MIN;
88 return (int16_t) lrint(damp);
89 }
90 /*- End of function --------------------------------------------------------*/
91
92 /* Saturate to a 16 bit integer, using the fastest float to int conversion */
93 static __inline__ int16_t ffastsaturatef(float famp)
94 {
95 if (famp > (float) INT16_MAX)
96 return INT16_MAX;
97 if (famp < (float) INT16_MIN)
98 return INT16_MIN;
99 return (int16_t) lfastrintf(famp);
100 }
101 /*- End of function --------------------------------------------------------*/
102
103 /* Saturate to a 16 bit integer, using the fastest double to int conversion */
104 static __inline__ int16_t ffastsaturate(double damp)
105 {
106 if (damp > (double) INT16_MAX)
107 return INT16_MAX;
108 if (damp < (double) INT16_MIN)
109 return INT16_MIN;
110 return (int16_t) lfastrint(damp);
111 }
112 /*- End of function --------------------------------------------------------*/
113
114 /* Saturate to a 16 bit integer, using the closest float to int conversion */
115 static __inline__ float ffsaturatef(float famp)
116 {
117 if (famp > (float) INT16_MAX)
118 return (float) INT16_MAX;
119 if (famp < (float) INT16_MIN)
120 return (float) INT16_MIN;
121 return famp;
122 }
123 /*- End of function --------------------------------------------------------*/
124
125 /* Saturate to a 16 bit integer, using the closest double to int conversion */
126 static __inline__ double ffsaturate(double famp)
127 {
128 if (famp > (double) INT16_MAX)
129 return (double) INT16_MAX;
130 if (famp < (double) INT16_MIN)
131 return (double) INT16_MIN;
132 return famp;
133 }
134 /*- End of function --------------------------------------------------------*/
135
136 static __inline__ int16_t saturated_add16(int16_t a, int16_t b)
137 {
138 #if defined(__GNUC__) && defined(__i386__)
139 __asm__ __volatile__(
140 " addw %2,%0;\n"
141 " jno 0f;\n"
142 " movw $0x7fff,%0;\n"
143 " adcw $0,%0;\n"
144 "0:"
145 : "=r" (a)
146 : "0" (a), "ir" (b)
147 : "cc"
148 );
149 return a;
150 #else
151 return saturate((int32_t) a + (int32_t) b);
152 #endif
153 }
154 /*- End of function --------------------------------------------------------*/
155
156 static __inline__ int32_t saturated_add32(int32_t a, int32_t b)
157 {
158 #if defined(__GNUC__) && defined(__i386__)
159 __asm__ __volatile__(
160 " addl %2,%0;\n"
161 " jno 0f;\n"
162 " movl $0x7fffffff,%0;\n"
163 " adcl $0,%0;\n"
164 "0:"
165 : "=r" (a)
166 : "0" (a), "ir" (b)
167 : "cc"
168 );
169 return a;
170 #else
171 uint32_t A;
172
173 if (a < 0)
174 {
175 if (b >= 0)
176 return a + b;
177 /*endif*/
178 A = (uint32_t) -(a + 1) + (uint32_t) -(b + 1);
179 return (A >= INT32_MAX) ? INT32_MIN : -(int32_t) A - 2;
180 }
181 /*endif*/
182 if (b <= 0)
183 return a + b;
184 /*endif*/
185 A = (uint32_t) a + (uint32_t) b;
186 return (A > INT32_MAX) ? INT32_MAX : A;
187 #endif
188 }
189 /*- End of function --------------------------------------------------------*/
190
191 static __inline__ int16_t saturated_sub16(int16_t a, int16_t b)
192 {
193 return saturate((int32_t) a - (int32_t) b);
194 }
195 /*- End of function --------------------------------------------------------*/
196
197 static __inline__ int16_t saturated_mul16(int16_t a, int16_t b)
198 {
199 if (a == INT16_MIN && b == INT16_MIN)
200 return INT16_MAX;
201 /*endif*/
202 return (int16_t) (((int32_t) a*(int32_t) b) >> 15);
203 }
204 /*- End of function --------------------------------------------------------*/
205
206 static __inline__ int32_t saturated_mul_16_32(int16_t a, int16_t b)
207 {
208 return ((int32_t) a*(int32_t) b) << 1;
209 }
210 /*- End of function --------------------------------------------------------*/
211
212 static __inline__ int16_t saturated_abs16(int16_t a)
213 {
214 return (a == INT16_MIN) ? INT16_MAX : (int16_t) abs(a);
215 }
216 /*- End of function --------------------------------------------------------*/
217
218 #if defined(__cplusplus)
219 }
220 #endif
221
222 #endif
223 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.