ashvardanian / ashvardanian/NumKong

Feature: Add a truncation mode to nk.astype for float-to-integer casts

Open
#377 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.