Mercurial > forge
view main/fixed/src/int/fixed.cc @ 9481:d84d2fea3c90 octave-forge
Re-enable compilation of fixed package
author | jordigh |
---|---|
date | Wed, 22 Feb 2012 22:07:33 +0000 |
parents | 2de537641f94 |
children |
line wrap: on
line source
/* Copyright (C) 2001-2003 Motorola Inc Copyright (C) 2001-2003 Laurent Mazet Copyright (C) 2003 David Bateman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. In addition to the terms of the GPL, you are permitted to link this program with any Open Source program, as defined by the Open Source Initiative (www.opensource.org) */ #if !defined (__int_fixed_cc) #define __int_fixed_cc 1 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) #pragma implementation #endif #include <iostream> #include <cmath> #include "fixed.h" #if !defined(OCTAVE_FORGE) #if defined(__APPLE__) && defined(__MACH__) extern "C" int isnan (double); extern "C" int isinf (double); #endif #define lo_ieee_isnan(x) isnan(x) #define lo_ieee_isinf(x) isinf(x) #else #include <octave/lo-ieee.h> #endif // Various tables of power 5. #if (SIZEOF_FIXED == 2) char pow5[16][16] = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,1,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,9,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,4,8,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,2,4,4,1,4,0,6,2,5 }, { 0,0,0,0,0,0,1,2,2,0,7,0,3,1,2,5 }, { 0,0,0,0,0,0,6,1,0,3,5,1,5,6,2,5 }, { 0,0,0,0,0,3,0,5,1,7,5,7,8,1,2,5 } }; #elif (SIZEOF_FIXED == 4) char pow5[32][32] = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,4,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,1,0,3,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,5,1,7,5,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,5,2,5,8,7,8,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,6,2,9,3,9,4,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,8,1,4,6,9,7,2,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,0,7,3,4,8,6,3,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,3,6,7,4,3,1,6,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,7,6,8,3,7,1,5,8,2,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,8,4,1,8,5,7,9,1,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,9,2,0,9,2,8,9,5,5,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,4,6,4,4,7,7,5,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,9,8,0,2,3,2,2,3,8,7,6,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,9,0,1,1,6,1,1,9,3,8,4,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,7,4,5,0,5,8,0,5,9,6,9,2,3,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,3,7,2,5,2,9,0,2,9,8,4,6,1,9,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,1,8,6,2,6,4,5,1,4,9,2,3,0,9,5,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,9,3,1,3,2,2,5,7,4,6,1,5,4,7,8,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,4,6,5,6,6,1,2,8,7,3,0,7,7,3,9,2,5,7,8,1,2,5 } }; #elif (SIZEOF_FIXED == 8) char pow5[64][64] = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,4,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,1,0,3,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,5,1,7,5,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,5,2,5,8,7,8,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,6,2,9,3,9,4,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,8,1,4,6,9,7,2,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,0,7,3,4,8,6,3,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,3,6,7,4,3,1,6,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,7,6,8,3,7,1,5,8,2,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,8,4,1,8,5,7,9,1,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,9,2,0,9,2,8,9,5,5,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,4,6,4,4,7,7,5,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,9,8,0,2,3,2,2,3,8,7,6,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,9,0,1,1,6,1,1,9,3,8,4,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,4,5,0,5,8,0,5,9,6,9,2,3,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,7,2,5,2,9,0,2,9,8,4,6,1,9,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,6,2,6,4,5,1,4,9,2,3,0,9,5,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,3,1,3,2,2,5,7,4,6,1,5,4,7,8,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,6,5,6,6,1,2,8,7,3,0,7,7,3,9,2,5,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,2,8,3,0,6,4,3,6,5,3,8,6,9,6,2,8,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,6,4,1,5,3,2,1,8,2,6,9,3,4,8,1,4,4,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,8,2,0,7,6,6,0,9,1,3,4,6,7,4,0,7,2,2,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,9,1,0,3,8,3,0,4,5,6,7,3,3,7,0,3,6,1,3,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,5,5,1,9,1,5,2,2,8,3,6,6,8,5,1,8,0,6,6,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,2,7,5,9,5,7,6,1,4,1,8,3,4,2,5,9,0,3,3,2,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,3,7,9,7,8,8,0,7,0,9,1,7,1,2,9,5,1,6,6,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,1,8,9,8,9,4,0,3,5,4,5,8,5,6,4,7,5,8,3,0,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,9,4,9,4,7,0,1,7,7,2,9,2,8,2,3,7,9,1,5,0,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,5,4,7,4,7,3,5,0,8,8,6,4,6,4,1,1,8,9,5,7,5,1,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,7,3,7,3,6,7,5,4,4,3,2,3,2,0,5,9,4,7,8,7,5,9,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,3,6,8,6,8,3,7,7,2,1,6,1,6,0,2,9,7,3,9,3,7,9,8,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,6,8,4,3,4,1,8,8,6,0,8,0,8,0,1,4,8,6,9,6,8,9,9,4,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,8,4,2,1,7,0,9,4,3,0,4,0,4,0,0,7,4,3,4,8,4,4,9,7,0,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,2,1,0,8,5,4,7,1,5,2,0,2,0,0,3,7,1,7,4,2,2,4,8,5,3,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,5,4,2,7,3,5,7,6,0,1,0,0,1,8,5,8,7,1,1,2,4,2,6,7,5,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,5,2,7,1,3,6,7,8,8,0,0,5,0,0,9,2,9,3,5,5,6,2,1,3,3,7,8,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,7,7,6,3,5,6,8,3,9,4,0,0,2,5,0,4,6,4,6,7,7,8,1,0,6,6,8,9,4,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8,8,1,7,8,4,1,9,7,0,0,1,2,5,2,3,2,3,3,8,9,0,5,3,3,4,4,7,2,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0,8,9,2,0,9,8,5,0,0,6,2,6,1,6,1,6,9,4,5,2,6,6,7,2,3,6,3,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,4,4,6,0,4,9,2,5,0,3,1,3,0,8,0,8,4,7,2,6,3,3,3,6,1,8,1,6,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,2,2,3,0,2,4,6,2,5,1,5,6,5,4,0,4,2,3,6,3,1,6,6,8,0,9,0,8,2,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,1,1,1,5,1,2,3,1,2,5,7,8,2,7,0,2,1,1,8,1,5,8,3,4,0,4,5,4,1,0,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,7,7,5,5,5,7,5,6,1,5,6,2,8,9,1,3,5,1,0,5,9,0,7,9,1,7,0,2,2,7,0,5,0,7,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,8,7,7,7,8,7,8,0,7,8,1,4,4,5,6,7,5,5,2,9,5,3,9,5,8,5,1,1,3,5,2,5,3,9,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,9,3,8,8,9,3,9,0,3,9,0,7,2,2,8,3,7,7,6,4,7,6,9,7,9,2,5,5,6,7,6,2,6,9,5,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,6,9,4,4,6,9,5,1,9,5,3,6,1,4,1,8,8,8,2,3,8,4,8,9,6,2,7,8,3,8,1,3,4,7,6,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,7,3,4,7,2,3,4,7,5,9,7,6,8,0,7,0,9,4,4,1,1,9,2,4,4,8,1,3,9,1,9,0,6,7,3,8,2,8,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,7,3,6,1,7,3,7,9,8,8,4,0,3,5,4,7,2,0,5,9,6,2,2,4,0,6,9,5,9,5,3,3,6,9,1,4,0,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,3,3,6,8,0,8,6,8,9,9,4,2,0,1,7,7,3,6,0,2,9,8,1,1,2,0,3,4,7,9,7,6,6,8,4,5,7,0,3,1,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,6,8,4,0,4,3,4,4,9,7,1,0,0,8,8,6,8,0,1,4,9,0,5,6,0,1,7,3,9,8,8,3,4,2,2,8,5,1,5,6,2,5 }, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,8,4,2,0,2,1,7,2,4,8,5,5,0,4,4,3,4,0,0,7,4,5,2,8,0,0,8,6,9,9,4,1,7,1,1,4,2,5,7,8,1,2,5 } }; #else # error ("Tables of power 5 only availble for fp_uint sizes of 4 and 8 bytes"); #endif const fp_uint one = 1; #if !defined(OCTAVE_FORGE) void Fixed::_error (char *file, int line, Fixed::Code code) { std::cerr << "Error in file " << file << " at line " << line << std::endl; std::cerr << message[code] << std::endl; exit (1); } void Fixed::_warning (char *file, int line, Fixed::Code code) { std::cerr << "Warning in file " << file << " at line " << line << std::endl; std::cerr << message[code] << std::endl; } #endif /* FixedPoint de-structuror */ double FixedPoint::fixedpoint() const { double v = (signbit()) ? -(double)((-number)&filter) : (double)number; v /= (1<<decsize); return (v); } /* FixedPoint constructors */ FixedPoint::FixedPoint (unsigned int is, unsigned int ds, const fp_uint n) { /* This constructor helps to construct FixedPoint from the `number' field of an FixedPoing object. As the sign bit is not marked, this constructor can overflow. */ /* Check sizes */ if (ds+is > maxfixedsize) { fixed_error (Fixed::WRONGFIXSIZE); return; } /* Get sizes */ decsize = ds; intsize = is; /* Get filters */ filter = (one << (is+ds+1)) - 1; /* Build number */ number = n&filter; /* Check for overflow */ if ((Fixed::FP_Overflow) && (n > filter)) fixed_warning (Fixed::LOSS_MSB_INT); /* Debug */ if (Fixed::FP_Debug) value = fixedpoint(); } FixedPoint::FixedPoint (unsigned int is, unsigned int ds, const fp_uint i, const fp_uint d) { /* This constructor helps to construct FixedPoint from an (i,d) representation. As the sign bit is not marked, this constructor can overflow from integer part and decimal part. */ /* Check sizes */ if (ds+is > maxfixedsize) { fixed_error (Fixed::WRONGFIXSIZE); return; } /* Get sizes */ decsize = ds; intsize = is; /* Get filters */ filter = (one << (is+ds+1)) - 1; fp_uint filter_int = (one << (is+1)) - 1; fp_uint filter_dec = (one << ds) - 1; /* Build number */ number = ((i&filter_int) << ds) | (d&filter_dec); /* Check for overflow */ if (Fixed::FP_Overflow) { if (d > filter_dec) fixed_warning (Fixed::LOSS_MSB_DEC); if (i > filter_int) fixed_warning (Fixed::LOSS_MSB_INT); } /* Debug */ if (Fixed::FP_Debug) value = fixedpoint(); } FixedPoint::FixedPoint (unsigned int is, unsigned int ds, const FixedPoint &x) { /* This constructor helps to construct FixedPoint from a other FixedPoint object. Even if this constructor loss some bits from integer part, the sign bit is kept. */ /* Check sizes */ if (ds+is> maxfixedsize) { fixed_error (Fixed::WRONGFIXSIZE); return; } /* Get sizes */ decsize = ds; intsize = is; /* Get sign bit */ fp_uint s = x.signbit(); /* Get filter */ filter = (one << (is+ds+1)) - 1; /* Create decimal part */ int diffds = ds-x.decsize; fp_uint d = x.number & ((one << x.decsize)-1); d = (diffds > 0) ? ( d << diffds) : (d >> (-diffds)); /* Create integer part */ int diffis = is-x.intsize; fp_uint i = (x.number >> x.decsize) & ((one << x.intsize)-1); if ((s) && (diffis > 0)) i |= ((one << diffis)-1) << x.intsize; i &= (one << is)-1; i |= (s << is); /* Create number */ number = (i << ds) | d; /* Check for overflow */ if (Fixed::FP_Overflow) { if (s) { if ((diffis < 0) && ((x.number >> x.decsize) < ((one << (1-diffis))-1) << is)) fixed_warning(Fixed::LOSS_MSB_FP); } else { if ((x.number >> x.decsize) >= (one << is)) fixed_warning(Fixed::LOSS_MSB_FP); } } /* Debug */ if (Fixed::FP_Debug) value = fixedpoint(); } FixedPoint::FixedPoint (unsigned int is, unsigned int ds, double x) { /* This constructor helps to construct FixedPoint from a double precision number. This constructor act as a ADC and clip too large value*/ /* Check sizes */ if (ds+is > maxfixedsize) fixed_error (Fixed::WRONGFIXSIZE); /* Get sizes */ decsize = ds; intsize = is; /* Get filter */ filter = (one << (is+ds+1)) - 1; /* Create clipping values */ double negclip = - double(one<<is); double posclip = double(one<<is) - 1./(one<<ds); /* Check for erreur */ if (lo_ieee_isnan(x)) { /* Not a number */ x = 0; if (Fixed::FP_Overflow) fixed_warning(Fixed::NAN_CONST); } else if (lo_ieee_isinf(x)) { /* Infinity */ x = (lo_ieee_isinf(x) > 0) ? posclip : negclip; if (Fixed::FP_Overflow) fixed_warning(Fixed::INF_CONST); } else if (x > posclip) { /* Positive clipping */ x = posclip; if (Fixed::FP_Overflow) fixed_warning(Fixed::LOSS_MSB_DB); } else if (x < negclip) { /* Negative clipping */ x = negclip; if (Fixed::FP_Overflow) fixed_warning(Fixed::LOSS_MSB_DB); } /* Create number */ if (x == negclip) number = one<<(is+ds); else { number = (fp_uint) floor(x*(1<<ds)); } number &= filter; /* Debug */ if (Fixed::FP_Debug) value = fixedpoint(); } FixedPoint::FixedPoint (const fp_int x) { /* This constructor helps to construct FixedPoint from a integer. This constructor act as a ADC and clip too large value. */ fp_int x_clipped; /* Create clipping values */ fp_int negclip = - fp_int(one<<maxfixedsize); fp_int posclip = fp_int(one<<maxfixedsize) - 1; /* Check for erreur */ if (x > posclip) { /* Positive clipping */ x_clipped = posclip; if (Fixed::FP_Overflow) fixed_warning(Fixed::LOSS_MSB_DB); } else if (x < negclip) { /* Negative clipping */ x_clipped = negclip; if (Fixed::FP_Overflow) fixed_warning(Fixed::LOSS_MSB_DB); } else x_clipped = x; /* Get sizes */ decsize = 0; intsize = 0; fp_int tmp = x_clipped; while ((tmp) && (~tmp)) { intsize++; tmp>>=1; } /* Get filter */ filter = (one << (intsize+1)) - 1; /* Create number */ number = x_clipped & filter; /* Debug */ if (Fixed::FP_Debug) value = fixedpoint(); } /* This is a stupid constructor, that drops the decimal part, but it at least allows the C++ complex class to do log10 */ FixedPoint::FixedPoint (const double y) { *this = FixedPoint(fp_int(y)); } /* FixedPoint intern operators */ FixedPoint &FixedPoint::operator = (const fp_int &x) { FixedPoint y(x); intsize = y.intsize; decsize = y.decsize; filter = y.filter; number = y.number; if (Fixed::FP_Debug) value = y.value; return (*this); } FixedPoint &FixedPoint::operator = (const FixedPoint &x) { intsize = x.intsize; decsize = x.decsize; filter = x.filter; number = x.number; if (Fixed::FP_Debug) value = x.value; return (*this); } FixedPoint &FixedPoint::operator += (const FixedPoint &x) { FixedPoint n; if ((x.intsize != intsize) || (x.decsize != decsize)) { int _intsize = (x.intsize > intsize) ? x.intsize : intsize; int _decsize = (x.decsize > decsize) ? x.decsize : decsize; *this = FixedPoint(_intsize, _decsize, *this); n = FixedPoint(_intsize, _decsize, x); } else n = x; char s = Fixed::FP_Overflow ? signbit() : 0; number += n.number; if ((Fixed::FP_Overflow) && (s == n.signbit()) && ((s?((~number)&filter):number)>>(intsize+decsize))) fixed_warning(Fixed::LOSS_MSB_ADD); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_add++; return (*this); } FixedPoint &FixedPoint::operator -= (const FixedPoint &x) { FixedPoint n; if ((x.intsize != intsize) || (x.decsize != decsize)) { int _intsize = (x.intsize > intsize) ? x.intsize : intsize; int _decsize = (x.decsize > decsize) ? x.decsize : decsize; *this = FixedPoint(_intsize, _decsize, *this); n = FixedPoint(_intsize, _decsize, x); } else n = x; char s = Fixed::FP_Overflow ? signbit() : 0; number -= n.number; if ((Fixed::FP_Overflow) && (s != n.signbit()) && ((s?((~number)&filter):number)>>(intsize+decsize))) fixed_warning(Fixed::LOSS_MSB_SUB); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_sub++; return (*this); } FixedPoint &FixedPoint::operator *= (const FixedPoint &x) { /* To avoid any problem of multiplication overflow, we limit the maximum number space to maxfixedsize */ FixedPoint n; if ((x.intsize != intsize) || (x.decsize != decsize)) { int _intsize = (x.intsize > intsize) ? x.intsize : intsize; int _decsize = (x.decsize > decsize) ? x.decsize : decsize; *this = FixedPoint(_intsize, _decsize, *this); n = FixedPoint(_intsize, _decsize, x); } else n = x; fp_uint n1 = (signbit()) ? (-number)&filter : number; fp_uint n2 = (n.signbit()) ? (-n.number)&filter : n.number; if (intsize+decsize < halffixedsize) { /* No overflow problem. */ n1 *= n2; n1 >>= decsize; if ((Fixed::FP_Overflow) && (!((signbit() != n.signbit()) && (fp_int(n1) == (1L<<(intsize+decsize))))) && (n1>>(intsize+decsize))) fixed_warning(Fixed::LOSS_MSB_MULT); number = ((signbit() != n.signbit()) ? -n1 : n1)&filter; } else { /* Overflow problem. */ int size = intsize+decsize; int unconsistent_bits = size - halffixedsize + 1; fp_int lsb_filter = (1<<unconsistent_bits)-1; /* Split n1 and n2 into two part. */ fp_uint n1_high = n1>>unconsistent_bits; fp_uint n1_low = n1&lsb_filter; fp_uint n2_high = n2>>unconsistent_bits; fp_uint n2_low = n2&lsb_filter; /* Calculate the lowest part of n1*n2. */ fp_uint n_low = n1_low*n2_low; /* Calculate the medium part of n1*n2 and extract the msb part of the lowest part to avoid bit redundancy. */ fp_uint n_medium = n1_high*n2_low + n1_low*n2_high + (n_low>>unconsistent_bits); n_low &= lsb_filter; /* Calculate the highest part of n1*n2 and extract the msb part of the medium part to avoid bit redundancy. */ fp_uint n_high = n1_high*n2_high + (n_medium>>unconsistent_bits); n_medium &= lsb_filter; /* Keep only bits in fixed point format from the lowest part of the product. */ fp_uint n_sized = n_low >> decsize; /* Keep only bits in fixed point format from the medium part of the product and put them at right position. */ if (int(decsize) > unconsistent_bits) n_sized += n_medium>>(decsize-unconsistent_bits); else n_sized += n_medium<<(unconsistent_bits-decsize); /* Keep only bits in fixed point format from the highest part of the product and put them at right position */ if (int(decsize) > 2*unconsistent_bits) n_sized += n_high >>(decsize-2*unconsistent_bits); else n_sized += n_high <<(2*unconsistent_bits-decsize); /* Check format and sign bit. */ if (Fixed::FP_Overflow) { int _t = 2*unconsistent_bits-decsize; if ((!((signbit() != n.signbit()) && (fp_int(n_sized) == (1L<<(intsize+decsize))))) && (((_t >= 0) && (((n_high<<_t)>>_t) != n_high)) || (n_sized>>(intsize+decsize)))) fixed_warning(Fixed::LOSS_MSB_MULT); } number = ((signbit() != n.signbit()) ? -n_sized : n_sized)&filter; } if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_mult++; return (*this); } FixedPoint &FixedPoint::operator /= (const FixedPoint &x) { /* This operator need to really be implemented in a fixed precision manner */ double y1 = fixedpoint(); double y2 = x.fixedpoint(); *this = FixedPoint((x.intsize > intsize) ? x.intsize : intsize, (x.decsize > decsize) ? x.decsize : decsize, y1/y2); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_div++; return (*this); } FixedPoint &FixedPoint::operator <<= (const int s) { if ((Fixed::FP_Overflow) && (((intsize+decsize-s>0) &&(number)) || (((signbit()?((~number)&filter):number)>>(intsize+decsize-s))))) fixed_warning(Fixed::LOSS_MSB_LSHIFT); number <<= s; number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_lshift++; return (*this); } FixedPoint &FixedPoint::operator >>= (const int s) { char sign = signbit(); number >>= s; if (sign) number |= (filter >> s) ^ filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_rshift++; return (*this); } /* FixedPoint unary operators */ FixedPoint &FixedPoint::operator ++ () { // prefix ++ char s = Fixed::FP_Overflow ? signbit() : 0; number++; if ((Fixed::FP_Overflow) && (!s) && (signbit())) fixed_warning(Fixed::LOSS_MSB_PRE_INC); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_inc++; return(*this); } FixedPoint &FixedPoint::operator -- () { // prefix -- char s = Fixed::FP_Overflow ? signbit() : 0; number--; if ((Fixed::FP_Overflow) && (s) && (!signbit())) fixed_warning(Fixed::LOSS_MSB_PRE_DEC); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_dec++; return(*this); } FixedPoint FixedPoint::operator ++ (int) { // postfix ++ FixedPoint n(*this); char s = Fixed::FP_Overflow ? signbit() : 0; number++; if ((Fixed::FP_Overflow) && (!s) && (signbit())) fixed_warning(Fixed::LOSS_MSB_POST_INC); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_inc++; return (n); } FixedPoint FixedPoint::operator -- (int) { // postfix -- FixedPoint n(*this); char s = Fixed::FP_Overflow ? signbit() : 0; number--; if ((Fixed::FP_Overflow) && (s) && (!signbit())) fixed_warning(Fixed::LOSS_MSB_PRE_DEC); number &= filter; if (Fixed::FP_Debug) value = fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_dec++; return (n); } FixedPoint operator - (const FixedPoint &x) { FixedPoint n(x); n.number = (-n.number) & n.filter; if (Fixed::FP_Debug) n.value = n.fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_neg++; return (n); } FixedPoint operator ! (const FixedPoint &x) { FixedPoint n(x); n.number = n.number & (n.filter >> 1); if (Fixed::FP_Debug) n.value = n.fixedpoint(); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_comp++; return (n); } /* FixedPoint comparators */ bool operator == (const FixedPoint &x, const FixedPoint &y) { if ((x.decsize == y.decsize) && (x.intsize == y.intsize)) return (x.number == y.number); unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; FixedPoint x1(ismax, dsmax, x); FixedPoint y1(ismax, dsmax, y); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_eq++; return (x1.number == y1.number); } bool operator != (const FixedPoint &x, const FixedPoint &y) { if ((x.decsize == y.decsize) && (x.intsize == y.intsize)) return (x.number != y.number); unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; FixedPoint x1(ismax, dsmax, x); FixedPoint y1(ismax, dsmax, y); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_neq++; return (x1.number != y1.number); } bool operator > (const FixedPoint &x, const FixedPoint &y) { FixedPoint x1, y1; if ((x.decsize != y.decsize) || (x.intsize != y.intsize)) { unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; x1 = FixedPoint(ismax, dsmax, x); y1 = FixedPoint(ismax, dsmax, y); } else { x1 = x; y1 = y; } char x1_sign = x1.signbit(); char y1_sign = y1.signbit(); if (x1_sign == y1_sign) return (x1.number > y1.number); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_gt++; return (x1_sign == 0); } bool operator >= (const FixedPoint &x, const FixedPoint &y) { FixedPoint x1, y1; if ((x.decsize != y.decsize) || (x.intsize != y.intsize)) { unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; x1 = FixedPoint(ismax, dsmax, x); y1 = FixedPoint(ismax, dsmax, y); } else { x1 = x; y1 = y; } char x1_sign = x1.signbit(); char y1_sign = y1.signbit(); if (x1_sign == y1_sign) return (x1.number >= y1.number); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_ge++; return (x1_sign == 0); } bool operator < (const FixedPoint &x, const FixedPoint &y) { FixedPoint x1, y1; if ((x.decsize != y.decsize) || (x.intsize != y.intsize)) { unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; x1 = FixedPoint(ismax, dsmax, x); y1 = FixedPoint(ismax, dsmax, y); } else { x1 = x; y1 = y; } char x1_sign = x1.signbit(); char y1_sign = y1.signbit(); if (x1_sign == y1_sign) return (x1.number < y1.number); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_lt++; return (x1_sign != 0); } bool operator <= (const FixedPoint &x, const FixedPoint &y) { FixedPoint x1, y1; if ((x.decsize != y.decsize) || (x.intsize != y.intsize)) { unsigned int dsmax = (x.decsize > y.decsize) ? x.decsize : y.decsize; unsigned int ismax = (x.intsize > y.intsize) ? x.intsize : y.intsize; x1 = FixedPoint(ismax, dsmax, x); y1 = FixedPoint(ismax, dsmax, y); } else { x1 = x; y1 = y; } char x1_sign = x1.signbit(); char y1_sign = y1.signbit(); if (x1_sign == y1_sign) return (x1.number <= y1.number); if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_le++; return (x1_sign != 0); } /* FixedPoint shifting functions */ FixedPoint rshift(const FixedPoint &x, int s) { FixedPoint t(x); while (s--) { t.decsize++; if (t.intsize) t.intsize--; } if (t.decsize+t.intsize > maxfixedsize) fixed_error (Fixed::WRONGFIXSIZE); return t; } FixedPoint lshift(const FixedPoint &x, int s) { FixedPoint t(x); while (s--) { t.intsize++; if (t.decsize) t.decsize--; } if (t.decsize+t.intsize > maxfixedsize) fixed_error (Fixed::WRONGFIXSIZE); return t; } /* These are to simplify things for Octave */ FixedPoint real (const FixedPoint &x) { return x; } FixedPoint imag (const FixedPoint &x) { return FixedPoint(x.intsize, x.decsize); } FixedPoint conj (const FixedPoint &x) { return x; } /* FixedPoint mathematic functions */ FixedPoint abs (const FixedPoint &x) { if (x.signbit()) { FixedPoint t(x); t.number = (-x.number)&x.filter; if (Fixed::FP_Debug) t.value = -x.value; if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_neg++; return (t); } return (x); } #define FRIEND_FIXEDPOINT_MFUNC(FUNC) \ FixedPoint FUNC (const FixedPoint &x) \ { \ if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_##FUNC++; \ return (FixedPoint(x.intsize, x.decsize, FUNC(x.fixedpoint()))); \ } #define FRIEND_FIXEDPOINT_MFUNC_LOWER(FUNC, lower) \ FixedPoint FUNC (const FixedPoint &x) \ { \ double value = x.fixedpoint(); \ if (value < lower) \ { fixed_error (Fixed::BADMATH); return FixedPoint(); } \ if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_##FUNC++; \ return FixedPoint(x.intsize, x.decsize, FUNC(value)); \ } #define FRIEND_FIXEDPOINT_MFUNC_UPPER(FUNC, upper) \ FixedPoint FUNC (const FixedPoint &x) \ { \ double value = x.fixedpoint(); \ if (value > upper) \ { fixed_error (Fixed::BADMATH); return FixedPoint(); } \ if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_##FUNC++; \ return FixedPoint(x.intsize, x.decsize, FUNC(value)); \ } #define FRIEND_FIXEDPOINT_MFUNC_RANGE(FUNC, upper, lower) \ FixedPoint FUNC (const FixedPoint &x) \ { \ double value = x.fixedpoint(); \ if ((value < lower) || (value > upper)) \ { fixed_error (Fixed::BADMATH); return FixedPoint(); } \ if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_##FUNC++; \ return FixedPoint(x.intsize, x.decsize, FUNC(value)); \ } FRIEND_FIXEDPOINT_MFUNC (cos); FRIEND_FIXEDPOINT_MFUNC (cosh); FRIEND_FIXEDPOINT_MFUNC (sin); FRIEND_FIXEDPOINT_MFUNC (sinh); FRIEND_FIXEDPOINT_MFUNC (tan); FRIEND_FIXEDPOINT_MFUNC (tanh); FRIEND_FIXEDPOINT_MFUNC_LOWER (sqrt,0.); #define FRIEND_FIXEDPOINT_POW(TYPE) \ FixedPoint pow (const FixedPoint &x, const TYPE y) \ { \ if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_pow++; \ return (FixedPoint(x.intsize, x.decsize, std::pow(x.fixedpoint(), y))); \ } FRIEND_FIXEDPOINT_POW (int); FRIEND_FIXEDPOINT_POW (double); FixedPoint pow (const FixedPoint &x, const FixedPoint &y) { if (Fixed::FP_CountOperations) \ Fixed::FP_Operations.nb_pow++; return (FixedPoint(x.intsize, x.decsize, pow(x.fixedpoint(), y.fixedpoint()))); } FRIEND_FIXEDPOINT_MFUNC (exp); FRIEND_FIXEDPOINT_MFUNC_LOWER (log,0.); FRIEND_FIXEDPOINT_MFUNC_LOWER (log10,0.); FixedPoint atan2 (const FixedPoint &x, const FixedPoint &y) { if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_atan2++; return (FixedPoint(x.intsize, x.decsize, atan2(x.fixedpoint(), y.fixedpoint()))); } FixedPoint round (const FixedPoint &x) { if (Fixed::FP_CountOperations) Fixed::FP_Operations.nb_round++; return (FixedPoint(x.intsize, x.decsize, floor(x.fixedpoint() + 0.5))); } FRIEND_FIXEDPOINT_MFUNC (rint); FRIEND_FIXEDPOINT_MFUNC (floor); FRIEND_FIXEDPOINT_MFUNC (ceil); std::istream &operator >> (std::istream &is, FixedPoint &x) { double d; is >> d; FixedPoint z(x.intsize, x.decsize, d); x.number = z.number; if (Fixed::FP_Debug) x.value = x.fixedpoint(); return (is); } std::ostream &operator << (std::ostream &os, const FixedPoint &x) { /* Extract number without sign. */ fp_uint num = (x.signbit()) ? (-x.number)&x.filter : x.number; /* Extract integer and decimal part. */ fp_uint i = num >> x.decsize; fp_uint d = (num & ((x.filter >> (x.intsize+1)) & x.filter)); /* Print sign. */ if (x.signbit()) os << "-"; /* Print integer part. */ os << i; /* Process decimal part. */ if (x.decsize) { /* Print decimal dot. */ os << "."; /* Table of 5 power from 0 to bit number of "fp_uint" */ const int nb_digits = SIZEOF_FIXED * 8; const int nb_digits_1 = nb_digits-1; /* Create decimal part as a string and compute its length. */ char dec[nb_digits]; int dec_len = 0; while (d > 0) { dec[nb_digits_1-dec_len] = d%10; dec_len++; d /= 10; } /* Create and initialize result string. */ char res[nb_digits]; for (int k=0; k<nb_digits; k++) res[k] = 0; /* Multiply 5^x.decsize by decimal part. */ for (int k=0; k<nb_digits; k++) { int val = pow5[x.decsize][nb_digits_1-k]; for (int l=0; l<dec_len; l++) { int digit = l + k; int tmp = (res[nb_digits_1-digit]) + (dec[nb_digits_1-l])*val; while (tmp > 0) { res[nb_digits_1-digit] = (tmp%10); digit++; tmp /= 10; tmp += (res[nb_digits_1-digit]); } } } for (int k=nb_digits-x.decsize; k<nb_digits;k++) os << char(res[k]+'0'); } return (os); } std::string getbitstring (const FixedPoint &x) { int l = x.intsize+x.decsize+1; fp_uint nb = x.number; std::string st(l, ' '); for (int i=1; i<=l; i++) { st[l-i] = '0'+ (nb&1); nb >>= 1; } return (st); } // FixedPoint operation summary FixedPointOperation::FixedPointOperation() : nb_add(0), nb_sub(0), nb_mult(0), nb_div(0), nb_lshift(0), nb_rshift(0), nb_inc(0), nb_dec(0), nb_neg(0), nb_comp(0), nb_eq(0), nb_neq(0), nb_gt(0), nb_ge(0), nb_lt(0), nb_le(0), nb_cos(0), nb_cosh(0), nb_sin(0), nb_sinh(0), nb_tan(0), nb_tanh(0), nb_sqrt(0), nb_pow(0), nb_exp(0), nb_log(0), nb_log10(0), nb_atan2(0), nb_round(0), nb_rint(0), nb_floor(0), nb_ceil(0) {} void FixedPointOperation::reset () { nb_add = nb_sub = nb_mult = nb_div = 0; nb_lshift = nb_rshift = 0; nb_inc = nb_dec = 0; nb_neg = nb_comp = 0; nb_eq = nb_neq = nb_gt = nb_ge = nb_lt = nb_le = 0; nb_cos = nb_cosh = nb_sin = nb_sinh = nb_tan = nb_tanh = 0; nb_sqrt = nb_pow = nb_exp = nb_log = nb_log10 = 0; nb_atan2 = 0; nb_round = nb_rint = nb_floor = nb_ceil = 0; } std::ostream &operator << (std::ostream &os, const FixedPointOperation &x) { os << "Summary of FixedPoint operations" << std::endl; os << "================================" << std::endl; os << "Number of additions: " << x.nb_add << std::endl; os << "Number of subtractions: " << x.nb_sub << std::endl; os << "Number of multiplications: " << x.nb_mult << std::endl; os << "Number of divisions: " << x.nb_div << std::endl; os << std::endl; os << "Number of left shifts: " << x.nb_lshift << std::endl; os << "Number of right shifts: " << x.nb_rshift << std::endl; os << std::endl; os << "Number of increments: " << x.nb_inc << std::endl; os << "Number of decrements: " << x.nb_dec << std::endl; os << std::endl; os << "Number of negations: " << x.nb_neg << std::endl; os << "Number of bitwise not: " << x.nb_comp << std::endl; os << std::endl; os << "Number of equalities: " << x.nb_eq << std::endl; os << "Number of inequalities: " << x.nb_neq << std::endl; os << "Number of greater than: " << x.nb_gt << std::endl; os << "Number of greater than or equal to: " << x.nb_ge << std::endl; os << "Number of less than: " << x.nb_lt << std::endl; os << "Number of less than or equal to: " << x.nb_le << std::endl; os << std::endl; os << "Number of cosine calculations: " << x.nb_cos << std::endl; os << "Number of hyperbolic cosine calculations: " << x.nb_cosh << std::endl; os << "Number of sine calculations: " << x.nb_sin << std::endl; os << "Number of hyperbolic sine calculations: " << x.nb_sinh << std::endl; os << "Number of tangent calculations: " << x.nb_tan << std::endl; os << "Number of hyperbolic tangent calculations: " << x.nb_tanh << std::endl; os << std::endl; os << "Number of square roots: " << x.nb_sqrt << std::endl; os << "Number of power calculations: " << x.nb_pow << std::endl; os << "Number of exponentials: " << x.nb_exp << std::endl; os << "Number of logarithms: " << x.nb_log << std::endl; os << "Number of base 10 logarithms: " << x.nb_log10 << std::endl; os << std::endl; os << "Number of arc-tangent calculations: " << x.nb_atan2 << std::endl; os << std::endl; os << "Number of round operations: " << x.nb_round << std::endl; os << "Number of rint operations: " << x.nb_rint << std::endl; os << "Number of floor operations: " << x.nb_floor << std::endl; os << "Number of ceil operations: " << x.nb_ceil << std::endl; os << std::endl; return os; } #endif /* ;;; Local Variables: *** ;;; mode: C++ *** ;;; End: *** */