diff options
-rw-r--r-- | mixlib/mix_types.c | 165 |
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; } |