4 * Copyright (c) 1997 Ben Harrison
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies.
11 /* Purpose: Low level utilities -BEN- */
17 * Convenient storage of the program name
23 * Determine if string "t" is equal to string "t"
25 bool streq(cptr a, cptr b)
27 return (!strcmp(a, b));
32 * Determine if string "t" is a suffix of string "s"
34 bool suffix(cptr s, cptr t)
39 /* Check for incompatible lengths */
40 if (tlen > slen) return (FALSE);
42 /* Compare "t" to the end of "s" */
43 return (!strcmp(s + slen - tlen, t));
48 * Determine if string "t" is a prefix of string "s"
50 bool prefix(cptr s, cptr t)
55 /* Compare content and length */
56 if (*t++ != *s++) return (FALSE);
59 /* Matched, we have a prefix */
66 * Redefinable "plog" action
68 void (*plog_aux)(cptr) = NULL;
71 * Print (or log) a "warning" message (ala "perror()")
72 * Note the use of the (optional) "plog_aux" hook.
76 /* Use the "alternative" function if possible */
77 if (plog_aux) (*plog_aux)(str);
79 /* Just do a labeled fprintf to stderr */
80 else (void)(fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "???", str));
86 * Redefinable "quit" action
88 void (*quit_aux)(cptr) = NULL;
91 * Exit (ala "exit()"). If 'str' is NULL, do "exit(0)".
92 * If 'str' begins with "+" or "-", do "exit(atoi(str))".
93 * Otherwise, plog() 'str' and exit with an error code of -1.
94 * But always use 'quit_aux', if set, before anything else.
98 /* Attempt to use the aux function */
99 if (quit_aux) (*quit_aux)(str);
102 if (!str) (void)(exit(0));
104 /* Extract a "special error code" */
105 if ((str[0] == '-') || (str[0] == '+')) (void)(exit(atoi(str)));
107 /* Send the string to plog() */
111 (void)(exit(EXIT_FAILURE));
117 * Redefinable "core" action
119 void (*core_aux)(cptr) = NULL;
122 * Dump a core file, after printing a warning message
123 * As with "quit()", try to use the "core_aux()" hook first.
129 /* Use the aux function */
130 if (core_aux) (*core_aux)(str);
132 /* Dump the warning string */
135 /* Attempt to Crash */
138 /* Be sure we exited */
139 quit("core() failed");
143 /*** 64-bit integer operations ***/
146 void s64b_add(s32b *A1, u32b *A2, s32b B1, u32b B2)
158 /* Subtract B from A */
159 void s64b_sub(s32b *A1, u32b *A2, s32b B1, u32b B2)
174 * (A1*2^32 + A2h*2^16 + A2l) * (B1*2^32 + B2h*2^16 + B2l)
175 * = (A1*B2 & 0xffffffff)*2^32
176 * +(A2*B1 & 0xffffffff)*2^32
177 * +(A2h*B2h & 0xffffffff)*2^32
178 * +(A2h*B2l & 0xffff0000)*2^16
179 * +(A2l*B2h & 0xffff0000)*2^16
180 * +(A2*B2 & 0xffffffff)
182 void s64b_mul(s32b *A1, u32b *A2, s32b B1, u32b B2)
187 u32b B2high = (B2 >> 16);
188 u32b A2high = (A2val >> 16);
193 tmp1 += A2high * B2high;
194 tmp1 += (A2high * (u16b)B2) >> 16;
195 tmp1 += ((u16b)A2val * B2high) >> 16;
202 int s64b_cmp(s32b A1, u32b A2, s32b B1, u32b B2)
204 if (A1 > B1) return 1;
205 if (A1 < B1) return -1;
206 if (A2 > B2) return 1;
207 if (A2 < B2) return -1;
214 * Assumes that both A and B are positive
216 void s64b_div(s32b *A1, u32b *A2, s32b B1, u32b B2)
224 /* No result for B==0 */
225 if (B1 == 0 && B2 == 0) return;
228 * Find the highest bit of quotient
230 while (s64b_cmp(A1val, A2val, B1, B2) == 1)
232 s64b_LSHIFT(B1, B2, 1);
236 /* Extract bits of quotient one by one */
239 if (s64b_cmp(A1val, A2val, B1, B2) >= 0)
242 result1 |= (0x00000001L << (bit - 32));
244 result2 |= (0x00000001L << bit);
246 s64b_sub(&A1val, &A2val, B1, B2);
249 s64b_RSHIFT(B1, B2, 1);
258 /* Reminder of division (A % B) */
259 void s64b_mod(s32b *A1, u32b *A2, s32b B1, u32b B2)
264 s64b_div(&tmp1, &tmp2, B1, B2);
265 s64b_mul(&tmp1, &tmp2, B1, B2);
266 s64b_sub(A1, A2, tmp1, tmp2);
270 * @brief 符号なし32ビット整数のビット数を返す。
271 * @param x ビット数を調べたい変数
274 int count_bits(BIT_FLAGS x)
281 } while (0 != (x = x&(x - 1)));
287 * @brief 平方根を切り捨て整数で返す