spxdec: Use read_u16() from portable_io.h.
[paraslash.git] / mood.c
diff --git a/mood.c b/mood.c
index 584c46b..a63d4d2 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -1,8 +1,4 @@
-/*
- * Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
 
 /** \file mood.c Paraslash's mood handling functions. */
 
@@ -93,32 +89,60 @@ struct mood {
  */
 static struct mood *current_mood;
 
-/**
- * Rough approximation to sqrt.
+/*
+ * Find the position of the most-significant set bit.
  *
- * \param x Integer of which to calculate the sqrt.
+ * Copied and slightly adapted from the linux source tree, version 4.9.39
+ * (2017-07).
+ */
+__a_const static uint32_t fls64(uint64_t v)
+{
+       int n = 63;
+       const uint64_t ones = ~(uint64_t)0U;
+
+       if ((v & (ones << 32)) == 0) {
+               n -= 32;
+               v <<= 32;
+       }
+       if ((v & (ones << (64 - 16))) == 0) {
+               n -= 16;
+               v <<= 16;
+       }
+       if ((v & (ones << (64 - 8))) == 0) {
+               n -= 8;
+               v <<= 8;
+       }
+       if ((v & (ones << (64 - 4))) == 0) {
+               n -= 4;
+               v <<= 4;
+       }
+       if ((v & (ones << (64 - 2))) == 0) {
+               n -= 2;
+               v <<= 2;
+       }
+       if ((v & (ones << (64 - 1))) == 0)
+               n -= 1;
+       return n;
+}
+
+/*
+ * Compute the integer square root floor(sqrt(x)).
  *
- * \return An integer res with res * res <= x.
+ * Taken 2007 from the linux source tree.
  */
 __a_const static uint64_t int_sqrt(uint64_t x)
 {
-       uint64_t op, res, one = 1;
-       op = x;
-       res = 0;
-
-       one = one << 62;
-       while (one > op)
-               one >>= 2;
+       uint64_t op = x, res = 0, one = 1;
 
+       one = one << (fls64(x) & ~one);
        while (one != 0) {
                if (op >= res + one) {
                        op = op - (res + one);
-                       res = res +  2 * one;
+                       res = res + 2 * one;
                }
                res /= 2;
                one /= 4;
        }
-//     PARA_NOTICE_LOG("sqrt(%llu) = %llu\n", x, res);
        return res;
 }
 
@@ -394,10 +418,13 @@ static int load_mood(const struct osl_row *mood_row, struct mood **m,
 
        *m = NULL;
        ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def);
-       if (ret < 0)
+       if (ret < 0) {
+               if (errmsg)
+                       *errmsg = make_message(
+                               "could not read mood definition");
                return ret;
-       if (!*mood_name)
-               return -E_DUMMY_ROW;
+       }
+       assert(*mood_name);
        mlpd.m = alloc_new_mood(mood_name);
        ret = for_each_line(FELF_READ_ONLY, mood_def.data, mood_def.size,
                parse_mood_line, &mlpd);
@@ -852,7 +879,9 @@ int change_current_mood(const char *mood_name, char **errmsg)
                };
                ret = osl(osl_get_row(moods_table, BLOBCOL_NAME, &obj, &row));
                if (ret < 0) {
-                       PARA_NOTICE_LOG("no such mood: %s\n", mood_name);
+                       if (errmsg)
+                               *errmsg = make_message("no such mood: %s",
+                                       mood_name);
                        return ret;
                }
                ret = load_mood(row, &m, errmsg);
@@ -867,13 +896,20 @@ int change_current_mood(const char *mood_name, char **errmsg)
        aa.m = current_mood;
        PARA_NOTICE_LOG("computing statistics of admissible files\n");
        ret = audio_file_loop(&aa, add_if_admissible);
-       if (ret < 0)
+       if (ret < 0) {
+               if (errmsg)
+                       *errmsg = make_message("audio file loop failed");
                return ret;
+       }
        for (i = 0; i < statistics.num; i++) {
                struct admissible_file_info *a = aa.array + i;
                ret = add_to_score_table(a->aft_row, a->score);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (errmsg)
+                               *errmsg = make_message(
+                                       "could not add row to score table");
                        goto out;
+               }
        }
        log_statistics();
        ret = statistics.num;