File indexing completed on 2024-05-12 17:22:35

0001 /* floatlogic.c: logic functions, based on floatnum. */
0002 /*
0003     Copyright (C) 2007, 2008 Wolf Lammen.
0004 
0005     This program is free software; you can redistribute it and/or modify
0006     it under the terms of the GNU General Public License as published by
0007     the Free Software Foundation; either version 2 of the License , or
0008     (at your option) any later version.
0009 
0010     This program is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013     GNU General Public License for more details.
0014 
0015     You should have received a copy of the GNU General Public License
0016     along with this program; see the file COPYING.  If not, write to:
0017 
0018       The Free Software Foundation, Inc.
0019       59 Temple Place, Suite 330
0020       Boston, MA 02111-1307 USA.
0021 
0022 
0023     You may contact the author by:
0024        e-mail:  ookami1 <at> gmx <dot> de
0025        mail:  Wolf Lammen
0026               Oertzweg 45
0027               22307 Hamburg
0028               Germany
0029 
0030 *************************************************************************/
0031 
0032 #include "floatlogic.h"
0033 #include "floatconst.h"
0034 
0035 #define MAXIDX ((LOGICRANGE-1) / BITS_IN_UNSIGNED)
0036 #define SIGNBIT (LOGICRANGE - 1 - MAXIDX * BITS_IN_UNSIGNED)
0037 
0038 static void
0039 _zeroextend(
0040   t_longint* longint)
0041 {
0042   int idx;
0043 
0044   idx = longint->length - 1;
0045   for (; ++idx <= (int)MAXIDX;)
0046     longint->value[idx] = 0;
0047 }
0048 
0049 signed char
0050 _signof(
0051   t_longint* longint)
0052 {
0053   return (longint->value[MAXIDX] & (1 << SIGNBIT)) != 0? -1:1;
0054 }
0055 
0056 static char
0057 _signextend(
0058   t_longint* longint)
0059 {
0060   unsigned mask;
0061   signed char sign;
0062 
0063   sign = _signof(longint);
0064   mask = (unsigned)(~0) << SIGNBIT;
0065   if (sign < 0)
0066     longint->value[MAXIDX] |= mask;
0067   else
0068     longint->value[MAXIDX] &= ~mask;
0069   return sign;
0070 }
0071 
0072 static void
0073 _neg(
0074   t_longint* longint)
0075 {
0076   int idx = -1;
0077   const int maxidx = MAXIDX;
0078   while (++idx <= maxidx && longint->value[idx] == 0);
0079   if (idx <= maxidx)
0080     longint->value[idx] = - longint->value[idx];
0081   while (++idx <= maxidx)
0082     longint->value[idx] = ~longint->value[idx];
0083 }
0084 
0085 char
0086 _floatnum2logic(
0087   t_longint* longint,
0088   cfloatnum x)
0089 {
0090   floatstruct tmp;
0091   int digits;
0092 
0093   digits = float_getexponent(x)+1;
0094   if (float_iszero(x) || digits <= 0)
0095   {
0096     longint->length = 1;
0097     longint->value[0] = 0;
0098   }
0099   else
0100   {
0101     if (digits > MATHPRECISION)
0102       return 0;
0103 
0104     float_create(&tmp);
0105     /* floatnum2longint rounds, we have to truncate first */
0106     float_copy(&tmp, x, digits);
0107     if (float_getsign(x) < 0)
0108       float_add(&tmp, &tmp, &c1, EXACT);
0109     _floatnum2longint(longint, &tmp);
0110     float_free(&tmp);
0111     if (_bitlength(longint) > LOGICRANGE)
0112       return 0;
0113   }
0114   _zeroextend(longint);
0115   if (float_getsign(x) < 0)
0116     _not(longint);
0117   return 1;
0118 }
0119 
0120 void
0121 _logic2floatnum(
0122   floatnum f,
0123   t_longint* longint)
0124 {
0125   int idx;
0126   signed char sign;
0127 
0128   sign = _signextend(longint);
0129   if (sign < 0)
0130     _neg(longint);
0131   idx = MAXIDX;
0132   while (idx >= 0 && longint->value[idx] == 0)
0133     --idx;
0134   if (idx < 0)
0135     longint->length = 0;
0136   else
0137     longint->length = idx + 1;
0138   _longint2floatnum(f, longint);
0139   float_setsign(f, sign);
0140 }
0141 
0142 void
0143 _not(
0144   t_longint* longint)
0145 {
0146   int idx;
0147 
0148   for (idx = -1; ++idx <= (int)MAXIDX;)
0149     longint->value[idx] = ~(longint->value[idx]);
0150 }
0151 
0152 void
0153 _and(
0154   t_longint* x1,
0155   t_longint* x2)
0156 {
0157   int idx;
0158 
0159   for (idx = -1; ++idx <= (int)MAXIDX;)
0160     x1->value[idx] = x1->value[idx] & x2->value[idx];
0161 }
0162 
0163 void
0164 _or(
0165   t_longint* x1,
0166   t_longint* x2)
0167 {
0168   int idx;
0169 
0170   for (idx = -1; ++idx <= (int)MAXIDX;)
0171     x1->value[idx] = x1->value[idx] | x2->value[idx];
0172 }
0173 
0174 void
0175 _xor(
0176   t_longint* x1,
0177   t_longint* x2)
0178 {
0179   int idx;
0180 
0181   for (idx = -1; ++idx <= (int)MAXIDX;)
0182     x1->value[idx] = x1->value[idx] ^ x2->value[idx];
0183 }
0184 
0185 void
0186 _shr(
0187   t_longint* x,
0188   unsigned shift)
0189 {
0190   int idx;
0191   const unsigned sign = _signof(x) < 0? ~0 : 0;
0192   const int moves = shift/BITS_IN_UNSIGNED;
0193   const int maxidx = MAXIDX;
0194 
0195   if (moves > 0)
0196   {
0197     shift -= moves * BITS_IN_UNSIGNED;
0198     for (idx = moves-1; ++idx <= maxidx;)
0199       x->value[idx-moves] = x->value[idx];
0200     idx = MAXIDX - moves + 1;
0201     if (idx < 0)
0202       idx = 0;
0203     for (; idx <= maxidx; ++idx)
0204       x->value[idx] = sign;
0205   }
0206   if (shift > 0)
0207   {
0208     for (idx = -1; ++idx < maxidx;)
0209       x->value[idx] = _longshr(x->value[idx], x->value[idx+1], shift);
0210     x->value[MAXIDX] = _longshr(x->value[MAXIDX], sign, shift);
0211   }
0212 }
0213 
0214 void
0215 _shl(
0216   t_longint* x,
0217   unsigned shift)
0218 {
0219   int moves, idx;
0220 
0221   moves = shift/BITS_IN_UNSIGNED;
0222   if (moves > 0)
0223   {
0224     shift -= moves * BITS_IN_UNSIGNED;
0225     for (idx = MAXIDX; idx >= moves; --idx)
0226       x->value[idx] = x->value[idx-moves];
0227     if (moves > (int)MAXIDX)
0228       moves = MAXIDX+1;
0229     for (idx = -1; ++idx < moves;)
0230       x->value[idx] = 0;
0231   }
0232   if (shift > 0)
0233   {
0234     for (idx = MAXIDX; idx > 0; --idx)
0235       x->value[idx] = _longshl(x->value[idx-1], x->value[idx], shift);
0236     x->value[0] <<= shift;
0237   }
0238 }