summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mixlib/mix_types.c165
1 files changed, 83 insertions, 82 deletions
diff --git a/mixlib/mix_types.c b/mixlib/mix_types.c
index 3c1cbb8..7f523f3 100644
--- a/mixlib/mix_types.c
+++ b/mixlib/mix_types.c
@@ -1,35 +1,36 @@
/* -*-c-*- ------------------ mix_types.c :
* Implementation file for mix_types.h declarations.
* ------------------------------------------------------------------
- * $Id: mix_types.c,v 1.2 2002/04/09 23:53:52 jao Exp $
+ * $Id: mix_types.c,v 1.3 2004/06/07 00:01:03 jao Exp $
* ------------------------------------------------------------------
- * Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
- *
+ * Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+ *
* 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 of the License, 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
*/
#include "mix.h"
#include <limits.h>
+#include <ctype.h>
#include "mix_types.h"
/*------------------------ initialisation stuff ------------------------*/
/* flag telling whether a field spec is valid */
static gboolean is_bad_field_[MIX_BYTE_MAX + 1];
-/* shift associated with a fspec */
+/* shift associated with a fspec */
static guint shift_[MIX_BYTE_MAX + 1];
/* mask associated with a fspec */
static glong mask_[MIX_BYTE_MAX + 1];
@@ -52,18 +53,18 @@ mix_init_types (void)
{
guint lt, rt;
for (lt = 0; lt < 8; ++lt)
- for (rt = 0; rt < 8; ++rt)
+ for (rt = 0; rt < 8; ++rt)
{
guint F = 8 * lt + rt;
is_bad_field_[F] = rt < lt || 5 < rt;
if ( is_bad_field_[F] )
shift_[F] = 0, mask_[F] = 0;
- else
+ else
{
guint width = rt - (lt == 0 ? 1 : lt) + 1;
shift_[F] = 6 * (5 - rt);
mask_[F] = ((1L << (6 * width)) - 1) << shift_[F];
- }
+ }
}
for ( lt = 0; lt < UCHAR_MAX + 1; ++lt )
@@ -75,7 +76,7 @@ mix_init_types (void)
mix_char_t
mix_ascii_to_char (guchar c)
{
- return ascii_to_mix_char_[c];
+ return ascii_to_mix_char_[toupper (c)];
}
@@ -94,10 +95,10 @@ mix_bytes_to_word (mix_byte_t *bytes, guint byteno)
{
mix_word_t result = 0;
guint k;
-
+
g_return_val_if_fail (bytes != NULL, MIX_WORD_ZERO);
g_return_val_if_fail (byteno != 0, MIX_WORD_ZERO);
-
+
if ( byteno > 5 ) byteno = 5;
for ( k = 0; k < byteno; k++ )
result |= ((gulong)bytes[k]) << (6*(byteno-k-1));
@@ -113,7 +114,7 @@ mix_word_get_field (mix_fspec_t f, mix_word_t word)
mix_word_t result;
g_return_val_if_fail (!is_bad_field_[f],MIX_WORD_ZERO);
-
+
result = ( (word & mask_[f]) >> shift_[f] );
if (f < 8) /* if f is of the form (0:R), retain the sign of word */
result |= mix_word_sign (word);
@@ -129,13 +130,13 @@ mix_word_set_field (mix_fspec_t f, mix_word_t from, mix_word_t to)
glong m = mask_[f];
g_return_val_if_fail (!is_bad_field_[f],to);
-
+
if (f < 8) /* if F is of the form (0:R), use the sign of -from- */
- result = (to & ~m & ~MIX_WORD_SIGN_BIT)
+ result = (to & ~m & ~MIX_WORD_SIGN_BIT)
| ((from /*<< shift_[f]*/) & m) | mix_word_sign (from);
else
result = (to & ~m) | ((from /*<< shift_[f]*/) & m);
-
+
return result;
}
@@ -146,16 +147,16 @@ mix_word_store_field (mix_fspec_t f, mix_word_t from, mix_word_t to)
glong m = mask_[f];
g_return_val_if_fail (!is_bad_field_[f],to);
-
+
if (f < 8) /* if F is of the form (0:R), use the sign of -from- */
- result = (to & ~m & ~MIX_WORD_SIGN_BIT)
+ result = (to & ~m & ~MIX_WORD_SIGN_BIT)
| ((from << shift_[f]) & m) | mix_word_sign (from);
else
result = (to & ~m) | ((from << shift_[f]) & m);
-
+
return result;
}
-
+
gboolean
@@ -164,19 +165,19 @@ mix_fspec_is_valid (mix_fspec_t f)
return !(is_bad_field_[f]);
}
-mix_byte_t
-mix_word_get_byte (mix_word_t word, /* word parsed */
+mix_byte_t
+mix_word_get_byte (mix_word_t word, /* word parsed */
guint idx /* byte: 1 to 5 */ )
{
mix_byte_t fspec = mix_fspec_new (idx,idx);
g_return_val_if_fail ((idx > 0 && idx < 6), MIX_BYTE_ZERO);
-
+
return mix_byte_new (mix_word_get_field (fspec,word));
}
-extern void
+extern void
mix_word_set_byte (mix_word_t *into, guint idx, mix_byte_t value)
{
mix_word_t from = value;
@@ -184,17 +185,17 @@ mix_word_set_byte (mix_word_t *into, guint idx, mix_byte_t value)
g_return_if_fail (into != NULL);
g_return_if_fail (idx > 0 && idx < 6);
-
+
from <<= shift_[fspec];
*into = mix_word_set_field (fspec,from,*into);
}
/* Arithmetic operations */
-mix_word_t
+mix_word_t
mix_word_add (mix_word_t x, mix_word_t y)
{
static const gulong MIX_WORD_MAX_SIM = 2*MIX_WORD_MAX + 1;
-
+
gint32 result;
if ( mix_word_sign (x) == mix_word_sign (y) )
{
@@ -203,7 +204,7 @@ mix_word_add (mix_word_t x, mix_word_t y)
/* for instance MIX_WORD_MAX + 1 = - MIX_WORD_MAX */
result = MIX_WORD_MAX_SIM - result;
result |= mix_word_sign (mix_word_negative (x));
- } else if ( result != 0 )
+ } else if ( result != 0 )
result |= mix_word_sign (x);
/* keep positive sign for 0 so that w - w == -w + w */
}
@@ -216,9 +217,9 @@ mix_word_add (mix_word_t x, mix_word_t y)
result = result|mix_word_sign (x);
/* keep positive sign for 0 so that w - w == -w + w */
}
-
+
g_assert ( result >= 0 );
-
+
return (mix_word_t)result;
}
@@ -227,29 +228,29 @@ mix_word_add_and_carry (mix_word_t x, mix_word_t y,
mix_word_t *h, mix_word_t *l)
{
gboolean result;
-
+
if ( mix_word_sign (x) == mix_word_sign (y) )
{
guint32 sum = (mix_word_magnitude (x) + mix_word_magnitude (y));
- if ( sum > MIX_WORD_MAX )
+ if ( sum > MIX_WORD_MAX )
{
result = TRUE;
- if ( l != NULL )
+ if ( l != NULL )
{
*l = sum - MIX_WORD_MAX -1;
*l |= mix_word_sign (x);
}
- if ( h != NULL )
+ if ( h != NULL )
{
*h = sum >> 30;
*h |= mix_word_sign (x);
}
- }
+ }
else /* sum <= MIX_WORD_MAX */
{
result = FALSE;
if ( h != NULL ) *h = 0;
- if ( l != NULL )
+ if ( l != NULL )
{
*l = sum;
if ( sum != 0 )
@@ -262,7 +263,7 @@ mix_word_add_and_carry (mix_word_t x, mix_word_t y,
{
result = FALSE;
if ( h != NULL ) *h = 0;
- if ( l != NULL )
+ if ( l != NULL )
{
gint32 dif = mix_word_magnitude (x) - mix_word_magnitude (y);
if ( dif < 0)
@@ -273,17 +274,17 @@ mix_word_add_and_carry (mix_word_t x, mix_word_t y,
*l = MIX_WORD_ZERO;
}
}
-
+
return result;
}
-
-void
-mix_word_mul (mix_word_t x, mix_word_t y,
+
+void
+mix_word_mul (mix_word_t x, mix_word_t y,
mix_word_t *high_word, mix_word_t *low_word)
{
guint32 sign = mix_word_sign (x) ^ mix_word_sign (y);
-
+
/*
x = x0 + x1 * 2 ^ 10 + x2 * 2 ^ 20
y = y0 + y1 * 2 ^ 10 + y2 * 2 ^ 20
@@ -295,7 +296,7 @@ mix_word_mul (mix_word_t x, mix_word_t y,
guint32 y0 = (y & 0x000003FF);
guint32 y1 = (y & 0x000FFC00) >> 10;
guint32 y2 = (y & 0x3FF00000) >> 20;
-
+
/*
x * y = partial0 +
partial1 * 2 ^ 10 +
@@ -311,21 +312,21 @@ mix_word_mul (mix_word_t x, mix_word_t y,
guint32 partial2 = x0 * y2 + x1 * y1 + x2 * y0;
guint32 partial3 = x1 * y2 + x2 * y1;
guint32 partial4 = x2 * y2;
-
+
/* sum1 has a place value of 1 and is < 2 ^ 32 */
guint32 sum1 = partial0 + (partial1 << 10);
guint32 carry1 = (sum1 & 0xFFF00000) >> 20;
-
+
/* sum2 has a place value of 2 ^ 20 and is < 2 ^ 32 */
guint32 sum2 = partial2 + (partial3 << 10) + carry1;
guint32 carry2 = (sum2 & 0xFFF00000) >> 20;
-
+
/* sum3 has a place value of 2 ^ 40 and is < 2 ^ 20 */
guint32 sum3 = partial4 + carry2;
-
+
sum1 &= ~0xFFF00000;
sum2 &= ~0xFFF00000;
-
+
/*
Now paste the three values back into two.
*/
@@ -340,36 +341,36 @@ mix_word_mul (mix_word_t x, mix_word_t y,
}
-gboolean
-mix_word_div (mix_word_t n1, mix_word_t n0, mix_word_t d,
+gboolean
+mix_word_div (mix_word_t n1, mix_word_t n0, mix_word_t d,
mix_word_t *quotient, mix_word_t *remainder)
{
- gboolean overflow = FALSE;
+ gboolean overflow = FALSE;
long magn1 = mix_word_magnitude (n1);
long magd = mix_word_magnitude (d);
-
- if (magd == 0)
+
+ if (magd == 0)
{
overflow = TRUE;
/* just so they have -some- valid value */
if ( quotient != NULL ) *quotient = 0;
- if ( remainder != NULL ) *remainder = 0;
- }
- else if (magn1 == 0)
+ if ( remainder != NULL ) *remainder = 0;
+ }
+ else if (magn1 == 0)
{ /* special-cased for speed */
- if ( quotient != NULL )
- *quotient = (mix_word_sign (n1) ^ mix_word_sign (d))
+ if ( quotient != NULL )
+ *quotient = (mix_word_sign (n1) ^ mix_word_sign (d))
| (mix_word_magnitude (n0) / magd);
if ( remainder != NULL )
*remainder = mix_word_sign (n1) | (mix_word_magnitude (n0) % magd);
- }
- else if (magd <= magn1)
+ }
+ else if (magd <= magn1)
{
overflow = TRUE;
if ( quotient != NULL ) *quotient = 0;
if ( remainder != NULL ) *remainder = 0;
- }
- else
+ }
+ else
{
long q = mix_word_magnitude (n0);
long r = magn1;
@@ -390,8 +391,8 @@ mix_word_div (mix_word_t n1, mix_word_t n0, mix_word_t d,
return overflow;
}
-void
-mix_word_shift_right (mix_word_t A, mix_word_t X, gulong count,
+void
+mix_word_shift_right (mix_word_t A, mix_word_t X, gulong count,
mix_word_t *pA, mix_word_t *pX)
{
if ( pX != NULL ) *pX = mix_word_sign (X);
@@ -400,7 +401,7 @@ mix_word_shift_right (mix_word_t A, mix_word_t X, gulong count,
if ( pA != NULL )
*pA |= mix_word_magnitude (A) >> (6 * count);
if ( pX != NULL )
- *pX |= MIX_WORD_MAX & ( (mix_word_magnitude (X) >> (6 * count))
+ *pX |= MIX_WORD_MAX & ( (mix_word_magnitude (X) >> (6 * count))
| (A << (30 - 6 * count)) );
} else if (count < 10 && pX != NULL)
*pX |= mix_word_magnitude (A) >> (6 * count - 30);
@@ -409,8 +410,8 @@ mix_word_shift_right (mix_word_t A, mix_word_t X, gulong count,
}
-void
-mix_word_shift_left (mix_word_t A, mix_word_t X, gulong count,
+void
+mix_word_shift_left (mix_word_t A, mix_word_t X, gulong count,
mix_word_t *pA, mix_word_t *pX)
{
if ( pX != NULL ) *pX = mix_word_sign (X);
@@ -426,13 +427,13 @@ mix_word_shift_left (mix_word_t A, mix_word_t X, gulong count,
;
}
-void
-mix_word_shift_left_circular (mix_word_t A, mix_word_t X, gulong count,
+void
+mix_word_shift_left_circular (mix_word_t A, mix_word_t X, gulong count,
mix_word_t *pA, mix_word_t *pX)
{
mix_word_t A1, X1;
guint c;
-
+
count %= 10;
A1 = count < 5 ? A : X;
X1 = count < 5 ? X : A;
@@ -445,13 +446,13 @@ mix_word_shift_left_circular (mix_word_t A, mix_word_t X, gulong count,
| ( MIX_WORD_MAX & (A1 << c) ) | ( mix_word_magnitude (X1) >> (30 - c) );
}
-void
-mix_word_shift_right_circular (mix_word_t A, mix_word_t X, gulong count,
+void
+mix_word_shift_right_circular (mix_word_t A, mix_word_t X, gulong count,
mix_word_t *pA, mix_word_t *pX)
{
mix_word_t A1, X1;
guint c;
-
+
count %= 10;
A1 = count < 5 ? A : X;
X1 = count < 5 ? X : A;
@@ -466,7 +467,7 @@ mix_word_shift_right_circular (mix_word_t A, mix_word_t X, gulong count,
/* Printable representation */
-void
+void
mix_word_print_to_file (mix_word_t word, const char *message, FILE *f)
{
guint k;
@@ -478,7 +479,7 @@ mix_word_print_to_file (mix_word_t word, const char *message, FILE *f)
fprintf (f, "(%010ld)", mix_word_magnitude (word));
}
-void
+void
mix_word_print_to_buffer (mix_word_t word, gchar *buf)
{
g_return_if_fail (buf != NULL);
@@ -495,7 +496,7 @@ mix_word_print_to_buffer (mix_word_t word, gchar *buf)
mix_short_t
mix_word_to_short (mix_word_t word)
{
- if ( mix_word_is_negative (word) )
+ if ( mix_word_is_negative (word) )
return ( (word & MIX_SHORT_MAX) | MIX_SHORT_SIGN_BIT );
else
return (word & MIX_SHORT_MAX);
@@ -510,11 +511,11 @@ mix_short_to_word (mix_short_t s)
return ((mix_word_t)s);
}
-mix_short_t
+mix_short_t
mix_short_add (mix_short_t x, mix_short_t y)
{
static const guint16 MIX_SHORT_MAX_SIM = 2*MIX_SHORT_MAX + 1;
-
+
gint16 result;
if ( mix_short_sign (x) == mix_short_sign (y) )
{
@@ -523,7 +524,7 @@ mix_short_add (mix_short_t x, mix_short_t y)
/* for instance MIX_SHORT_MAX + 1 = - MIX_SHORT_MAX */
result = MIX_SHORT_MAX_SIM - result;
result |= mix_short_sign (mix_short_negative (x));
- } else if ( result != 0 )
+ } else if ( result != 0 )
result |= mix_short_sign (x);
/* keep positive sign for 0 so that w - w == -w + w */
}
@@ -536,9 +537,9 @@ mix_short_add (mix_short_t x, mix_short_t y)
result = result|mix_short_sign (x);
/* keep positive sign for 0 so that w - w == -w + w */
}
-
+
g_assert ( result >= 0 );
-
+
return (mix_short_t)result;
}