Skip to main content

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.

설치로 이동

소스 정보

저장소
stillwater-sc/universal
최근 소스 활동
2026년 3월 7일 22:17
감지된 SKILL.md 언어
영어
스타
501
포크
72

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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
# Scaffold a New Number System Type Create all required files, CMake wiring, and test structure for a new number type in the Universal library. ## Arguments `$ARGUMENTS` — the type name (e.g., `takum`) and optionally a description of the template parameters. If not provided, ask the user. ## Before You Start 1. Ask the user: - How many template parameters? (1-param like `integer<nbits>` or 2-param like `posit<nbits, es>`) - Is this a **static** (fixed-size) or **elastic** (adaptive) type? - What category? (integer, fixed-point, float, tapered, logarithmic, block format) - What internal building blocks does it use? (blockbinary, blocksignificand, blocktriple, etc.) 2. Read the matching skeleton template to use as the structural reference: - 1-param: `include/sw/universal/number/skeleton_1param/` - 2-param: `include/sw/universal/number/skeleton_2params/` 3. Read an existing similar type for behavioral reference (e.g., posit for tapered, cfloat for float, fixpnt for fixed-point). ## CRITICAL Rules These are hard-won lessons from past incidents. Violating them causes build failures or CI rejections. ### Triviality - Number types MUST be trivially constructible - **NO in-class member initializers**: use `uint8_t _bits;` NOT `uint8_t _bits{ 0 };` - `ReportTrivialityOfType<T>()` will `static_assert` fail if the type isn't trivial - Default constructor must have empty body or be `= default` ### Constexpr - Do NOT mark constructors/assignment operators `constexpr` if they call `std::frexp`, `std::ldexp`, `std::log2`, etc. - Only use `constexpr` if the conversion path uses only `std::memcpy` or integer arithmetic ### Exception Hierarchy - Number systems inherit from `universal_arithmetic_exception` / `universal_internal_exception` - Internal building blocks inherit from `std::runtime_error` (NEVER from `universal_*`) - Dependencies flow strictly **downward**: number system -> internal block -> never upward - Each type has its OWN exception guard macro (e.g., `TYPENAME_THROW_ARITHMETIC_EXCEPTION`) - The umbrella header forwards its exception config to building blocks: ```cpp #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 ``` ### Portability - Never use `long double` manual bit-shift division — use `std::ldexp(1.0l, exponent)` instead - Always initialize `blockbinary` temporaries (clang doesn't zero stack like gcc) - Test with BOTH gcc AND clang before committing ## File Creation Order Create files in this exact order (dependencies flow top-to-bottom): ### Step 1: Header files in `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): ```text 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) ``` ### Step 2: Traits file in `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. ### Step 3: Test directory structure 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 | ```text 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) ``` ### Step 4: Test CMakeLists.txt 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` | ```cmake 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}") ``` ### Step 5: CMake wiring in root CMakeLists.txt **4 insertion points** (find the right alphabetical position among existing types): 1. **Option definition** (~line 160): ```cmake option(UNIVERSAL_BUILD_NUMBER_TYPE "Set to ON to build TYPE tests" OFF) ``` 2. **UNIVERSAL_BUILD_NUMBER_STATICS cascade** (~line 831): ```cmake set(UNIVERSAL_BUILD_NUMBER_TYPE ON) ``` 3. **add_subdirectory block** (~line 974): ```cmake if(UNIVERSAL_BUILD_NUMBER_TYPE) add_subdirectory("static/<CATEGORY>/TYPE") endif(UNIVERSAL_BUILD_NUMBER_TYPE) ``` 4. **CI_LITE cascade** (~line 756, optional — only if portability-critical): ```cmake set(UNIVERSAL_BUILD_NUMBER_TYPE ON) ``` ### Step 6: Initial api.cpp test Create a minimal test that: - Includes the umbrella header - Sets `TYPENAME_THROW_ARITHMETIC_EXCEPTION 1` - Tests default construction - Tests construction from native types (int, float, double) - Tests `type_tag()` output - Tests `ReportTrivialityOfType<TYPE<config>>()` - Uses `ReportTestSuiteHeader()` / `ReportTestSuiteResults()` pattern - Has full exception catch blocks ## Template Parameter Naming Conventions | 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` | ## Verification Checklist After creating all files: 1. Build with gcc: `cmake --build --preset gcc-debug --target TYPE_api` 2. Run the test: `build/gcc-debug/static/TYPE/TYPE_api` 3. Build with clang: `cmake --build --preset clang-debug --target TYPE_api` 4. Run the clang test: `build/clang-debug/static/TYPE/TYPE_api` 5. Verify triviality passes (no `static_assert` failures) 6. Verify `type_tag()` produces expected output ## Reference Implementations For 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` |
GitHub에서 보기