SphinxBase  0.6
include/sphinxbase/fixpoint.h
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
00002 /* ====================================================================
00003  * Copyright (c) 2005 Carnegie Mellon University.  All rights 
00004  * reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer. 
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in
00015  *    the documentation and/or other materials provided with the
00016  *    distribution.
00017  *
00018  * This work was supported in part by funding from the Defense Advanced 
00019  * Research Projects Agency and the National Science Foundation of the 
00020  * United States of America, and the CMU Sphinx Speech Consortium.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 
00023  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
00024  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00025  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
00026  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00028  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00029  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00030  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00031  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00032  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * ==================================================================== */
00035 
00036 /* Fixed-point arithmetic macros.
00037  *
00038  * Author: David Huggins-Daines <dhuggins@cs.cmu.edu>
00039  */
00040 
00041 #ifndef _FIXPOINT_H_
00042 #define _FIXPOINT_H_
00043 
00044 #include <limits.h>
00045 
00046 /* Win32/WinCE DLL gunk */
00047 #include <sphinxbase/sphinxbase_export.h>
00048 #include <sphinxbase/prim_type.h>
00049 
00050 #ifdef __cplusplus
00051 extern "C" {
00052 #endif
00053 #if 0
00054 /* Fool Emacs. */
00055 }
00056 #endif
00057 
00058 #ifndef DEFAULT_RADIX
00059 #define DEFAULT_RADIX 12
00060 #endif
00061 
00063 typedef int32 fixed32;
00064 
00066 #define FLOAT2FIX_ANY(x,radix) \
00067         (((x)<0.0) ? \
00068         ((fixed32)((x)*(float32)(1<<(radix)) - 0.5)) \
00069         : ((fixed32)((x)*(float32)(1<<(radix)) + 0.5)))
00070 #define FLOAT2FIX(x) FLOAT2FIX_ANY(x,DEFAULT_RADIX)
00071 
00072 #define FIX2FLOAT_ANY(x,radix) ((float32)(x)/(1<<(radix)))
00073 #define FIX2FLOAT(x) FIX2FLOAT_ANY(x,DEFAULT_RADIX)
00074 
00083 /* 
00084  * This works on most modern ARMs but *only* in ARM mode (for obvious
00085  * reasons), so don't use it in Thumb mode (but why are you building
00086  * signal processing code in Thumb mode?!)
00087  */
00088 #if defined(__arm__) && !defined(__thumb__)
00089 #define FIXMUL(a,b) FIXMUL_ANY(a,b,DEFAULT_RADIX)
00090 #define FIXMUL_ANY(a,b,r) ({                            \
00091       int cl, ch, _a = a, _b = b;                       \
00092       __asm__ ("smull %0, %1, %2, %3\n"                 \
00093            "mov %0, %0, lsr %4\n"                       \
00094            "orr %0, %0, %1, lsl %5\n"                   \
00095            : "=&r" (cl), "=&r" (ch)                     \
00096            : "r" (_a), "r" (_b), "i" (r), "i" (32-(r)));\
00097       cl; })
00098 #elif defined(BFIN) && DEFAULT_RADIX == 16
00099 /* Blackfin magic */
00100 #undef FIXMUL
00101 /* Use the accumulators for the 16.16 case (probably not as efficient as it could be). */
00102 #define FIXMUL(a,b) ({                                  \
00103       int c, _a = a, _b = b;                            \
00104         __asm__("%0.L = %1.l * %2.l (FU);\n\t"          \
00105             "%0.H = %1.h * %2.h (IS);\n\t"              \
00106             "A1 = %0;\n\t"                              \
00107             "A1 += %1.h * %2.l (IS, M);\n\t"            \
00108             "%0 = (A1 += %2.h * %1.l) (IS, M);\n\t"     \
00109             : "=&W" (c)                                 \
00110             : "d" (_a), "d" (_b)                        \
00111             : "A1", "cc");                                      \
00112       c; })
00113 #define FIXMUL_ANY(a,b,radix) ((fixed32)(((int64)(a)*(b))>>(radix)))
00114 #elif defined(_MSC_VER) || (defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8)
00115 #define FIXMUL(a,b) FIXMUL_ANY(a,b,DEFAULT_RADIX)
00116 #define FIXMUL_ANY(a,b,radix) ((fixed32)(((int64)(a)*(b))>>(radix)))
00117 #else /* Most general case where 'long long' doesn't exist or is slow. */
00118 #define FIXMUL(a,b) FIXMUL_ANY(a,b,DEFAULT_RADIX)
00119 #define FIXMUL_ANY(a,b,radix) \
00120         (fixed32)(((((uint32)(a))&((1<<(radix))-1))         \
00121                    * (((uint32)(b))&((1<<(radix))-1)) >> (radix))       \
00122         + (((((int32)(a))>>(radix)) * (((int32)(b))>>(radix))) << (radix)) \
00123         + ((((uint32)(a))&((1<<(radix))-1)) * (((int32)(b))>>(radix))) \
00124         + ((((uint32)(b))&((1<<(radix))-1)) * (((int32)(a))>>(radix))))
00125 #endif
00126 
00127 /* Various fixed-point logarithmic functions that we need. */
00129 #define MIN_FIXLOG -2829416  /* log(1e-300) * (1<<DEFAULT_RADIX) */
00130 #define MIN_FIXLOG2 -4081985 /* log2(1e-300) * (1<<DEFAULT_RADIX) */
00131 
00132 #define FIXLN_2         ((fixed32)(0.693147180559945 * (1<<DEFAULT_RADIX)))
00133 
00134 #define FIXLN(x) (fixlog(x) - (FIXLN_2 * DEFAULT_RADIX))
00135 
00139 int32 fixlog(uint32 x);
00144 int32 fixlog2(uint32 x);
00145 
00146 #ifdef __cplusplus
00147 }
00148 #endif
00149 
00150 
00151 #endif /* _FIXPOINT_H_ */