Files
gotta-scroll-fast/driver/Fixed64.utils.h
T
thomas 5f1254d11a
Tests / test_core_function (push) Failing after 12s
import upstream maccel baseline
2026-03-25 09:32:22 +00:00

76 lines
1.8 KiB
C

#include <linux/types.h>
#ifndef __KERNEL__
#include <stdint.h>
#endif // !__KERNEL__
/**
* [Yeetmouse](https://github.com/AndyFilter/YeetMouse/blob/master/driver/FixedMath/Fixed64.h#L1360)
* has better string utils. FP64_ToString there doesn't require
* `__udivmodti4` in 64-bit mode.
*
*/
typedef int32_t FP_INT;
typedef int64_t FP_LONG;
#define FP64_Shift 32
static inline FP_LONG FP64_Mul(FP_LONG a, FP_LONG b) {
return (FP_LONG)(((__int128_t)a * (__int128_t)b) >> FP64_Shift);
}
static char *FP_64_itoa_loop(char *buf, uint64_t scale, uint64_t value,
int skip) {
while (scale) {
unsigned digit = (value / scale);
if (!skip || digit || scale == 1) {
skip = 0;
*buf++ = '0' + digit;
value %= scale;
}
scale /= 10;
}
return buf;
}
void FP64_ToString(FP_LONG value, char *buf);
void FP64_ToString(FP_LONG value, char *buf) {
uint64_t uvalue = (value >= 0) ? value : -value;
if (value < 0)
*buf++ = '-';
#define SCALE 9
static const uint64_t FP_64_scales[10] = {
/* 18 decimals is enough for full 64bit fixed point precision */
1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000};
/* Separate the integer and decimal parts of the value */
uint64_t intpart = uvalue >> 32;
uint64_t fracpart = uvalue & 0xFFFFFFFF;
uint64_t scale = FP_64_scales[SCALE];
fracpart = FP64_Mul(fracpart, scale);
if (fracpart >= scale) {
/* Handle carry from decimal part */
intpart++;
fracpart -= scale;
}
/* Format integer part */
buf = FP_64_itoa_loop(buf, 1000000000, intpart, 1);
/* Format decimal part (if any) */
if (scale != 1) {
*buf++ = '.';
buf = FP_64_itoa_loop(buf, scale / 10, fracpart, 0);
}
*buf = '\0';
}