Print changes

This commit is contained in:
2026-08-13 02:41:41 -07:00
parent 046b9b0c87
commit 7b854c1559
11 changed files with 438 additions and 26 deletions
+157 -1
View File
@@ -2,6 +2,7 @@
#define INCLUDED_MEMORY_H
#include <float.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
@@ -10,7 +11,7 @@
// Geneal macros
#ifndef __has_attribute
# define __has_attribute(attr) 0
# define __has_attribute(x) 0
#endif
#if __has_attribute(always_inline) && defined(_NDEBUG)
@@ -98,6 +99,142 @@ static ALWAYS_INLINE lisp_float64_t INT_TO_FLOAT64_BITS(uint64_t i) {
uint32_t: INT_TO_FLOAT32_BITS(i), \
uint64_t: INT_TO_FLOAT64_BITS(i))
#define FLOAT_POSITIVE 0
#define FLOAT_NEGATIVE 1
typedef struct
#if __has_attribute(packed)
__attribute__((packed))
#endif
{
uint32_t sign : 1;
int32_t exp : 8;
uint32_t mantissa : 23;
} lisp_float32_parts;
#define FLOAT32_MIN_EXP -127
#define FLOAT32_MAX_EXP 127
#define FLOAT32_MAX_PRECISION 6
#define FLOAT32_MAX_MANTISSA 0x7fffff
typedef struct
#if __has_attribute(packed)
__attribute__((packed))
#endif
{
uint64_t sign : 1;
int64_t exp : 11;
uint64_t mantissa : 52;
} lisp_float64_parts;
#define FLOAT64_MIN_EXP -1023
#define FLOAT64_MAX_EXP 1023
#define FLOAT64_MAX_PRECISION 15
#define FLOAT64_MAX_MANTISSA 0xfffffffffffff
static ALWAYS_INLINE lisp_float32_parts FLOAT32_TO_PARTS(lisp_float32_t flt) {
#if __has_attribute(packed)
union {
lisp_float32_parts parts;
lisp_float32_t flt_val;
} conv = {.flt_val = flt};
conv.parts.exp -= 127;
return conv.parts;
#else
uint32_t bits = FLOAT_TO_INT_BITS(flt);
return (lisp_float32_parts) {
.sign = bits >> 31,
.exp = (bits >> 23) - 127,
.mantissa = bits & 0x7fffff,
};
#endif
}
static ALWAYS_INLINE lisp_float64_parts FLOAT64_TO_PARTS(lisp_float64_t flt) {
#if __has_attribute(packed)
union {
lisp_float64_parts parts;
lisp_float64_t flt_val;
} conv = {.flt_val = flt};
conv.parts.exp -= 1023;
return conv.parts;
#else
uint64_t bits = FLOAT_TO_INT_BITS(flt);
return (lisp_float64_parts) {
.sign = bits >> 63,
.exp = (bits >> 52) - 1023,
.mantissa = bits & 0xfffffffffffff,
};
#endif
}
#define FLOAT_TO_PARTS(flt) \
_Generic((flt), \
lisp_float32_t: FLOAT32_TO_PARTS(flt), \
lisp_float64_t: FLOAT64_TO_PARTS(flt))
static ALWAYS_INLINE lisp_float64_t PARTS_TO_FLOAT64(lisp_float64_parts parts) {
#if __has_attribute(packed)
parts.exp += 1023;
union {
lisp_float64_parts parts;
lisp_float64_t flt_val;
} conv = {.parts = parts};
return conv.flt_val;
#else
return INT_TO_FLOAT64_BITS(parts.sign << 63 | (parts.exp + 1023) << 52
| parts.mantissa);
#endif
}
static ALWAYS_INLINE lisp_float32_t PARTS_TO_FLOAT32(lisp_float32_parts parts) {
#if __has_attribute(packed)
parts.exp += 127;
union {
lisp_float32_parts parts;
lisp_float32_t flt_val;
} conv = {.parts = parts};
return conv.flt_val;
#else
return INT_TO_FLOAT32_BITS(parts.sign << 31 | (parts.exp + 127) << 23
| parts.mantissa);
#endif
}
#define PARTS_TO_FLOAT(parts) \
_Generic((parts), \
lisp_float32_parts: PARTS_TO_FLOAT32(parts), \
lisp_float64_parts: PARTS_TO_FLOAT64(parts))
static ALWAYS_INLINE lisp_float32_t LISP_FLOAT32_NAN(void) {
return PARTS_TO_FLOAT32((lisp_float32_parts) {
.sign = FLOAT_POSITIVE,
.exp = FLOAT32_MAX_EXP,
.mantissa = FLOAT32_MAX_MANTISSA,
});
}
static ALWAYS_INLINE lisp_float32_t LISP_FLOAT32_INF(bool negative) {
return PARTS_TO_FLOAT32((lisp_float32_parts) {
.sign = negative ? FLOAT_NEGATIVE : FLOAT_POSITIVE,
.exp = FLOAT32_MAX_EXP,
.mantissa = 0,
});
}
static ALWAYS_INLINE lisp_float64_t LISP_FLOAT64_NAN(void) {
return PARTS_TO_FLOAT64((lisp_float64_parts) {
.sign = FLOAT_POSITIVE,
.exp = FLOAT64_MAX_EXP,
.mantissa = FLOAT64_MAX_MANTISSA,
});
}
static ALWAYS_INLINE lisp_float64_t LISP_FLOAT64_INF(bool negative) {
return PARTS_TO_FLOAT64((lisp_float64_parts) {
.sign = negative ? FLOAT_NEGATIVE : FLOAT_POSITIVE,
.exp = FLOAT64_MAX_EXP,
.mantissa = 0,
});
}
// Allocator
void *lisp_realloc(void *oldptr, size_t size);
void *lisp_malloc(size_t size);
@@ -130,6 +267,25 @@ static ALWAYS_INLINE void add_timespecs(const struct timespec *t1,
out->tv_nsec = nsec;
}
static ALWAYS_INLINE size_t signed_number_length(intmax_t n) {
if (!n) {
return 1;
}
size_t sign_part = 0;
if (n < 0) {
n = -n;
sign_part = 1;
}
return sign_part + floor(log10(n)) + 1;
}
static ALWAYS_INLINE size_t unsigned_number_length(uintmax_t n) {
if (!n) {
return 1;
}
return floor(log10(n)) + 1;
}
typedef struct {
// this is actually size + 1 bytes for the null byte
char *buffer;