OSDN Git Service

v3.0.0 Alpha5 OSDN最終版
[hengband/hengband.git] / src / z-util.c
1 /* File: z-util.c */
2
3 /*
4  * Copyright (c) 1997 Ben Harrison
5  *
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.
9  */
10
11 /* Purpose: Low level utilities -BEN- */
12
13 #include "z-util.h"
14
15
16 /*
17  * Convenient storage of the program name
18  */
19 concptr argv0 = NULL;
20
21
22 /*
23  * Determine if string "t" is equal to string "t"
24  */
25 bool streq(concptr a, concptr b)
26 {
27         return (!strcmp(a, b));
28 }
29
30
31 /*
32  * Determine if string "t" is a suffix of string "s"
33  */
34 bool suffix(concptr s, concptr t)
35 {
36         int tlen = strlen(t);
37         int slen = strlen(s);
38
39         /* Check for incompatible lengths */
40         if (tlen > slen) return (FALSE);
41
42         /* Compare "t" to the end of "s" */
43         return (!strcmp(s + slen - tlen, t));
44 }
45
46
47 /*
48  * Determine if string "t" is a prefix of string "s"
49  */
50 bool prefix(concptr s, concptr t)
51 {
52         /* Scan "t" */
53         while (*t)
54         {
55                 /* Compare content and length */
56                 if (*t++ != *s++) return (FALSE);
57         }
58
59         /* Matched, we have a prefix */
60         return (TRUE);
61 }
62
63
64
65 /*
66  * Redefinable "plog" action
67  */
68 void (*plog_aux)(concptr) = NULL;
69
70 /*
71  * Print (or log) a "warning" message (ala "perror()")
72  * Note the use of the (optional) "plog_aux" hook.
73  */
74 void plog(concptr str)
75 {
76         /* Use the "alternative" function if possible */
77         if (plog_aux) (*plog_aux)(str);
78
79         /* Just do a labeled fprintf to stderr */
80         else (void)(fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "???", str));
81 }
82
83
84
85 /*
86  * Redefinable "quit" action
87  */
88 void (*quit_aux)(concptr) = NULL;
89
90 /*
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.
95  */
96 void quit(concptr str)
97 {
98         /* Attempt to use the aux function */
99         if (quit_aux) (*quit_aux)(str);
100
101         /* Success */
102         if (!str) (void)(exit(0));
103
104         /* Extract a "special error code" */
105         if ((str[0] == '-') || (str[0] == '+')) (void)(exit(atoi(str)));
106
107         /* Send the string to plog() */
108         plog(str);
109
110         /* Failure */
111         (void)(exit(EXIT_FAILURE));
112 }
113
114
115
116 /*
117  * Redefinable "core" action
118  */
119 void (*core_aux)(concptr) = NULL;
120
121 /*
122  * Dump a core file, after printing a warning message
123  * As with "quit()", try to use the "core_aux()" hook first.
124  */
125 void core(concptr str)
126 {
127         char *crash = NULL;
128
129         /* Use the aux function */
130         if (core_aux) (*core_aux)(str);
131
132         /* Dump the warning string */
133         if (str) plog(str);
134
135         /* Attempt to Crash */
136         (*crash) = (*crash);
137
138         /* Be sure we exited */
139         quit("core() failed");
140 }
141
142
143 /*** 64-bit integer operations ***/
144
145 /* Add B to A */
146 void s64b_add(s32b *A1, u32b *A2, s32b B1, u32b B2)
147 {
148         (*A2) += B2;
149
150         /* Overflawed? */
151         if ((*A2) < B2)
152                 (*A1) += B1 + 1;
153         else
154                 (*A1) += B1;
155 }
156
157
158 /* Subtract B from A */
159 void s64b_sub(s32b *A1, u32b *A2, s32b B1, u32b B2)
160 {
161         /* Underflaw? */
162         if ((*A2) < B2)
163                 (*A1) -= B1 + 1;
164         else
165                 (*A1) -= B1;
166
167         (*A2) -= B2;
168 }
169
170
171 /*
172  * Multiply A by B
173  *
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)
181  */
182 void s64b_mul(s32b *A1, u32b *A2, s32b B1, u32b B2)
183 {
184         s32b tmp1;
185         u32b A2val = (*A2);
186
187         u32b B2high = (B2 >> 16);
188         u32b A2high = (A2val >> 16);
189
190         (*A2) *= B2;
191         tmp1 = (*A1) * B2;
192         tmp1 += A2val * B1;
193         tmp1 += A2high * B2high;
194         tmp1 += (A2high * (u16b)B2) >> 16;
195         tmp1 += ((u16b)A2val * B2high) >> 16;
196
197         (*A1) = tmp1;
198 }
199
200
201 /* Compare A to B */
202 int s64b_cmp(s32b A1, u32b A2, s32b B1, u32b B2)
203 {
204         if (A1 > B1) return 1;
205         if (A1 < B1) return -1;
206         if (A2 > B2) return 1;
207         if (A2 < B2) return -1;
208         return 0;
209 }
210
211 /*
212  * Divide A by B
213  *
214  * Assumes that both A and B are positive
215  */
216 void s64b_div(s32b *A1, u32b *A2, s32b B1, u32b B2)
217 {
218         s32b result1 = 0;
219         u32b result2 = 0;
220         s32b A1val = (*A1);
221         u32b A2val = (*A2);
222         int bit = 0;
223
224         /* No result for B==0 */
225         if (B1 == 0 && B2 == 0) return;
226
227         /*
228          * Find the highest bit of quotient
229          */
230         while (s64b_cmp(A1val, A2val, B1, B2) == 1)
231         {
232                 s64b_LSHIFT(B1, B2, 1);
233                 bit++;
234         }
235
236         /* Extract bits of quotient one by one */
237         while (bit >= 0)
238         {
239                 if (s64b_cmp(A1val, A2val, B1, B2) >= 0)
240                 {
241                         if (bit >= 32)
242                                 result1 |= (0x00000001L << (bit - 32));
243                         else
244                                 result2 |= (0x00000001L << bit);
245
246                         s64b_sub(&A1val, &A2val, B1, B2);
247                 }
248         
249                 s64b_RSHIFT(B1, B2, 1);
250                 bit--;
251         }
252
253         (*A1) = result1;
254         (*A2) = result2;
255 }
256
257
258 /* Reminder of division (A % B) */
259 void s64b_mod(s32b *A1, u32b *A2, s32b B1, u32b B2)
260 {
261         s32b tmp1 = (*A1);
262         u32b tmp2 = (*A2);
263
264         s64b_div(&tmp1, &tmp2, B1, B2);
265         s64b_mul(&tmp1, &tmp2, B1, B2);
266         s64b_sub(A1, A2, tmp1, tmp2);
267 }
268
269 /*!
270 * @brief 符号なし32ビット整数のビット数を返す。
271 * @param x ビット数を調べたい変数
272 * @return ビット数
273 */
274 int count_bits(BIT_FLAGS x)
275 {
276         int n = 0;
277
278         if (x) do
279         {
280                 n++;
281         } while (0 != (x = x&(x - 1)));
282
283         return (n);
284 }
285
286 /*!
287  * @brief 平方根を切り捨て整数で返す
288  * @param n 数値
289  * @return 平方根
290  */
291 int mysqrt(int n)
292 {
293         int tmp = n >> 1;
294         int tasu = 10;
295         int kaeriti = 1;
296
297         if (!tmp)
298         {
299                 if (n) return 1;
300                 else return 0;
301         }
302
303         while (tmp)
304         {
305                 if ((n / tmp) < tmp)
306                 {
307                         tmp >>= 1;
308                 }
309                 else break;
310         }
311         kaeriti = tmp;
312         while (tasu)
313         {
314                 if ((n / tmp) < tmp)
315                 {
316                         tasu--;
317                         tmp = kaeriti;
318                 }
319                 else
320                 {
321                         kaeriti = tmp;
322                         tmp += tasu;
323                 }
324         }
325         return kaeriti;
326 }