بنقرة واحدة
new-number-type
// Scaffold a new number system type with all required files, CMake wiring, exception hierarchy, traits, tests, and numeric_limits. Use when adding a new arithmetic type to the Universal library.
// Scaffold a new number system type with all required files, CMake wiring, exception hierarchy, traits, tests, and numeric_limits. Use when adding a new arithmetic type to the Universal library.
Analyze a GitHub issue, explore related code, and propose or implement a fix. Use when the user asks to investigate, fix, or resolve a GitHub issue.
Build and test targets with both gcc and clang. Use when you need to build, compile, test, or verify code changes with dual-compiler validation.
| name | new-number-type |
| description | Scaffold a new number system type with all required files, CMake wiring, exception hierarchy, traits, tests, and numeric_limits. Use when adding a new arithmetic type to the Universal library. |
| user-invocable | true |
| argument-hint | <type-name> [template-params...] |
| allowed-tools | Read, Edit, Write, Glob, Grep, Bash |
Create all required files, CMake wiring, and test structure for a new number type in the Universal library.
$ARGUMENTS — the type name (e.g., takum) and optionally a description of the template parameters. If not provided, ask the user.
Ask the user:
integer<nbits> or 2-param like posit<nbits, es>)Read the matching skeleton template to use as the structural reference:
include/sw/universal/number/skeleton_1param/include/sw/universal/number/skeleton_2params/Read an existing similar type for behavioral reference (e.g., posit for tapered, cfloat for float, fixpnt for fixed-point).
These are hard-won lessons from past incidents. Violating them causes build failures or CI rejections.
uint8_t _bits; NOT uint8_t _bits{ 0 };ReportTrivialityOfType<T>() will static_assert fail if the type isn't trivial= defaultconstexpr if they call std::frexp, std::ldexp, std::log2, etc.constexpr if the conversion path uses only std::memcpy or integer arithmeticuniversal_arithmetic_exception / universal_internal_exceptionstd::runtime_error (NEVER from universal_*)TYPENAME_THROW_ARITHMETIC_EXCEPTION)#if !defined(TYPENAME_THROW_ARITHMETIC_EXCEPTION)
#define TYPENAME_THROW_ARITHMETIC_EXCEPTION 0
#if !defined(BLOCKBINARY_THROW_ARITHMETIC_EXCEPTION)
#define BLOCKBINARY_THROW_ARITHMETIC_EXCEPTION 0
#endif
#else
#if !defined(BLOCKBINARY_THROW_ARITHMETIC_EXCEPTION)
#define BLOCKBINARY_THROW_ARITHMETIC_EXCEPTION TYPENAME_THROW_ARITHMETIC_EXCEPTION
#endif
#endif
long double manual bit-shift division — use std::ldexp(1.0l, exponent) insteadblockbinary temporaries (clang doesn't zero stack like gcc)Create files in this exact order (dependencies flow top-to-bottom):
include/sw/universal/number/TYPE/| File | Purpose | Key contents |
|---|---|---|
TYPE_fwd.hpp | Forward declarations + type aliases | template<params> class TYPE; + convenience aliases |
exceptions.hpp | Exception hierarchy | TYPE_arithmetic_exception, TYPE_divide_by_zero, TYPE_internal_exception |
TYPE_impl.hpp | Main class implementation | Full class with constructors, operators, conversions |
numeric_limits.hpp | std::numeric_limits specialization | All required constants and static functions |
manipulators.hpp | type_tag(), to_binary(), color_print(), range() | Use enable_if_t<is_TYPE<T>> pattern |
attributes.hpp | Free functions for type properties | sign(), scale(), TYPE_range() |
TYPE.hpp | Umbrella header | Includes everything in correct order (see below) |
Umbrella header include order (MUST follow this sequence):
1. Compiler directives (compiler.hpp, architecture.hpp, bit_cast.hpp, long_double.hpp)
2. Required stdlib (<iostream>, <iomanip>)
3. Behavioral compilation switches (TYPENAME_THROW_ARITHMETIC_EXCEPTION, etc.)
4. Exception config forwarding to building blocks
5. Trait function headers (number_traits.hpp, arithmetic_traits.hpp)
6. exceptions.hpp
7. TYPE_fwd.hpp
8. TYPE_impl.hpp
9. TYPE_traits.hpp (from traits/ directory)
10. numeric_limits.hpp
11. manipulators.hpp
12. attributes.hpp
13. mathlib.hpp (if applicable)
include/sw/universal/traits/| File | Purpose |
|---|---|
TYPE_traits.hpp | is_TYPE trait, is_TYPE_trait struct, enable_if_TYPE alias |
The trait MUST match the exact template parameters of the class.
Create the test directory under the appropriate category. The repo uses
static/<CATEGORY>/<TYPE>/ where CATEGORY groups related types:
| Category | Types |
|---|---|
tapered/ | posit, takum, unum2 |
float/ | cfloat, bfloat16, dfloat, hfloat, e8m0 |
logarithmic/ | lns, dbns |
fixpnt/ | binary, decimal |
integer/ | binary, decimal, octal, hexadecimal |
block/ | microfloat, mxblock, nvblock |
static/<CATEGORY>/TYPE/ (or elastic/TYPE/ for adaptive types)
CMakeLists.txt
api/
api.cpp # Primary API test — start here
conversion/
(empty initially)
logic/
(empty initially)
arithmetic/
(empty initially)
math/
(empty initially)
complex/
(empty initially, only populated when BUILD_COMPLEX=ON)
Use the standard pattern. The compile_all label path follows:
"Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/<testdir>"
Check an existing sibling type's CMakeLists.txt for the exact label prefix.
| Number category | Encoding | Label prefix example |
|---|---|---|
floating-point | binary | cfloat, bfloat16, dd, microfloat |
floating-point | decimal | dfloat |
floating-point | hexadecimal | hfloat |
floating-point | logarithmic | lns, dbns |
floating-point | tapered | posit, takum |
fixed-point | binary | fixpnt |
fixed-point | decimal | dfixpnt |
integer | binary | integer |
integer | decimal | dint |
rational | binary | rational |
file(GLOB API_SRC "api/*.cpp")
file(GLOB CONVERSION_SRC "conversion/*.cpp")
file(GLOB LOGIC_SRC "logic/*.cpp")
file(GLOB ARITHMETIC_SRC "arithmetic/*.cpp")
file(GLOB MATH_SRC "math/*.cpp")
file(GLOB COMPLEX_SRC "complex/*.cpp")
# Example for lns: "Number Systems/static/floating-point/logarithmic/lns/api"
# Example for fixpnt: "Number Systems/static/fixed-point/binary/fixpnt/api"
# Example for dint: "Number Systems/static/integer/decimal/dint/api"
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/api" "${API_SRC}")
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/conversion" "${CONVERSION_SRC}")
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/logic" "${LOGIC_SRC}")
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/arithmetic" "${ARITHMETIC_SRC}")
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/math" "${MATH_SRC}")
compile_all("true" "TYPE" "Number Systems/static/<NUMBER_CATEGORY>/<ENCODING>/TYPE/complex" "${COMPLEX_SRC}")
4 insertion points (find the right alphabetical position among existing types):
Option definition (~line 160):
option(UNIVERSAL_BUILD_NUMBER_TYPE "Set to ON to build TYPE tests" OFF)
UNIVERSAL_BUILD_NUMBER_STATICS cascade (~line 831):
set(UNIVERSAL_BUILD_NUMBER_TYPE ON)
add_subdirectory block (~line 974):
if(UNIVERSAL_BUILD_NUMBER_TYPE)
add_subdirectory("static/<CATEGORY>/TYPE")
endif(UNIVERSAL_BUILD_NUMBER_TYPE)
CI_LITE cascade (~line 756, optional — only if portability-critical):
set(UNIVERSAL_BUILD_NUMBER_TYPE ON)
Create a minimal test that:
TYPENAME_THROW_ARITHMETIC_EXCEPTION 1type_tag() outputReportTrivialityOfType<TYPE<config>>()ReportTestSuiteHeader() / ReportTestSuiteResults() pattern| Parameter | Name | Notes |
|---|---|---|
| Total bits | nbits | NOT N or bits |
| Exponent bits | es | NOT E or exponent_bits |
| Fraction bits | rbits or fbits | Depends on type |
| Block type | bt | Default to uint8_t |
| In friend declarations | nnbits, nes, nbt | Prefix with n |
After creating all files:
cmake --build --preset gcc-debug --target TYPE_apibuild/gcc-debug/static/TYPE/TYPE_apicmake --build --preset clang-debug --target TYPE_apibuild/clang-debug/static/TYPE/TYPE_apistatic_assert failures)type_tag() produces expected outputFor behavioral reference, read an existing type that's similar:
| If your type is... | Study this implementation |
|---|---|
| Tapered floating-point | posit/posit_impl.hpp |
| Classic floating-point | cfloat/cfloat_impl.hpp |
| Fixed-point | fixpnt/fixpnt_impl.hpp |
| Logarithmic | lns/lns_impl.hpp |
| Integer | integer/integer_impl.hpp |
| Block format | mxblock/mxblock_impl.hpp |
| Double-double | dd/dd_impl.hpp |