Orvid / Caprica

A compiler for the Papyrus scripting language used by the Creation Engine.
MIT License
84 stars 15 forks source link

Unexpected behavior with certain op-equals operations on array elements #11

Open EyeDeck opened 6 years ago

EyeDeck commented 6 years ago

I'm not sure if this project is still active, but I still use Caprica constantly because I appreciate the faster compile speed and language extensions, so I'll leave this here anyway.

I was profiling a bit of code that looks like this, tweaking a mediocre random number generator I wrote to be "good enough", but more importantly is like 200x faster than Utility.RandomInt/Float because it isn't a delayed function.

    LCG n = GetLCG()
    float[] weights = new float[10]
    float totalWeight = 0
    for int i = 0 to 9
        weights[i] = (i+1)*0.1
        totalWeight += weights[i]
    endfor

    int[] bins = new int[10]
    for int i = 0 to 10000
        bins[WeightedRandom(n, weights, 5.5)] += 1
    endfor

So I noticed that bins[] was coming out with a uniform distribution, which is wrong, and that WeightedRandom() was getting run 20k times instead of the intended 10k. Obviously that means that that line of code is equivalent to

    bins[WeightedRandom(n, weights, 5.5)] = bins[WeightedRandom(n, weights, 5.5)] + 1

Tweaking it just slightly to pre-calculate the index fixed it, e.g.

    int index = WeightedRandom(n, weights, 5.5)
    bins[index] += 1

I suppose this makes sense in a way, but it's something to be aware of in case you're trying to write lazy test code like me.

Orvid commented 6 years ago

This is largely a result of how Caprica implements compilation... In theory it's possible to fix, but is non-trivial gen Caprica's design :(

EyeDeck commented 6 years ago

Ah well, I wouldn't worry about it too much then. I doubt anyone other than me has ever run into this, and Caprica is still so criminally underrated that I'd be surprised if anyone else ever will. For example, just last week I realized that Caprica allows for semi-proper multi-dimensional arrays in Papyrus. That may seem trivial, but little things like that can make all the difference between easy and impossible. In other words, I very much appreciate the work you've put into this.