Skip to content

[BUG] linearstep is not guaranteed to return exactly 0 or 1 outside the edges #2063

@roelandschoukens

Description

@roelandschoukens

For x > e2 and e1 < e2, linearstep(e1, e2, x) should return 1.0. This however isn't guaranteed by the implementation in stdosl.h, due to possible rounding errors.

I think on platforms that exactly follow IEEE this is in fact guaranteed, but many platforms, especially with GPU targets, have optimisations with weaker error guarantees than what is required by IEEE floating point math. (see for example div.approx in PTX)

This is the implementation in stdosl.h:

float linearstep (float edge0, float edge1, float x) {
    float result;
    if (edge0 != edge1) {
        float xclamped = clamp (x, edge0, edge1);
        result = (xclamped - edge0) / (edge1 - edge0);
    } else {  // special case: edges coincide
        result = step (edge0, x);
    }
    return result;
}

A possible fix: since in the if branch we know edge0 is not equal to edge1, the following is mathematically equivalent, but it is logically guaranteed to return exactly 1 for x > e2 and e1 < e2:

    if (edge0 != edge1) {
        result = clamp((x - edge0) / (edge1 - edge0), 0, 1);
    } else ....

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions