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 * @brief 意図的にクラッシュさせ、コアファイルをダンプする
114 * @param str エラーメッセージ
115 * @details MSVC以外のコンパイラはpragma warning をコンパイルエラーにする.
118 void core(concptr str)
120 char *crash = nullptr;
129 #if defined(_MSC_VER)
130 #pragma warning(push)
131 #pragma warning(disable : 6011)
134 #if defined(_MSC_VER)
137 quit("core() failed");
140 /*** 64-bit integer operations ***/
142 void s64b_lshift(int32_t *hi, uint32_t *lo, const int n)
148 *hi = (int32_t)((uint32_t)(*hi << n) | (*lo >> (32 - n)));
152 void s64b_rshift(int32_t *hi, uint32_t *lo, const int n)
158 *lo = ((uint32_t)*hi << (32 - n)) | (*lo >> n);
163 void s64b_add(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
175 /* Subtract B from A */
176 void s64b_sub(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
191 * (A1*2^32 + A2h*2^16 + A2l) * (B1*2^32 + B2h*2^16 + B2l)
192 * = (A1*B2 & 0xffffffff)*2^32
193 * +(A2*B1 & 0xffffffff)*2^32
194 * +(A2h*B2h & 0xffffffff)*2^32
195 * +(A2h*B2l & 0xffff0000)*2^16
196 * +(A2l*B2h & 0xffff0000)*2^16
197 * +(A2*B2 & 0xffffffff)
199 void s64b_mul(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
202 uint32_t A2val = (*A2);
204 uint32_t B2high = (B2 >> 16);
205 uint32_t A2high = (A2val >> 16);
210 tmp1 += A2high * B2high;
211 tmp1 += (A2high * (uint16_t)B2) >> 16;
212 tmp1 += ((uint16_t)A2val * B2high) >> 16;
218 int s64b_cmp(int32_t A1, uint32_t A2, int32_t B1, uint32_t B2)
238 * Assumes that both A and B are positive
240 void s64b_div(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
243 uint32_t result2 = 0;
244 int32_t A1val = (*A1);
245 uint32_t A2val = (*A2);
248 /* No result for B==0 */
249 if (B1 == 0 && B2 == 0) {
254 * Find the highest bit of quotient
256 while (s64b_cmp(A1val, A2val, B1, B2) == 1) {
257 s64b_lshift(&B1, &B2, 1);
261 /* Extract bits of quotient one by one */
263 if (s64b_cmp(A1val, A2val, B1, B2) >= 0) {
265 result1 |= (0x00000001UL << (bit - 32));
267 result2 |= (0x00000001UL << bit);
270 s64b_sub(&A1val, &A2val, B1, B2);
273 s64b_rshift(&B1, &B2, 1);
281 /* Reminder of ENERGY_DIVISION (A % B) */
282 void s64b_mod(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
284 int32_t tmp1 = (*A1);
285 uint32_t tmp2 = (*A2);
287 s64b_div(&tmp1, &tmp2, B1, B2);
288 s64b_mul(&tmp1, &tmp2, B1, B2);
289 s64b_sub(A1, A2, tmp1, tmp2);
293 * @brief 符号なし32ビット整数のビット数を返す。
294 * @param x ビット数を調べたい変数
297 int count_bits(BIT_FLAGS x)
304 } while (0 != (x = x & (x - 1)));