10000 GitHub - rdentato/val: A small library to bring NaNboxing to C
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

rdentato/val

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

val — A NaN-Boxed Dynamic Value Library for C

Version License: MIT

val is a single-header, zero-dependency library that implements a dynamic val_t type for C programs via NaN-boxing. It can store:

  • IEEE-754 double-precision floats
  • Signed and unsigned 52-bit integers (as double)
  • Typed pointers (void, char, custom pointers)
  • Booleans, nil, and user-defined constants

All in one 64-bit word, with efficient runtime checks, comparisons, and hashing.

Tested on:

OS compiler notes
Linux gcc 11.4.0 64-bits and 32-bits targets
Linux clang 14.0.0 64-bits and 32-bits targets
MS Windows 11 Mingw64 15.1.0 64-bits and 32-bits targets
MS Windows 11 MS cl 19.44 /std:C11

Features

  • Compact representation: 64-bit val_t uses NaN payload bits.

  • Fast type checks: Macro utilities like valisdouble(), valisinteger(), valisptr(), valisbool(), valisnil().

  • Generic constructors:

    val_t v1 = val(3.14);     // A double
    val_t v2 = val(-42);      // A signed integer
    val_t v3 = val("hello");  // A string
  • Generic extractor:

    double d  = valtodouble(v1);
    int64_t i = valtoint(v2);
    char *s   = valtoptr(v3);
  • Comparison & hashing:

    • valcmp(a,b) returns –1, 0, or 1.
    • valhash(a) produces a 32-bit FNV1a or Murmur-style hash.
  • Zero dependencies: Just include val.h in any C11/C17 project.

  • Extensible: Define additional pointer-tags or constants via macros.


Installation

Simply copy val.h into your project’s include directory, then in your source:

#include "val.h"

No build steps required.


Quick Start

#include <stdio.h>
#include "val.h"

int main(void) {
    // Create various values
    val_t d = val(2.71828);
    val_t i = val(-12345);
    val_t u = val((unsigned int)12345);
    val_t b = val((_Bool)true);
    val_t s = val("NaN-boxing");

    // Type checks
    assert(valisdouble(d));
    assert(valisint(i));
    assert(valisint(u));
    assert(valisbool(b));
    assert(valischarptr(s));

    // Conversions
    printf("double: %f\n", valtodouble(d));
    printf("signed: %lld\n", (long long)valtoint(i));
    printf("unsigned: %llu\n", (unsigned long long)valtounsignedint(u));
    printf("bool: %s\n", valtobool(b) ? "true" : "false");
    printf("string: %s\n", (char *)valtoptr(s));

    // Comparison
    val_t x = val(10);
    val_t y = val(20);
    printf("cmp(x,y)  = %d\n", valcmp(x,y));   // –1
    
    // Note that in `valcomp()`, `10` is automatically converted to `val_t`
    printf("cmp(x,10) = %d\n", valcmp(x,10));  // 0

    // Hashing
    printf("hash(\"NaN-boxing\") = 0x%x\n", valhash(s));
    return 0;
}

Documentation

See the docs directory for full documentation.

The test directory is also a source of valuable information.


References


Changelog

  • 0.3.0 Beta (May 2025)

    • Introduced generic _Generic constructors.
    • Added pointer tags 0–7.
    • Improved valcmp and valhash performance.

License

© 2025 Remo Dentato ‹rdentato@gmail.com› Released under the MIT License.

About

A small library to bring NaNboxing to C

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
0