ashvardanian / ashvardanian/NumKong
Feature: Add a truncation mode to nk.astype for float-to-integer casts
- Dominant language
- C
- Stars
- 1.9k
- Forks
- 133
- Avg merge
- 18h 28m
- Merged PRs (30d)
- 3
Description
## Request
Add an explicit truncate-toward-zero mode for float-to-integer conversions in `nk.astype`.
## Why
`nk.astype` currently rounds float inputs to the nearest even integer and saturates overflow. That is useful for image operations that need rounded pixels. Other image pipelines already clip values to the destination range and then rely on NumPy `astype` to discard the fractional part. Those paths need `1.9 -> 1`, while the current NumKong conversion produces `1.9 -> 2`.
This matters independently of the buffer-first API from #368: the current conversion cannot replace a NumPy cast when truncation is part of the result contract.
## Proposed API
```python
result = nk.astype(values, "uint8", rounding="truncate")
nk.astype(values, "uint8", rounding="truncate", out=output)
```
`rounding="nearest_even"` can remain the default, preserving the current behavior. The exact parameter name is flexible; the important part is an explicit, documented truncation mode.
## Contract
For float-to-integer conversions with truncation enabled:
- discard the fractional part toward zero: `-1.9 -> -1`, `-0.5 -> 0`, `0.5 -> 0`, `1.9 -> 1`;
- saturate values outside the destination integer range after truncation;
- preserve the existing NaN and infinity rules;
- retain the existing shape, arbitrary-rank input, strided-input, and `out=` contracts from #368;
- reject or document the mode for conversions that are not float-to-integer.
For the common clipped uint8 route, the intended behavior is:
```python
values = np.clip(values, 0, 255)
expected = values.astype(np.uint8)
actual = nk.astype(values, "uint8", rounding="truncate")
np.testing.assert_array_equal(actual, expected)
```
## Tests
Cover positive and negative fractional values, half-integers, integer boundaries, clipped and unclipped overflow, NaN, infinities, contiguous and strided inputs, and caller-owned `out` buffers.
Contributor guide
Research direction
Start at the nk.astype entry point and its existing conversion tests, then trace the current float-to-integer behavior and the contracts carried over from #368. Done means an explicit truncation mode handles the listed fractional, boundary, NaN, infinity, strided, and out-buffer cases while preserving the default behavior and documenting or rejecting unsupported conversions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, numpy, python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100