1 /* -*-c-*- --------------- mix_types.h:
2  *  This file contains declarations for the basic types used in MIX:
3  *   mix_byte_t, mix_char_t, mix_short_t and mix_word_t.
4  * ------------------------------------------------------------------
5  * Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 
24 #ifndef MIX_TYPES_H
25 #define MIX_TYPES_H
26 
27 #include <stdio.h>
28 #include "mix.h"
29 
30 /* Initialisation function to be called before using the other
31  * functions in this file
32  */
33 extern void
34 mix_init_types(void);
35 
36 
37 /*----------------- m_byte_t --------------------------------------------*/
38 /* MIX byte type */
39 typedef guint8 mix_byte_t;
40 
41 /* Maximum value stored in an mix_byte_t */
42 #define MIX_BYTE_MAX ((1L << 6) - 1)
43 
44 /* Zero mix byte */
45 #define MIX_BYTE_ZERO  ((mix_byte_t)0)
46 
47 /* Create a mix_byte_t from any native type */
48 #define mix_byte_new(x) ((mix_byte_t)((x) & MIX_BYTE_MAX ))
49 
50 /* Operations */
51 /* Addition */
52 #define mix_byte_add(x,y) mix_byte_new((x) + (y))
53 /* Substraction */
54 #define mix_byte_sub(x,y) mix_byte_new((x) - (y))
55 /* Product */
56 #define mix_byte_mul(x,y) mix_byte_new((x) * (y))
57 /* Quotient */
58 #define mix_byte_div(x,y) mix_byte_new((x) / (y))
59 
60 
61 /*----------------- mix_char_t --------------------------------------------*/
62 /* MIX char type: chars are coded in MIX from 0 to MIX_CHAR_MAX */
63 typedef guint8 mix_char_t;
64 
65 #define MIX_CHAR_MAX 55
66 
67 /* Conversions for mix_char_t's */
68 #define mix_char_new(l) (((l) < MIX_CHAR_MAX )? (l) : MIX_CHAR_MAX)
69 #define mix_char_to_byte(mchar) mix_byte_new (mchar)
70 #define mix_byte_to_char(byte) mix_char_new (byte)
71 
72 extern mix_char_t
73 mix_ascii_to_char(guchar c);
74 
75 extern guchar
76 mix_char_to_ascii(mix_char_t c);
77 
78 
79 /*----------------- mix_word_t --------------------------------------------*/
80 /*
81  * Represented as a gint32 (glib ensures that this type has 32
82  * bits). Bit 30 is the sign, higher bits are 0,
83  * and bits 0-29 are the magnitude.
84  * Each MIX 'byte' is a 6-bit substring of the magnitude.
85  */
86 typedef guint32  mix_word_t;
87 
88 /* Maximum value stored in an mix_word_t */
89 #define MIX_WORD_MAX ((1L << 30) - 1)
90 /* Sign bit in a word */
91 #define MIX_WORD_SIGN_BIT    (1L << 30)
92 /* Zero mix word */
93 #define MIX_WORD_ZERO  ((mix_word_t)0)
94 /* Negative zero mix word */
95 #define MIX_WORD_MINUS_ZERO  (MIX_WORD_ZERO | MIX_WORD_SIGN_BIT)
96 
97 
98 /* Create a mix_word_t from any native type */
99 #define mix_word_new(x)						\
100 ( (x) < 0							\
101   ? ( MIX_WORD_SIGN_BIT | ((mix_word_t)(-(x)) & MIX_WORD_MAX) )	\
102   : ( (mix_word_t)(x) & MIX_WORD_MAX )				\
103 )
104 
105 /* Create a mix_word_t from individual bytes */
106 #define mix_word_new_b(b1,b2,b3,b4,b5)				\
107 ((mix_word_t)(mix_byte_new(b5) + (mix_byte_new(b4)<<6) +	\
108 	      (mix_byte_new(b3)<<12) + (mix_byte_new(b2)<<18) +	\
109 	      (mix_byte_new(b1)<<24)))
110 
111 /* Create a negative mix_word_t from individual bytes */
112 #define mix_word_new_bn(b1,b2,b3,b4,b5) \
113    mix_word_negative(mix_word_new_b(b1,b2,b3,b4,b5))
114 
115 /* Create mix_word_t from an array of mix_byte_t */
116 extern mix_word_t
117 mix_bytes_to_word(mix_byte_t *bytes, guint byteno);
118 
119 /* Access byte within a word */
120 extern mix_byte_t /* byte -idx- or MIX_BYTE_ZERO if -idx- out of range */
121 mix_word_get_byte(mix_word_t word,   /* word parsed */
122 		  guint idx          /* byte: 1 to 5 */);
123 
124 /* Set a byte  within a mix_word_t  */
125 extern void
126 mix_word_set_byte(mix_word_t *into,   /* word to be modified */
127 		  guint idx,          /* byte: 1 to 5 */
128 		  mix_byte_t value    /* byte's value */);
129 
130 
131 /* Operations */
132 /* Sign-related definitions */
133 #define mix_word_negative(word)      ( (word) ^ MIX_WORD_SIGN_BIT )
134 #define mix_word_reverse_sign(word)  ( word ^= MIX_WORD_SIGN_BIT )
135 #define mix_word_sign(word)          ( (word) & MIX_WORD_SIGN_BIT )
136 #define mix_word_magnitude(word)     ( (word) & (MIX_WORD_SIGN_BIT - 1) )
137 #define mix_word_is_positive(word)   ( mix_word_sign(word) == 0 )
138 #define mix_word_is_negative(word)   ( mix_word_sign(word) != 0 )
139 #define mix_word_is_even(word)       ( ((word) & 1) == 0 )
140 #define mix_word_is_odd(word)        ( ((word) & 1) == 1 )
141 
142 
143 /* Arithmetic operations */
144 extern mix_word_t
145 mix_word_add(mix_word_t x, mix_word_t y);
146 
147 #define mix_word_sub(x,y)    ( mix_word_add((x),mix_word_negative(y)) )
148 
149 /* Add two words filling a high word if needed.
150    -high_word- and/or -low_word- can be NULL.
151 */
152 extern gboolean /* TRUE if overflow */
153 mix_word_add_and_carry(mix_word_t x, mix_word_t y,
154 		       mix_word_t *high_word, mix_word_t *low_word);
155 
156 /* Product, stored in -high_word- and -low_word-, which
157    can be NULL.
158 */
159 extern void
160 mix_word_mul(mix_word_t x, mix_word_t y,
161 	     mix_word_t *high_word, mix_word_t *low_word);
162 
163 /* Division. -quotient- and/or -remainder- can be NULL. */
164 extern gboolean /* TRUE if overflow */
165 mix_word_div(mix_word_t n1, mix_word_t n0, mix_word_t d,
166 	     mix_word_t *quotient, mix_word_t *remainder);
167 
168 /* Shift operations */
169 extern void
170 mix_word_shift_left(mix_word_t A, mix_word_t X, gulong count,
171 		    mix_word_t *pA, mix_word_t *pX);
172 extern void
173 mix_word_shift_right(mix_word_t A, mix_word_t X, gulong count,
174 		     mix_word_t *pA, mix_word_t *pX);
175 extern void
176 mix_word_shift_left_circular(mix_word_t A, mix_word_t X, gulong count,
177 			     mix_word_t *pA, mix_word_t *pX);
178 extern void
179 mix_word_shift_right_circular(mix_word_t A, mix_word_t X, gulong count,
180                               mix_word_t *pA, mix_word_t *pX);
181 
182 extern void
183 mix_word_shift_left_binary(mix_word_t A, mix_word_t X, gulong count,
184                            mix_word_t *pA, mix_word_t *pX);
185 
186 extern void
187 mix_word_shift_right_binary(mix_word_t A, mix_word_t X, gulong count,
188                             mix_word_t *pA, mix_word_t *pX);
189 
190 /*
191  * Fields within a word: a word containing the (L:R)
192  * bytes of the original one. L and R (with 0 <= L <= R < 6)
193  * are specified by a mix_fspec_t F = 8*L + R.
194  */
195 typedef guint8 mix_fspec_t;
196 
197 #define mix_fspec_left(f) ( ((f)>>3) & 7 )
198 #define mix_fspec_right(f) ( (f) & 7 )
199 #define mix_fspec_new(L,R) ( mix_byte_new(8*(L) + (R)) )
200 
201 extern gboolean
202 mix_fspec_is_valid(mix_fspec_t f);
203 
204 extern mix_word_t /* the specified field or 0 if f is not valid */
205 mix_word_get_field(mix_fspec_t f, mix_word_t word);
206 
207 extern mix_word_t /* -to- with the field -f- from -from- or -to-
208 		     if -f- is not a valid fspec  */
209 mix_word_set_field(mix_fspec_t f, mix_word_t from, mix_word_t to);
210 
211 /* set field into a zero word */
212 #define mix_word_extract_field(fspec,from_word) \
213     mix_word_set_field(fspec,from_word,MIX_WORD_ZERO)
214 
215 /* Store operation: the no. of bytes determined by -f- is taken
216  * from the right of -from- and stored into -to- in the location
217  *  specified by -f-
218  */
219 extern mix_word_t
220 mix_word_store_field(mix_fspec_t f, mix_word_t from, mix_word_t to);
221 
222 
223 /* Printable representation */
224 #define mix_word_print(word,message) \
225   mix_word_print_to_file (word, message, stdout)
226 
227 extern void
228 mix_word_print_to_file (mix_word_t word, const char *message, FILE *f);
229 
230 extern void
231 mix_word_print_to_buffer (mix_word_t word, gchar *buf);
232 
233 
234 /*----------------- mix_short_t ------------------------------------------*/
235 typedef guint16 mix_short_t;
236 
237 #define MIX_SHORT_MAX  ((1L << 12) - 1)
238 #define MIX_SHORT_SIGN_BIT  ((mix_short_t)(1L << 12))
239 #define MIX_SHORT_ZERO ((mix_short_t)0)
240 #define MIX_SHORT_MINUS_ZERO (MIX_SHORT_ZERO | MIX_SHORT_SIGN_BIT)
241 
242 /* Sign-related definitions */
243 #define mix_short_negative(s)      ( (s) ^ MIX_SHORT_SIGN_BIT )
244 #define mix_short_sign(s)          ( (s) & MIX_SHORT_SIGN_BIT )
245 #define mix_short_magnitude(s)     	\
246    ( (s) & (MIX_SHORT_SIGN_BIT - 1) )
247 #define mix_short_is_positive(s)   ( mix_short_sign(s) == 0 )
248 #define mix_short_is_negative(s)   ( mix_short_sign(s) != 0 )
249 #define mix_short_reverse_sign(s)  ( (s) ^= MIX_SHORT_SIGN_BIT )
250 
251 /* create short from a long */
252 #define mix_short_new(val) \
253 	((val)>= 0 ? (val)&MIX_SHORT_MAX : mix_short_negative(-(val)))
254 
255 /* Create shorts from individual bytes */
256 #define mix_short_new_b(b1,b2) \
257 ((mix_short_t)((mix_byte_new(b1)<<6) + mix_byte_new(b2)))
258 
259 #define mix_short_new_bn(b1,b2) mix_short_negative(mix_short_new_b(b1,b2))
260 
261 /* Conversions between words and shorts. Arithmetic operations
262    on shorts are not provided but for addition: use words instead.
263 */
264 /* Make a short taking word's sign and its two least significant
265    bytes (bytes no. 4 and 5)
266 */
267 extern mix_short_t
268 mix_word_to_short(mix_word_t word);
269 
270 extern  mix_word_t
271 mix_short_to_word(mix_short_t s);
272 
273 /* fast conversion (these macros' argument are evaluated twice */
274 #define mix_word_to_short_fast(w)					\
275 ( mix_word_is_negative(w) ?						\
276   ((w) & MIX_SHORT_MAX)|MIX_SHORT_SIGN_BIT : (w)&MIX_SHORT_MAX )
277 
278 #define mix_short_to_word_fast(s)					     \
279 ( mix_short_is_negative(s) ?						     \
280 (mix_word_t) (mix_short_magnitude(s)|MIX_WORD_SIGN_BIT): (mix_word_t)(s) )
281 
282 
283 extern mix_short_t
284 mix_short_add(mix_short_t x, mix_short_t y);
285 
286 
287 /* printable representation */
288 extern void
289 mix_short_print(mix_short_t s, const gchar *message);
290 
291 extern void
292 mix_short_print_to_buffer (mix_short_t s, gchar *buf);
293 
294 
295 
296 #endif /* MIX_TYPES_H */
297 
298 
299 
300 
301