# Trying to understand the range of Improved Perlin noise

I've been implementing Improved Perlin Noise for a small library I'm writing. Everything was hunky dory when it was just in the 3rd dimension, but I recently expanded to the 1st, 2nd, and 4th dimension, which is where things started get weird.

I originally thought that the range of Improved Perlin was +-1.0. When I implemented the 1st dimension version, I noticed that the unmodified range was +-0.5, ie, you had to multiply the result by 2, but figured nothing of it. 2nd dimension worked just like 3rd, with both working within the +-1.0 range. Then when I got to 4th, I ran a large number of samples and saw that I was getting results outside the -1.0 to +1.0 range.

I started Googling, and apparently the +-1.0 range is a common misconception? The solution I've read in a couple places, which is +-1/2(sqrt(N)), where N is the number of dimensions, implies the following ranges for dimensions 1 through 4:

0.5, ~0.71, ~0.87, 1, respectively

However, the only version I have which matches this is the 1st dimension, which as I said, works out to +-0.5 before multiplying by 2. For dimensions 2 and 3, I get +-1.0 without any need to modify the result, and for the 4th dimension, I believe my results are actually in the range of the 6th dimension according to that solution.

The following is my code: https://pastebin.com/CpAi3PUF And for those who aren't familiar, it's Cython, so yes, a weird Frankenstein of Python and C.

I use the following code to test the ranges of each dimension: https://pastebin.com/yUpw1Z00 Since my method involves just running tons of random inputs over and over, I did run this test a few times to make sure the results are consistent, which they are, and here is an example of the output:

DIM1 - Minimum: -0.999999999999943 | Maximum: 0.9999999999871175 | Average: 0.0003455999808678627
DIM2 - Minimum: -0.9999515602331069 | Maximum: 0.999900249691747 | Average: -0.00011840974404335401
DIM3 - Minimum: -0.9932063986908607 | Maximum: 0.9931959744642007 | Average: -0.00010701170753012655
DIM4 - Minimum: -1.0576886515898196 | Maximum: 1.123720946368049 | Average: 0.00022555631399532482


You can clearly see that as my code is written, dimensions 1 through 3 have a limit of +1.0, and then with the 4So clearly there is some contradiction between the alleged result ranges, and the code I'm implementing. The 3rd and 4th dimensions were implemented straight from Perlin's own example code.

3rd Dimension: https://mrl.nyu.edu/~perlin/noise/

4th dimension: https://mrl.nyu.edu/~perlin/noise/ImprovedNoise4D.java

The only major changes I've made to the implementation are in the grad functions, where I use what is essentially a switch case, rather than Perlin's fancy pants (but extremely expensive) bitshifting method. But afaik doing so is functionally equivalent.

Can anyone provide some insight as to what is going on? What is causing the difference between the supposed expected ranges, and my actual results? And what can I do to get the 4th dimension "in shape", like how modifying the 1st dimension is required?

Thanks so much for any help.

• Please embed the relevant sample of your code in the question itself, not in an external link. – DMGregory May 11 at 11:48
• @DMGregory is that really the proper way to do it, even when my code is 275 lines? – user2875252 May 11 at 18:51
• The key words here are "relevant sample" — you can communicate the approach you're using in far fewer than 275 lines, and that makes it much more likely someone who sees your question will be able to understand it and answer it. Relying on an outside link where they have to read all your code is a good way to scare folks off. ;) – DMGregory May 11 at 18:56
• Except the whole problem is that there is a clear discrepancy between my implementation and the expected results, so I really don't see how anyone would be able to answer what the issue is without seeing exactly my implementation. – user2875252 May 12 at 0:54
• Yes, that's exactly why it's important to include a relevant sample of your code in the question itself. – DMGregory May 12 at 1:23