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- */
13 #include "term/z-util.h"
16 * Convenient storage of the program name
18 concptr argv0 = nullptr;
21 * Determine if string "t" is equal to string "t"
23 bool streq(std::string_view a, std::string_view b)
29 * Determine if string "t" is a suffix of string "s"
31 bool suffix(std::string_view s, std::string_view t)
33 //! @todo C++20 では ends_with が使用可能
34 if (t.size() > s.size()) {
38 return s.compare(s.size() - t.size(), s.npos, t) == 0;
42 * Determine if string "t" is a prefix of string "s"
44 bool prefix(std::string_view s, std::string_view t)
46 //! @todo C++20 では starts_with が使用可能
47 return s.substr(0, t.size()) == t;
51 * Redefinable "plog" action
53 void (*plog_aux)(concptr) = nullptr;
56 * Print (or log) a "warning" message (ala "perror()")
57 * Note the use of the (optional) "plog_aux" hook.
59 void plog(concptr str)
61 /* Use the "alternative" function if possible */
66 /* Just do a labeled fprintf to stderr */
68 (void)(fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "???", str));
73 * Redefinable "quit" action
75 void (*quit_aux)(concptr) = nullptr;
78 * Exit (ala "exit()"). If 'str' is nullptr, do "exit(0)".
79 * If 'str' begins with "+" or "-", do "exit(atoi(str))".
80 * Otherwise, plog() 'str' and exit with an error code of -1.
81 * But always use 'quit_aux', if set, before anything else.
83 void quit(concptr str)
85 /* Attempt to use the aux function */
95 /* Extract a "special error code" */
96 if ((str[0] == '-') || (str[0] == '+')) {
97 (void)(exit(atoi(str)));
100 /* Send the string to plog() */
104 (void)(exit(EXIT_FAILURE));
108 * Redefinable "core" action
110 void (*core_aux)(concptr) = nullptr;
113 * Dump a core file, after printing a warning message
114 * As with "quit()", try to use the "core_aux()" hook first.
116 void core(concptr str)
118 char *crash = nullptr;
120 /* Use the aux function */
125 /* Dump the warning string */
130 /* Attempt to Crash */
133 /* Be sure we exited */
134 quit("core() failed");
137 /*** 64-bit integer operations ***/
139 void s64b_lshift(int32_t *hi, uint32_t *lo, const int n)
145 *hi = (int32_t)((uint32_t)(*hi << n) | (*lo >> (32 - n)));
149 void s64b_rshift(int32_t *hi, uint32_t *lo, const int n)
155 *lo = ((uint32_t)*hi << (32 - n)) | (*lo >> n);
160 void s64b_add(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
172 /* Subtract B from A */
173 void s64b_sub(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
188 * (A1*2^32 + A2h*2^16 + A2l) * (B1*2^32 + B2h*2^16 + B2l)
189 * = (A1*B2 & 0xffffffff)*2^32
190 * +(A2*B1 & 0xffffffff)*2^32
191 * +(A2h*B2h & 0xffffffff)*2^32
192 * +(A2h*B2l & 0xffff0000)*2^16
193 * +(A2l*B2h & 0xffff0000)*2^16
194 * +(A2*B2 & 0xffffffff)
196 void s64b_mul(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
199 uint32_t A2val = (*A2);
201 uint32_t B2high = (B2 >> 16);
202 uint32_t A2high = (A2val >> 16);
207 tmp1 += A2high * B2high;
208 tmp1 += (A2high * (uint16_t)B2) >> 16;
209 tmp1 += ((uint16_t)A2val * B2high) >> 16;
215 int s64b_cmp(int32_t A1, uint32_t A2, int32_t B1, uint32_t B2)
235 * Assumes that both A and B are positive
237 void s64b_div(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
240 uint32_t result2 = 0;
241 int32_t A1val = (*A1);
242 uint32_t A2val = (*A2);
245 /* No result for B==0 */
246 if (B1 == 0 && B2 == 0) {
251 * Find the highest bit of quotient
253 while (s64b_cmp(A1val, A2val, B1, B2) == 1) {
254 s64b_lshift(&B1, &B2, 1);
258 /* Extract bits of quotient one by one */
260 if (s64b_cmp(A1val, A2val, B1, B2) >= 0) {
262 result1 |= (0x00000001UL << (bit - 32));
264 result2 |= (0x00000001UL << bit);
267 s64b_sub(&A1val, &A2val, B1, B2);
270 s64b_rshift(&B1, &B2, 1);
278 /* Reminder of ENERGY_DIVISION (A % B) */
279 void s64b_mod(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
281 int32_t tmp1 = (*A1);
282 uint32_t tmp2 = (*A2);
284 s64b_div(&tmp1, &tmp2, B1, B2);
285 s64b_mul(&tmp1, &tmp2, B1, B2);
286 s64b_sub(A1, A2, tmp1, tmp2);
290 * @brief 符号なし32ビット整数のビット数を返す。
291 * @param x ビット数を調べたい変数
294 int count_bits(BIT_FLAGS x)
301 } while (0 != (x = x & (x - 1)));