Skip to content

Utils.makeInt32Range is implemented incorrectly #24

@Niko-sk2x

Description

@Niko-sk2x

This has been found by DaPorkchop_ while working on another project

This method:

public static double makeInt32Range(double n) {
if (n >= 1073741824.0) {
return (2.0 * n % 1073741824.0) - 1073741824.0;
} else if (n <= -1073741824.0) {
return (2.0 * n % 1073741824.0) + 1073741824.0;
} else {
return n;
}
}

has been originally ported from the following C code in libnoise:

  inline double MakeInt32Range (double n)
  {
    if (n >= 1073741824.0) {
      return (2.0 * fmod (n, 1073741824.0)) - 1073741824.0;
    } else if (n <= -1073741824.0) {
      return (2.0 * fmod (n, 1073741824.0)) + 1073741824.0;
    } else {
      return n;
    }
  }

But because of operator precedence in java, the java code is actually equivalent to this

    public static double makeInt32Range(double n) {
        if (n >= 1073741824.0) {
            return ((2.0 * n) % 1073741824.0) - 1073741824.0;
        } else if (n <= -1073741824.0) {
            return ((2.0 * n) % 1073741824.0) + 1073741824.0;
        } else {
            return n;
        }
    }

Where in the original C code, modulo should take precedence.

For values of n between k * 1073741824 and k * 1073741824 + 536870912 for integer k >= 1 (and similar for negative range) this just happens to output the same values, but otherwise for n > 1073741824 the result will be always negative (and similarly for n < -1073741824 the result will be always positive) instead of repeating the entire range from -1073741824 to 1073741824.

Changing this now may be considered a breaking change as there could be terrain generators that would generate different terrain with this fixed.

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