This commit is contained in:
Steven Dan
2025-12-11 09:43:42 +08:00
commit d8b2974133
1822 changed files with 280037 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
cmake_minimum_required(VERSION 3.21)
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
project(compressor_ratio)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/compressor_ratio.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(expander_ratio)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/expander_ratio.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(rms_threshold)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/rms_threshold.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(peak_threshold)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/peak_threshold.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(calc_alpha)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/calc_alpha.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(db_gain)
set(APP_HW_TARGET XCORE-AI-EXPLORER)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/db_gain.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()
project(time_samples)
set(APP_COMPILER_FLAGS
-O3
-g
-report
-Wall
-Werror
-fxscope)
set(APP_DEPENDENT_MODULES lib_audio_dsp)
set(APP_C_SRCS src/time_samples.c)
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
XMOS_REGISTER_APP()

View File

@@ -0,0 +1,44 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/helpers.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
printf("inlen %d", in_len);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0;
int32_t samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = calc_alpha(48000.0, samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(int32_t), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,42 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/helpers.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0, samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = rms_compressor_slope_from_ratio(samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(float), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,43 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/signal_chain.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0;
int32_t samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = adsp_dB_to_gain(samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(int32_t), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,42 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/helpers.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0, samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = peak_expander_slope_from_ratio(samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(float), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,43 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/helpers.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0;
int32_t samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = calculate_peak_threshold(samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(int32_t), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,43 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/helpers.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / sizeof(float);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp = 0;
int32_t samp_out = 0;
fread(&samp, sizeof(float), 1, in);
//printf("%ld ", samp);
samp_out = calculate_rms_threshold(samp);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(int32_t), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,44 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "control/signal_chain.h"
FILE * _fopen(char * fname, char* mode) {
FILE * fp = fopen(fname, mode);
if (fp == NULL)
{
printf("Error opening a file\n");
exit(1);
}
return fp;
}
int main()
{
FILE * in = _fopen("test_vector.bin", "rb");
FILE * out = _fopen("out_vector.bin", "wb");
fseek(in, 0, SEEK_END);
int in_len = ftell(in) / (2.0f*sizeof(float));
printf("inlen %d", in_len);
fseek(in, 0, SEEK_SET);
for (unsigned i = 0; i < in_len; i++)
{
float samp[2] = {0};
int32_t samp_out = 0;
fread(&samp, sizeof(float), 2, in);
//printf("%ld ", samp);
samp_out = time_to_samples(48000.0, samp[0], (time_units_t)samp[1]);
//printf("%ld ", samp_out);
fwrite(&samp_out, sizeof(int32_t), 1, out);
}
fclose(in);
fclose(out);
return 0;
}

View File

@@ -0,0 +1,179 @@
# Copyright 2024-2025 XMOS LIMITED.
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
import numpy as np
from pathlib import Path
import subprocess
import itertools
from enum import IntEnum
import audio_dsp.dsp.utils as utils
import audio_dsp.dsp.drc.drc_utils as drcu
import audio_dsp.dsp.signal_chain as sc
from audio_dsp.dsp.generic import Q_SIG, HEADROOM_DB
bin_dir = Path(__file__).parent / "bin"
gen_dir = Path(__file__).parent / "autogen"
fs=48000
def flt_to_bin_file(sig_fl, out_dir=bin_dir):
sig_fl32 = np.array(sig_fl).astype(np.float32)
name = "test_vector"
sig_fl32.tofile(out_dir / f"{name}.bin")
return sig_fl
def get_c_wav(dir_name, conv_name, verbose=False, sim = True, dtype=np.float32):
app = "xsim" if sim else "xrun --io"
run_cmd = app + " " + str(bin_dir / f"{conv_name}.xe")
stdout = subprocess.check_output(run_cmd, cwd = dir_name, shell = True)
if verbose: print("run msg:\n", stdout.decode())
sig_bin = dir_name / "out_vector.bin"
assert sig_bin.is_file(), f"Could not find output bin {sig_bin}"
sig_int = np.fromfile(sig_bin, dtype=dtype)
return sig_int
def test_compressor_ratio_helper():
test_dir = bin_dir / "compressor_ratio"
test_dir.mkdir(exist_ok = True, parents = True)
ratios = [0, 0.9, 1, 5, 10000, 999999999999999999999999999]
flt_to_bin_file(ratios, test_dir)
out_c = get_c_wav(test_dir, "compressor_ratio")
slopes_python = np.zeros_like(ratios, dtype=np.float32)
for n in range(len(ratios)):
slope, slopes_python[n] = drcu.rms_compressor_slope_from_ratio(ratios[n])
assert np.all(out_c == slopes_python)
def test_expander_ratio_helper():
test_dir = bin_dir / "expander_ratio"
test_dir.mkdir(exist_ok = True, parents = True)
ratios = [0, 0.9, 1, 5, 10000, 999999999999999999999999999]
flt_to_bin_file(ratios, test_dir)
out_c = get_c_wav(test_dir, "expander_ratio")
slopes_python = np.zeros_like(ratios, dtype=np.float32)
for n in range(len(ratios)):
slope, slopes_python[n] = drcu.peak_expander_slope_from_ratio(ratios[n])
assert np.all(out_c == slopes_python)
def test_rms_threshold():
test_dir = bin_dir / "rms_threshold"
test_dir.mkdir(exist_ok = True, parents = True)
threshold_dbs = [-2000, 0, HEADROOM_DB/2 + 1]
flt_to_bin_file(threshold_dbs, test_dir)
out_c = get_c_wav(test_dir, "rms_threshold", dtype=np.int32)
thresh_python = np.zeros_like(threshold_dbs, dtype=np.int32)
for n in range(len(threshold_dbs)):
_, thresh_python[n] = drcu.calculate_rms_threshold(threshold_dbs[n], Q_SIG)
np.testing.assert_allclose(out_c, thresh_python, rtol=2**-21, atol=1)
def test_peak_threshold():
test_dir = bin_dir / "peak_threshold"
test_dir.mkdir(exist_ok = True, parents = True)
# threshold_dbs = [-2000, -0, HEADROOM_DB + 1]
threshold_dbs = utils.db(np.logspace(np.log10(0.001), np.log10(8), 100))
flt_to_bin_file(threshold_dbs, test_dir)
out_c = get_c_wav(test_dir, "peak_threshold", dtype=np.int32)
thresh_python = np.zeros_like(threshold_dbs, dtype=np.int32)
for n in range(len(threshold_dbs)):
_, thresh_python[n] = drcu.calculate_threshold(threshold_dbs[n], Q_SIG, power=False)
np.testing.assert_allclose(out_c, thresh_python, rtol=2**-21, atol=1)
def test_calc_alpha():
test_dir = bin_dir / "calc_alpha"
test_dir.mkdir(exist_ok = True, parents = True)
attack_times = [-1, 0, 1/48000, 3/48000, 1, 1000, (4/48000)*(2**31)]
flt_to_bin_file(attack_times, test_dir)
out_c = get_c_wav(test_dir, "calc_alpha", dtype=np.int32)
alphas_python = np.zeros_like(attack_times, dtype=np.int32)
for n in range(len(attack_times)):
alpha, alphas_python[n] = drcu.alpha_from_time(attack_times[n], 48000)
# not exact due to float32 implementation differences
np.testing.assert_allclose(out_c, alphas_python, rtol=2**-24, atol=0)
def test_db_gain():
test_dir = bin_dir / "db_gain"
test_dir.mkdir(exist_ok = True, parents = True)
gain_dbs = [-np.inf, -2000, 0, 25]
flt_to_bin_file(gain_dbs, test_dir)
out_c = get_c_wav(test_dir, "db_gain", dtype=np.int32)
gain_python = np.zeros_like(gain_dbs, dtype=np.int32)
for n in range(len(gain_dbs)):
gain, gain_python[n] = sc.db_to_qgain(gain_dbs[n])
np.testing.assert_allclose(out_c, gain_python, rtol=2**-23, atol=0)
class time_units_type(IntEnum):
samples = 0
ms = 1
s = 2
def test_time_samples():
test_dir = bin_dir / "time_samples"
test_dir.mkdir(exist_ok = True, parents = True)
times = [10, 128, 1.7, 0.94, 2, -2]
units = [time_units_type["samples"], time_units_type["s"], time_units_type["ms"]]
input_params = list(itertools.product(times, units))
flt_to_bin_file(input_params, test_dir)
out_c = get_c_wav(test_dir, "time_samples", dtype=np.int32)
delay_py = np.zeros(len(input_params), dtype=np.int32)
for n in range(len(input_params)):
delay_py[n] = utils.time_to_samples(48000, input_params[n][0], input_params[n][1].name)
# not exact due to float32 implementation differences
np.testing.assert_allclose(out_c, delay_py, rtol=2**-24, atol=0)
if __name__ == "__main__":
bin_dir.mkdir(exist_ok=True, parents=True)
gen_dir.mkdir(exist_ok=True, parents=True)
test_db_gain()

View File

@@ -0,0 +1,105 @@
# Copyright 2024-2025 XMOS LIMITED.
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
import pytest
import audio_dsp.dsp.utils as utils
import audio_dsp.dsp.drc.drc_utils as drcu
import audio_dsp.dsp.signal_chain as sc
from audio_dsp.dsp.generic import Q_SIG, HEADROOM_DB
@pytest.mark.parametrize("ratio, warning", [(0, UserWarning),
(0.9, UserWarning),
(1, None),
(5, None),
(10000, None),
(999999999999999999999999999, None)])
def test_compressor_ratio_helper(ratio, warning):
if warning:
with pytest.warns(warning):
slope, slope_f32 = drcu.rms_compressor_slope_from_ratio(ratio)
else:
slope, slope_f32 = drcu.rms_compressor_slope_from_ratio(ratio)
@pytest.mark.parametrize("ratio, warning", [(0, UserWarning),
(0.9, UserWarning),
(1, None),
(5, None),
(10000, None),
(999999999999999999999999999, None)])
def test_expander_ratio_helper(ratio, warning):
if warning:
with pytest.warns(warning):
slope, slope_f32 = drcu.peak_expander_slope_from_ratio(ratio)
else:
slope, slope_f32 = drcu.peak_expander_slope_from_ratio(ratio)
@pytest.mark.parametrize("threshold_db, warning", [(-2000, None),
(0, None),
(HEADROOM_DB/2 + 1, UserWarning)])
def test_rms_threshold(threshold_db, warning):
if warning:
with pytest.warns(warning):
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=True)
else:
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=True)
@pytest.mark.parametrize("threshold_db, warning", [(-2000, None),
(0, None),
(HEADROOM_DB + 1, UserWarning)])
def test_peak_threshold(threshold_db, warning):
if warning:
with pytest.warns(warning):
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=False)
else:
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=False)
@pytest.mark.parametrize("time, warning", [(-1, UserWarning),
(0, UserWarning),
(1/48000, UserWarning),
(3/48000, None),
(1, None),
(1000, None),
((4/48000)*(2**31), UserWarning),
])
def test_calc_alpha(time, warning):
if warning:
with pytest.warns(warning):
alpha, alpha_int = drcu.alpha_from_time(time, 48000)
else:
alpha, alpha_int = drcu.alpha_from_time(time, 48000)
@pytest.mark.parametrize("gain_db, warning", [(-2000, None),
(0, None),
(25, UserWarning)])
def test_db_gain(gain_db, warning):
if warning:
with pytest.warns(warning):
gain, gain_int = sc.db_to_qgain(gain_db)
else:
gain, gain_int = sc.db_to_qgain(gain_db)
@pytest.mark.parametrize("time, units, warning", [[10, "samples", None],
[128, "samples", None],
[1.7, "ms", None],
[0.94, "s", None],
[2, "s", None],
[-2, "s", UserWarning],
[2, "seconds", UserWarning]
])
def test_time_to_samples(time, units, warning):
if warning:
with pytest.warns(warning):
utils.time_to_samples(48000, time, units)
else:
utils.time_to_samples(48000, time, units)
if __name__ == "__main__":
test_peak_threshold(25)

View File

@@ -0,0 +1,116 @@
# Copyright 2024-2025 XMOS LIMITED.
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
import pytest
import numpy as np
import audio_dsp.dsp.utils as utils
import audio_dsp.dsp.types as types
# seed RNG to avoid collection failures
np.random.seed(0)
@pytest.mark.parametrize('x', (2*np.random.rand(100)-1)*2**64)
def test_float_s32_float(x):
x_s32 = types.float_s32(float(x))
x2 = float(x_s32)
tol = 2**x_s32.exp
assert np.isclose(x, x2, rtol=2**-31, atol=tol)
@pytest.mark.parametrize('x, Q', np.stack(((2*np.random.rand(100)-1),
np.random.randint(0, 30, size=100)),
axis=-1))
def test_float_s32_float_Q(x, Q):
x_s32 = types.float_s32(float(x), Q_sig=Q)
x2 = float(x_s32)
tol = 2**-Q
assert np.isclose(x, x2, rtol=2**-31, atol=tol)
@pytest.mark.parametrize('x', (2*np.random.rand(100)-1)*2**64)
def test_float_s32_abs(x):
x_s32 = types.float_s32(float(x))
x2 = float(abs(x_s32))
tol = 2**x_s32.exp
assert np.isclose(abs(x), x2, rtol=2**-31, atol=tol)
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_mult(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32*y_s32
xy = float(xy_s32)
tol = 2**xy_s32.exp
assert np.isclose(x*y, xy, rtol=2**-29, atol=tol)
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_div(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32/y_s32
xy = float(xy_s32)
tol = 2**xy_s32.exp
assert np.isclose(x/y, xy, rtol=2**-29, atol=tol)
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_add(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32 + y_s32
xy = float(xy_s32)
tol = 2**(max(x_s32.exp, y_s32.exp) + 2)
assert np.isclose(x + y, xy, rtol=2**-29, atol=tol)
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_subt(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32-y_s32
xy = float(xy_s32)
tol = 2**(max(x_s32.exp, y_s32.exp) + 1)
assert np.isclose(x-y, xy, rtol=2**-29, atol=tol)
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_gt(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32 > y_s32
xy = x > y
assert xy == xy_s32
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
def test_float_s32_lt(x, y):
x_s32 = types.float_s32(float(x))
y_s32 = types.float_s32(float(y))
xy_s32 = x_s32 < y_s32
xy = x < y
assert xy == xy_s32
if __name__ == "__main__":
for n in range(100):
# test_float_s32_float((2*np.random.rand(1)-1)*2**32)
test_float_s32_add((2*np.random.rand(1)-1)*2**27,
(2*np.random.rand(1)-1)*2**27)