Affix
view release on metacpan or search on metacpan
lib/Affix/marshal.c view on Meta::CPAN
typedef uint16_t float16_t;
bool is_pin_v2(pTHX_ SV * sv);
const infix_type * resolve_type(pTHX_ const infix_type * type);
SV * bind_aggregate(pTHX_ void * ptr, const infix_type * type, SV * owner, bool);
int is_v2_vtable(MGVTBL * v);
static SV * _bind_aggregate_internal(
pTHX_ void * ptr, const infix_type * type, SV * owner, infix_arena_t * arena, bool, bool);
int is_string_list_type(pTHX_ const infix_type * type) {
const infix_type * t = resolve_type(aTHX_ type);
if (!t)
return 0;
if (t->category != INFIX_TYPE_POINTER)
return 0;
const infix_type * p1 = resolve_type(aTHX_ t->meta.pointer_info.pointee_type);
if (!p1 || p1->category != INFIX_TYPE_POINTER)
return 0;
const infix_type * p2 = resolve_type(aTHX_ p1->meta.pointer_info.pointee_type);
if (!p2)
return 0;
if (p2->category != INFIX_TYPE_PRIMITIVE)
return 0;
/* We treat 'char' and 'uchar' as semantic strings.
'sint8' is left as a raw integer for manual memory control. */
return (p2->meta.primitive_id == INFIX_PRIMITIVE_SINT8 || p2->meta.primitive_id == INFIX_PRIMITIVE_UINT8);
}
/**
* @brief Converts IEEE 754 half-precision (16-bit) to single-precision (32-bit) float.
* @details Half-precision has 1 sign bit, 5 exponent bits, and 10 mantissa bits.
* @param h The 16-bit half-precision value (stored as an unsigned integer).
* @return The 32-bit single-precision float.
*/
float float16_to_float32(float16_t h) {
uint32_t h_exp = (h >> 10) & 0x1f; /* Extract 5-bit exponent */
uint32_t h_sig = h & 0x3ff; /* Extract 10-bit mantissa (significand) */
uint32_t sign = (uint32_t)(h >> 15) << 31; /* Shift sign bit to 32-bit position */
if (h_exp == 0) {
if (h_sig == 0)
return (sign) ? -0.0f : 0.0f; /* Signed zero */
while (!(h_sig & 0x400)) { /* Subnormal number: normalize it */
h_sig <<= 1;
h_exp--;
}
h_exp++;
h_sig &= ~0x400;
}
else if (h_exp == 0x1f) {
/* Infinity or NaN */
uint32_t f_nan = (h_sig == 0) ? 0x7f800000 : 0x7fc00000;
union {
uint32_t u;
float f;
} u;
u.u = sign | f_nan;
return u.f;
}
/* Adjust exponent bias from 15 to 127 and align mantissa to 23 bits */
uint32_t f_exp = (h_exp + (127 - 15)) << 23;
uint32_t f_sig = h_sig << 13;
union {
uint32_t u;
float f;
} u;
u.u = sign | f_exp | f_sig;
return u.f;
}
/**
* @brief Converts IEEE 754 single-precision (32-bit) float to half-precision (16-bit).
* @details Rounds standard floats down to the limited bounds of a half-precision float.
* @param f The 32-bit single-precision float.
* @return The 16-bit half-precision value.
*/
float16_t float32_to_float16(float f) {
union {
float f;
uint32_t u;
} u;
u.f = f;
uint32_t sign = (u.u >> 16) & 0x8000;
uint32_t exp = (u.u >> 23) & 0xff;
uint32_t sig = u.u & 0x7fffff;
/* Handle Inf and NaN */
if (exp == 0xff)
return sign | 0x7c00 | (sig ? 0x200 : 0);
int e = (int)exp - 127 + 15; /* Re-bias exponent to 15 */
if (e >= 31)
return sign | 0x7c00; /* Overflow to Infinity */
if (e <= 0) {
/* Underflow to Subnormal */
if (e < -10)
return sign;
sig |= 0x800000;
sig >>= (1 - e);
return sign | (sig >> 13);
}
return sign | (e << 10) | (sig >> 13);
}
/**
* @brief Common destructor for all v2 magic.
* Ensures that if a pin owns an anonymous type graph, it is freed with the SV.
*/
int free_v2_pin(pTHX_ SV * sv, MAGIC * mg) {
Affix_Pin_2_Point_Oh * im = (Affix_Pin_2_Point_Oh *)mg->mg_ptr;
if (im->destructor && im->ptr)
im->destructor(im->ptr);
if (im->destructor_lib_sv)
SvREFCNT_dec(im->destructor_lib_sv);
if (im->arena)
infix_arena_destroy(im->arena);
return 0;
}
static int dup_v2_pin(pTHX_ MAGIC * mg, CLONE_PARAMS * param) {
#ifdef USE_ITHREADS
Affix_Pin_2_Point_Oh * old_pin = (Affix_Pin_2_Point_Oh *)mg->mg_ptr;
if (!old_pin)
return 0;
Affix_Pin_2_Point_Oh * new_pin;
Newxz(new_pin, 1, Affix_Pin_2_Point_Oh);
memcpy(new_pin, old_pin, sizeof(Affix_Pin_2_Point_Oh));
// Lifeline Tracking (Library handles)
if (old_pin->destructor_lib_sv) {
new_pin->destructor_lib_sv = sv_dup(old_pin->destructor_lib_sv, param);
SvREFCNT_inc(new_pin->destructor_lib_sv);
}
// Type Metadata (Deep Copy)
if (old_pin->arena) {
// If the pin owns a private type arena (anonymous signatures),
// we must clone the arena and re-point the type into the new arena.
new_pin->arena = infix_arena_create(4096);
new_pin->type = _copy_type_graph_to_arena(new_pin->arena, old_pin->type);
}
// Else: Global types from the registry are handled via CLONE in Affix.c
mg->mg_ptr = (char *)new_pin;
#endif
return 0;
}
( run in 1.529 second using v1.01-cache-2.11-cpan-2c0d6866c4f )