Skip to content

RingBuffer.Resample repeats source elements unevenly because of banker's rounding, and its docs promise linear interpolation it doesn't do #88

Closed

Description

@matt-edmondson

What's wrong

The XML doc on RingBuffer<T>.Resample (Containers/RingBuffer.cs:237) says it "preserves the data pattern by applying simple linear interpolation". It also says that when upsampling, new values are created between existing ones.

The implementation (RingBuffer.cs:274-275) does not interpolate. It picks the nearest existing element:

double oldIndex = (double)i * (oldCount - 1) / Math.Max(length - 1, 1);
int index = (int)Math.Round(oldIndex);

Nearest-neighbour is unavoidable for a generic T. The problem is Math.Round, which defaults to MidpointRounding.ToEven. For common ratios the mapping often lands exactly on .5, and every such tie goes to the even index. Some source elements then appear three times while their neighbours appear once, which distorts the resampled shape.

Reproduction (verified)

new RingBuffer<float>([0, 10], 2).Resample(3);        // [0, 0, 10]
new RingBuffer<float>([0, 1, 2, 3, 4], 5).Resample(9); // [0,0,1,2,2,2,3,4,4]
new RingBuffer<float>([0, 1, 2], 3).Resample(5);       // [0,0,1,2,2]

In the 5→9 case, element 2 appears three times while elements 1 and 3 each appear once.

The existing test ResampleWithSpecificValues_CorrectlyInterpolates (Containers.Test/RingBufferTests.cs:221-235) has a comment saying it expects 10, 15, 20, 25, 30. The actual output is 10, 10, 20, 30, 30. The test passes only because it asserts indices 0, 2 and 4.

Why it matters

Resample is offered for resampling time series and changing sample rates. A caller who relies on the documented interpolation, or at least on even duplication of samples, gets a distorted signal with no error.

Suggested fix / acceptance criteria

Activity

  1. matt-edmondson commented on Sep 28, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    Notes: Centre sampling, (int)((i + 0.5) * oldCount / length), gives the evenest spread and avoids floating-point ties altogether. Assert the full output arrays in the new tests.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions