Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.
My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index 665ef95..10713d0 100644 ****************************************************************************/ #include "plugin.h" +#include <inttypes.h> #include <albumart.h> #include "lib/pluginlib_actions.h" #include "lib/helper.h" @@ -337,16 +338,64 @@ static inline PFreal fmul(PFreal a, PFreal b) return (a*b) >> PFREAL_SHIFT; } +#define MASK_TOP_N(bits) ((uint32_t)(((1ull << 32) - 1) << (32-(bits)))) +/* Shift val as far left as possible without overflow, up to max places, + * reducing places by the number of places shifted. + */ +static inline void max_shift_left(int32_t *val, int *places) +{ + uint32_t uval = abs(*val); + bool s = uval == (uint32_t)*val; + if(*places >= 16 && !(MASK_TOP_N(17) & uval)) + { + uval <<= 16; + *places -= 16; + } + if(*places >= 8 && !(MASK_TOP_N(9) & uval)) + { + uval <<= 8; + *places -= 8; + } + if(*places >= 4 && !(MASK_TOP_N(5) & uval)) + { + uval <<= 4; + *places -= 4; + } + if(*places >= 2 && !(MASK_TOP_N(3) & uval)) + { + uval <<= 2; + *places -= 2; + } + if(*places && !(MASK_TOP_N(2) & uval)) + { + uval <<= 1; + *places -= 1; + } + *val = s ? uval : -uval; +} + +/* Return the maximum possible left shift for a signed int32, without + * overflow + */ +unsigned int allowed_shift(int32_t val) +{ + uint32_t uval = abs(val); + if (!uval) + return 32; + else + return __builtin_clz(uval) - 1; +} + /* There are some precision issues when not using (long long) which in turn takes very long to compute... I guess the best solution would be to optimize the computations so it only requires a single long */ -static inline PFreal fdiv(PFreal num, PFreal den) +PFreal fdiv(PFreal num, PFreal den) { - long long p = (long long) (num) << (PFREAL_SHIFT * 2); - long long q = p / (long long) den; - long long r = q >> PFREAL_SHIFT; - - return r; +// int shift = MIN(allowed_shift(num), PFREAL_SHIFT); + int places = PFREAL_SHIFT; + max_shift_left(&num, &places); + den >>= places; + return num / den; } #define fmin(a,b) (((a) < (b)) ? (a) : (b)) |