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 )