mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
Ports three Research Stack RRC gates into formal/SilverSight/RRC/ using the existing CoreFormalism braid and Q16_16 surfaces. Adds a Lean ↔ C ↔ Python Q16_16 roundtrip test: - c/q16_canonical.c: canonical saturating Q16_16 C library - exe/Q16_16Roundtrip.lean: Lake extern_lib linked executable - tests/test_q16_roundtrip.py: Python ↔ C harness (revived from quarantine) Updates lakefile.lean with q16-roundtrip executable and extern_lib q16_canonical. Build: lake build SilverSightRRC 3006 jobs, 0 errors; q16-roundtrip 5949 jobs, 0 errors
77 lines
2.3 KiB
C
77 lines
2.3 KiB
C
/* Canonical Q16_16 fixed-point arithmetic (C implementation).
|
|
*
|
|
* This is the C side of the Lean <-> C <-> Python roundtrip test.
|
|
* It mirrors python/q16_canonical.py:
|
|
* - banker's rounding for float->fixed conversion
|
|
* - saturation to INT32_MIN/INT32_MAX
|
|
* - exact integer conversions
|
|
* - saturating add/sub
|
|
* - mul/div with banker's rounding (double-based, matching Python)
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <float.h>
|
|
|
|
#define Q16_SCALE 65536.0
|
|
#define Q16_SCALE_INT 65536
|
|
#define Q16_MIN_RAW (-2147483648LL)
|
|
#define Q16_MAX_RAW 2147483647LL
|
|
|
|
static int64_t clamp_int64(long long v) {
|
|
if (v < Q16_MIN_RAW) return Q16_MIN_RAW;
|
|
if (v > Q16_MAX_RAW) return Q16_MAX_RAW;
|
|
return v;
|
|
}
|
|
|
|
/* Convert float to Q16_16 raw value using banker's rounding. */
|
|
int32_t float_to_q16_nearbyint(double f) {
|
|
if (isnan(f) || isinf(f)) {
|
|
return 0; /* Python raises; C returns a sentinel. */
|
|
}
|
|
long long r = (long long)nearbyint(f * Q16_SCALE);
|
|
return (int32_t)clamp_int64(r);
|
|
}
|
|
|
|
/* Convert Q16_16 raw value to float (exact). */
|
|
double q16_to_float(int32_t q) {
|
|
return (double)q / Q16_SCALE;
|
|
}
|
|
|
|
/* Convert integer to Q16_16 raw value (exact, with saturation). */
|
|
int32_t int_to_q16(int32_t i) {
|
|
long long r = (long long)i * Q16_SCALE_INT;
|
|
return (int32_t)clamp_int64(r);
|
|
}
|
|
|
|
/* Convert Q16_16 raw value to integer, truncating toward zero. */
|
|
int32_t q16_to_int(int32_t q) {
|
|
return q / Q16_SCALE_INT;
|
|
}
|
|
|
|
/* Saturating addition of two Q16_16 values. */
|
|
int32_t q16_add(int32_t a, int32_t b) {
|
|
long long r = (long long)a + (long long)b;
|
|
return (int32_t)clamp_int64(r);
|
|
}
|
|
|
|
/* Saturating subtraction of two Q16_16 values. */
|
|
int32_t q16_sub(int32_t a, int32_t b) {
|
|
long long r = (long long)a - (long long)b;
|
|
return (int32_t)clamp_int64(r);
|
|
}
|
|
|
|
/* Multiply two Q16_16 values with banker's rounding (matches Python). */
|
|
int32_t q16_mul(int32_t a, int32_t b) {
|
|
double prod = (double)a * (double)b;
|
|
long long r = (long long)nearbyint(prod / Q16_SCALE);
|
|
return (int32_t)clamp_int64(r);
|
|
}
|
|
|
|
/* Divide two Q16_16 values with banker's rounding. */
|
|
int32_t q16_div(int32_t a, int32_t b) {
|
|
if (b == 0) return 0;
|
|
double num = (double)a * Q16_SCALE;
|
|
long long r = (long long)nearbyint(num / (double)b);
|
|
return (int32_t)clamp_int64(r);
|
|
}
|