Minor cleanups extra (#3026)
* Add missing words to doxygen in float.h and double.h
* Update tools/check_float_test_names.py to also check function returm-types
* Update tools/check_float_test_names.py to check function argument-types
* Update tools/check_float_test_names.py to check function argument-names
diff --git a/src/rp2_common/pico_double/include/pico/double.h b/src/rp2_common/pico_double/include/pico/double.h
index 185428c..004633e 100644
--- a/src/rp2_common/pico_double/include/pico/double.h
+++ b/src/rp2_common/pico_double/include/pico/double.h
@@ -205,12 +205,12 @@
#if !__PICO_DOUBLE_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline double int2double(int32_t i) { return (double)i; }
- static inline double uint2double(uint32_t i) { return (double)i; }
+ static inline double uint2double(uint32_t u) { return (double)u; }
#else
//! Convert a signed 32-bit integer to the nearest double
double int2double(int32_t i);
//! Convert an unsigned 32-bit integer to the nearest double
- double uint2double(uint32_t i);
+ double uint2double(uint32_t u);
#endif
#endif
@@ -218,12 +218,12 @@
#if !__PICO_DOUBLE_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline double int642double(int64_t i) { return (double)i; }
- static inline double uint642double(uint64_t i) { return (double)i; }
+ static inline double uint642double(uint64_t u) { return (double)u; }
#else
//! Convert a signed 64-bit integer to the nearest double
double int642double(int64_t i);
//! Convert an unsigned 64-bit integer to the nearest double
- double uint642double(uint64_t i);
+ double uint642double(uint64_t u);
#endif
#endif
@@ -231,7 +231,7 @@
#if !__PICO_DOUBLE_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline int32_t double2int_z(double d) { return (int32_t)d; }
- static inline int32_t double2uint_z(double d) { return (uint32_t)d; }
+ static inline uint32_t double2uint_z(double d) { return (uint32_t)d; }
#else
//! \brief Convert a double to a signed 32-bit integer, rounding towards zero.
//! On Arm this conversion is saturating (to INT32_MAX/INT32_MIN) for out of range input except when using `pico_double_compiler`
@@ -258,19 +258,19 @@
#endif
#if PICO_DOUBLE_HAS_FIX32_TO_DOUBLE_CONVERSIONS
-//! \brief Convert a signed 32-bit integer with the given number of fractional bits to the nearest double
+//! \brief Convert a signed 32-bit fixed-point integer with the given number of fractional bits to the nearest double
//! Out of range inputs will convert to +/- Infinity
double fix2double(int32_t m, int e);
-//! \brief Convert an unsigned 32-bit integer with the given number of fractional bits to the nearest double
+//! \brief Convert an unsigned 32-bit fixed-point integer with the given number of fractional bits to the nearest double
//! Out of range inputs will convert to +Infinity
double ufix2double(uint32_t m, int e);
#endif
#if PICO_DOUBLE_HAS_FIX64_TO_DOUBLE_CONVERSIONS
-//! \brief Convert a signed 64-bit integer with the given number of fractional bits to the nearest double
+//! \brief Convert a signed 64-bit fixed-point integer with the given number of fractional bits to the nearest double
//! Out of range inputs will convert to +/- Infinity
double fix642double(int64_t m, int e);
-//! \brief Convert an unsigned 64-bit integer with the given number of fractional bits to the nearest double
+//! \brief Convert an unsigned 64-bit fixed-point integer with the given number of fractional bits to the nearest double
//! Out of range inputs will convert to +Infinity
double ufix642double(uint64_t m, int e);
#endif
diff --git a/src/rp2_common/pico_float/include/pico/float.h b/src/rp2_common/pico_float/include/pico/float.h
index bf2ece7..f040e28 100644
--- a/src/rp2_common/pico_float/include/pico/float.h
+++ b/src/rp2_common/pico_float/include/pico/float.h
@@ -224,12 +224,12 @@
// for VFP the C cast is an assembly instruction anyway, so we prefer that over a function call
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline float int2float(int32_t i) { return (float)i; }
- static inline float uint2float(uint32_t i) { return (float)i; }
+ static inline float uint2float(uint32_t u) { return (float)u; }
#else
//! Convert a signed 32-bit integer to the nearest float
float int2float(int32_t i);
//! Convert an unsigned 32-bit integer to the nearest float
- float uint2float(uint32_t i);
+ float uint2float(uint32_t u);
#endif
#endif
@@ -237,12 +237,12 @@
#if !__PICO_FLOAT_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline float int642float(int64_t i) { return (float)i; }
- static inline float uint642float(uint64_t i) { return (float)i; }
+ static inline float uint642float(uint64_t u) { return (float)u; }
#else
//! Convert a signed 64-bit integer to the nearest float
float int642float(int64_t i);
//! Convert an unsigned 64-bit integer to the nearest float
- float uint642float(uint64_t i);
+ float uint642float(uint64_t u);
#endif
#endif
@@ -250,14 +250,14 @@
#if !__PICO_FLOAT_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline int32_t float2int_z(float f) { return (int32_t)f; }
- static inline int32_t float2uint_z(float f) { return (uint32_t)f; }
+ static inline uint32_t float2uint_z(float f) { return (uint32_t)f; }
#else
//! \brief Convert a float to a signed 32-bit integer, rounding towards zero.
//! On Arm this conversion is saturating (to INT32_MAX/INT32_MIN) for out of range input except when using `pico_float_compiler`
int32_t float2int_z(float f);
//! \brief Convert a float to an unsigned 32-bit integer, rounding towards zero
//! On Arm this conversion is saturating (to UINT32_MAX/UINT32_MIN) for out of range input except when using `pico_float_compiler`
- int32_t float2uint_z(float f);
+ uint32_t float2uint_z(float f);
#endif
#endif
@@ -265,31 +265,31 @@
#if !__PICO_FLOAT_ARM_OPTIMIZED
// for non Arm-optimized we may as well provide the function and let the compiler handle it
static inline int64_t float2int64_z(float f) { return (int64_t)f; }
- static inline int64_t float2uint64_z(float f) { return (uint64_t)f; }
+ static inline uint64_t float2uint64_z(float f) { return (uint64_t)f; }
#else
//! \brief Convert a float to a signed 64-bit integer, rounding towards zero.
//! On Arm this conversion is saturating (to INT64_MAX/INT64_MIN) for out of range input except when using `pico_float_compiler`
int64_t float2int64_z(float f);
//! \brief Convert a float to an unsigned 64-bit integer, rounding towards zero.
//! On Arm this conversion is saturating (to UINT64_MAX/UINT64_MIN) for out of range input except when using `pico_float_compiler`
- int64_t float2uint64_z(float f);
+ uint64_t float2uint64_z(float f);
#endif
#endif
#if PICO_FLOAT_HAS_FIX32_TO_FLOAT_CONVERSIONS
-//! \brief Convert a signed 32-bit integer with the given number of fractional bits to the nearest float
+//! \brief Convert a signed 32-bit fixed-point integer with the given number of fractional bits to the nearest float
//! Out of range inputs will convert to +/- Infinity
float fix2float(int32_t m, int e);
-//! \brief Convert an unsigned 32-bit integer with the given number of fractional bits to the nearest float
+//! \brief Convert an unsigned 32-bit fixed-point integer with the given number of fractional bits to the nearest float
//! Out of range inputs will convert to +Infinity
float ufix2float(uint32_t m, int e);
#endif
#if PICO_FLOAT_HAS_FIX64_TO_FLOAT_CONVERSIONS
-//! \brief Convert a signed 64-bit integer with the given number of fractional bits to the nearest float
+//! \brief Convert a signed 64-bit fixed-point integer with the given number of fractional bits to the nearest float
//! Out of range inputs will convert to +/- Infinity
float fix642float(int64_t m, int e);
-//! \brief Convert an unsigned 64-bit integer with the given number of fractional bits to the nearest float
+//! \brief Convert an unsigned 64-bit fixed-point integer with the given number of fractional bits to the nearest float
//! Out of range inputs will convert to +Infinity
float ufix642float(uint64_t m, int e);
#endif
diff --git a/test/pico_float_test/custom_double_funcs_test.c b/test/pico_float_test/custom_double_funcs_test.c
index 72892dd..6d95aea 100644
--- a/test/pico_float_test/custom_double_funcs_test.c
+++ b/test/pico_float_test/custom_double_funcs_test.c
@@ -30,8 +30,8 @@
static inline double ufix2double_24(uint32_t m) { return ufix2double(m, 24); }
static inline double ufix2double_32(uint32_t m) { return ufix2double(m, 32); }
-static inline double double2fix_12(int32_t m) { return double2fix(m, 12); }
-static inline double double2ufix_12(int32_t m) { return double2ufix(m, 12); }
+static inline int32_t double2fix_12(double d) { return double2fix(d, 12); }
+static inline uint32_t double2ufix_12(double d) { return double2ufix(d, 12); }
#endif
#if LIB_PICO_DOUBLE_COMPILER || defined(__riscv)
diff --git a/test/pico_float_test/custom_float_funcs_test.c b/test/pico_float_test/custom_float_funcs_test.c
index 62e4a1c..728f0ca 100644
--- a/test/pico_float_test/custom_float_funcs_test.c
+++ b/test/pico_float_test/custom_float_funcs_test.c
@@ -28,8 +28,8 @@
static inline float ufix2float_16(uint32_t m) { return ufix2float(m, 16); }
static inline float ufix2float_24(uint32_t m) { return ufix2float(m, 24); }
-static inline float float2fix_12(int32_t m) { return float2fix(m, 12); }
-static inline float float2ufix_12(int32_t m) { return float2ufix(m, 12); }
+static inline int32_t float2fix_12(float f) { return float2fix(f, 12); }
+static inline uint32_t float2ufix_12(float f) { return float2ufix(f, 12); }
#endif
#if LIB_PICO_FLOAT_COMPILER || defined(__riscv)
@@ -72,7 +72,7 @@
pico_default_asm_volatile("b int2float");
}
-float __attribute__((naked)) call_uint2float(uint32_t i) {
+float __attribute__((naked)) call_uint2float(uint32_t u) {
pico_default_asm_volatile("b uint2float");
}
@@ -88,7 +88,7 @@
pico_default_asm_volatile("b fix2float");
}
-float __attribute__((naked)) call_ufix2float(int32_t i, uint32_t n) {
+float __attribute__((naked)) call_ufix2float(uint32_t u, uint32_t n) {
pico_default_asm_volatile("b ufix2float");
}
diff --git a/tools/check_float_test_names.py b/tools/check_float_test_names.py
index 3413085..55b51b4 100755
--- a/tools/check_float_test_names.py
+++ b/tools/check_float_test_names.py
@@ -18,29 +18,66 @@
Check("double", "src/rp2_common/pico_double/include/pico/double.h", "test/pico_float_test/custom_double_funcs_test.c"),
)
-CONVERSION_TYPES = set((
+BASE_TYPES = {
# integral types
- "int", "uint", "int64", "uint64",
+ "int32_t": "i",
+ "uint32_t": "u",
+ "int64_t": "i64",
+ "uint64_t": "u64",
# floating-point types
- "float", "double",
+ "float": "f",
+ "double": "d",
+}
+
+CONVERSION_TYPES = {
+ # integral types
+ "int": "int32_t",
+ "uint": "uint32_t",
+ "int64": "int64_t",
+ "uint64": "uint64_t",
+ # floating-point types
+ "float": "float",
+ "double": "double",
# fixed-point types
- "fix", "ufix", "fix64", "ufix64",
+ "fix": "int32_t",
+ "ufix": "uint32_t",
+ "fix64": "int64_t",
+ "ufix64": "uint64_t",
# integral types that round towards zero
- "int_z", "uint_z", "int64_z", "uint64_z",
+ "int_z": "int32_t",
+ "uint_z": "uint32_t",
+ "int64_z": "int64_t",
+ "uint64_z": "uint64_t",
# fixed-point types that round towards zero
- "fix_z", "ufix_z", "fix64_z", "ufix64_z",
+ "fix_z": "int32_t",
+ "ufix_z": "uint32_t",
+ "fix64_z": "int64_t",
+ "ufix64_z": "uint64_t",
# other "types" used in the test functions
- "float_8", "float_12", "float_16", "float_24", "float_28", "float_32",
- "double_8", "double_12", "double_16", "double_24", "double_28", "double_32",
- "fix_12", "ufix_12",
-))
+ "float_8": "float",
+ "float_12": "float",
+ "float_16": "float",
+ "float_24": "float",
+ "float_28": "float",
+ "float_32": "float",
+ "double_8": "double",
+ "double_12": "double",
+ "double_16": "double",
+ "double_24": "double",
+ "double_28": "double",
+ "double_32": "double",
+ "fix_12": "int32_t",
+ "ufix_12": "uint32_t",
+}
if ENFORCE_SEQUENTIAL_SUFFIXES:
@dataclass
class ConversionFunc:
name: str
+ return_type: str
from_type: str
to_type: str
+ input_args: list
num_input_args: int
tested: bool = False
last_test: str = ""
@@ -49,20 +86,46 @@
@dataclass
class ConversionFunc:
name: str
+ return_type: str
from_type: str
to_type: str
+ input_args: list
num_input_args: int
tested: bool = False
-def add_conversion_function(conversion_functions, conversion_function, from_type, to_type, num_input_args, filename, lineno):
+def add_conversion_function(conversion_functions, conversion_function, return_type, from_type, to_type, input_args, filename, lineno):
if conversion_function in conversion_functions:
raise Exception(f"{filename}:{lineno} Conversion function {conversion_function} appears twice")
else:
- if from_type not in CONVERSION_TYPES:
- raise Exception(f"{filename}:{lineno} Conversion function {conversion_function} converts from unknown type {from_type}")
- if to_type not in CONVERSION_TYPES:
- raise Exception(f"{filename}:{lineno} Conversion function {conversion_function} converts to unknown type {to_type}")
- conversion_functions[conversion_function] = ConversionFunc(conversion_function, from_type, to_type, num_input_args)
+ check_func_args(conversion_function, input_args, from_type, to_type, return_type, filename, lineno)
+ conversion_functions[conversion_function] = ConversionFunc(conversion_function, return_type, from_type, to_type, input_args, len(input_args))
+
+def parse_func_args(s):
+ # converts e.g. "float f, int e" to (("float", "f"), ("int", "e"))
+ return list(a.strip().split(' ') for a in s.split(","))
+
+def check_func_args(func, args, from_type, to_type, return_type, filename, lineno):
+# print(func, args)
+ if from_type not in CONVERSION_TYPES:
+ raise Exception(f"{filename}:{lineno} Conversion function {conversion_function} converts from unknown type {from_type}")
+ if to_type not in CONVERSION_TYPES:
+ raise Exception(f"{filename}:{lineno} Conversion function {conversion_function} converts to unknown type {to_type}")
+ implied_return_type = type_to_base_type(to_type)
+ if return_type != implied_return_type:
+ raise Exception(f"{filename}:{lineno} Expected {conversion_function} to return {implied_return_type}, not {return_type}")
+ first_arg = args[0]
+ arg_type, arg_name = first_arg
+ implied_from_type = type_to_base_type(from_type)
+ if arg_type != implied_from_type:
+ raise Exception(f"{filename}:{lineno} Expected {func} to have {implied_from_type} type for it's first argument, not {arg_type}")
+ expected_name = type_to_short_type(arg_type)
+ if expected_name == "i64":
+ expected_name = "i"
+ elif expected_name == "u64":
+ expected_name = "u"
+ if not (re.match("u?fix(?:64)?2", func) and arg_name == "m"): # ignore the mantissa argument of fixed-point conversion functions
+ if arg_name != expected_name:
+ raise Exception(f"{filename}:{lineno} Expected first argument of {func} (of type {arg_type}) to be named {expected_name}, not {arg_name}")
@dataclass
class TestMacro:
@@ -140,22 +203,14 @@
else:
return ord(alpha1) - ord(alpha2) == 1
+def type_to_base_type(t):
+ if t in BASE_TYPES:
+ return t
+ return CONVERSION_TYPES[t]
+
def type_to_short_type(t):
- assert(t in CONVERSION_TYPES)
- if t in ("int", "fix", "int_z", "fix_z") or t.startswith("fix_"):
- return "i"
- elif t in ("uint", "ufix", "uint_z", "ufix_z") or t.startswith("ufix_"):
- return "u"
- elif t in ("int64", "fix64", "int64_z", "fix64_z"):
- return "i64"
- elif t in ("uint64", "ufix64", "uint64_z", "ufix64_z"):
- return "u64"
- elif t == "float" or t.startswith("float_"):
- return "f"
- elif t == "double" or t.startswith("double_"):
- return "d"
- else:
- raise Exception(f"Couldn't determine short_type for {t}")
+ b = type_to_base_type(t)
+ return BASE_TYPES[b]
if __name__ == "__main__":
@@ -169,13 +224,22 @@
# strip trailing comments
line = re.sub(r"\s*//.*$", "", line)
if line:
- if m := re.match(r"^\w+ ((\w+)2(\w+))\(([^\)]+)\);$", line):
- conversion_function = m.group(1)
- from_type = m.group(2)
- to_type = m.group(3)
- num_input_args = len(m.group(4).split(","))
+ if m := re.match(r"^(\w+) ((\w+)2(\w+))\(([^\)]+)\);$", line):
+ return_type = m.group(1)
+ conversion_function = m.group(2)
+ from_type = m.group(3)
+ to_type = m.group(4)
+ input_args = parse_func_args(m.group(5))
#print(lineno, line, conversion_function)
- add_conversion_function(conversion_functions, conversion_function, from_type, to_type, num_input_args, check.header_file, lineno)
+ add_conversion_function(conversion_functions, conversion_function, return_type, from_type, to_type, input_args, check.header_file, lineno)
+ elif m := re.search(r"static inline (\w+) ((\w+)2(\w+))\(([^\)]+)\)", line):
+ return_type = m.group(1)
+ conversion_function = m.group(2)
+ from_type = m.group(3)
+ to_type = m.group(4)
+ input_args = parse_func_args(m.group(5))
+ check_func_args(conversion_function, input_args, from_type, to_type, return_type, check.header_file, lineno)
+ #print(lineno, line, conversion_function)
test_macros = dict()
function_groups = dict()
@@ -252,37 +316,45 @@
conversion_function = m.group(1)
from_type = m.group(2)
to_type = m.group(3)
- num_input_args = len(m.group(4).split(","))
+ input_args = parse_func_args(m.group(4))
+ num_input_args = len(input_args)
#print(lineno, line, conversion_function)
if conversion_function not in conversion_functions:
raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has no counterpart in {check.header_file}")
else:
if num_input_args != conversion_functions[conversion_function].num_input_args:
- raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has a different number of arguments to the counterpart in {check.header_file}")
- elif m := re.match(r"^\w+ __attribute__\(\(naked\)\) (call_((\w+)2(\w+)))\(([^\)]+)\)", line):
- conversion_function = m.group(1)
- base_function = m.group(2)
- from_type = m.group(3)
- to_type = m.group(4)
- num_input_args = len(m.group(5).split(","))
+ raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has a different number of arguments ({num_input_args}) to the counterpart in {check.header_file} ({conversion_functions[conversion_function].num_input_args})")
+ elif m := re.match(r"^(\w+) __attribute__\(\(naked\)\) (call_((\w+)2(\w+)))\(([^\)]+)\)", line):
+ return_type = m.group(1)
+ conversion_function = m.group(2)
+ base_function = m.group(3)
+ from_type = m.group(4)
+ to_type = m.group(5)
+ input_args = parse_func_args(m.group(6))
+ num_input_args = len(input_args)
#print(lineno, line, conversion_function)
if base_function not in conversion_functions:
raise Exception(f"{check.tests_file}:{lineno} {conversion_function} exists but {base_function} doesn't exist")
else:
if num_input_args != conversion_functions[base_function].num_input_args:
- raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has a different number of arguments to {base_function}")
- add_conversion_function(conversion_functions, conversion_function, from_type, to_type, num_input_args, check.tests_file, lineno)
- elif m := re.match(r"^static inline (?:float|double) ((\w+)2(\w+_\d+))\(([^\)]+)\)", line):
- conversion_function = m.group(1)
- from_type = m.group(2)
- to_type = m.group(3)
- num_input_args = len(m.group(4).split(","))
+ raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has a different number of arguments ({num_input_args}) to {base_function} ({conversion_functions[base_function].num_input_args})")
+ add_conversion_function(conversion_functions, conversion_function, return_type, from_type, to_type, input_args, check.tests_file, lineno)
+ elif m := re.match(r"^static inline (\w+) ((\w+)2(\w+_\d+))\(([^\)]+)\)", line):
+ return_type = m.group(1)
+ conversion_function = m.group(2)
+ from_type = m.group(3)
+ to_type = m.group(4)
+ input_args = parse_func_args(m.group(5))
+ num_input_args = len(input_args)
#print(lineno, line, conversion_function)
- m = re.match(r"^static inline (?:float|double) (\w+2\w+)_\d+\(", line)
+ m = re.match(r"^static inline (?:\w+) (\w+2\w+)_\d+\(", line)
base_function = m.group(1)
if base_function not in conversion_functions:
raise Exception(f"{check.tests_file}:{lineno} {conversion_function} exists but {base_function} doesn't exist")
- add_conversion_function(conversion_functions, conversion_function, from_type, to_type, num_input_args, check.tests_file, lineno)
+ else:
+ if num_input_args != conversion_functions[base_function].num_input_args and not re.search(r'_\d+$', conversion_function):
+ raise Exception(f"{check.tests_file}:{lineno} {conversion_function} has a different number of arguments ({num_input_args}) to {base_function} ({conversion_functions[base_function].num_input_args})")
+ add_conversion_function(conversion_functions, conversion_function, return_type, from_type, to_type, input_args, check.tests_file, lineno)
elif m := re.match(r"^printf\(\"((\w+)2(\w+))\\n\"\);$", line):
function_group = m.group(1)
from_type = m.group(2)