Neos-Metaverse / NeosPublic

A public issue/wiki only repository for the NeosVR project
193 stars 9 forks source link

Separate "modulo" and "remainder" nodes #3169

Closed iamgreaser closed 3 years ago

iamgreaser commented 3 years ago

EDIT: It was brought to my attention that the modulo node does, in fact, exist, and it's called "Repeat" for some bizarre reason. Therefore, this issue is not really an "enhancement" but a "tweak".

Is your feature request related to a problem? Please describe.

Please remind me if there is a proper modulo node and not just a truncation remainder node, I don't have Neos open right now but if I recall correctly it only provides a truncation remainder. Anyway, here comes the issue.

There is a common set of workarounds needed whenever a programming language makes the mortal sin of providing a % operator which does truncation remainder instead of modulo. It is likely that LogiX did whatever C# did, which may be based on whatever C did and/or whatever the relevant CPUs ended up doing because reasons. Either way, LogiX commits said mortal sin.

In general, the only way to sanely use the % node at the moment is in the form of (((x % D) + D) % D) unless you want things to break whenever the x input goes negative.

Remainder and modulo do the same thing when both inputs are positive, but as soon as a negative numerator input makes its way in, they differ - modulo continues the pattern intuitively, while truncating remainder starts moving into negatives and ultimately creates a discontinuity in terms of the period.

Because the % node already exists, we cannot simply change it to use modulo, as it might actually break something, despite probably fixing a lot of other things.

Relevant issues

Nothing seems to directly address this, but implementing this as-is will make some progress towards #795 which pertains to giving intuitive names for various nodes.

Describe the solution you'd like

Add a "Mod" node, short for "Modulus", and place it under Operators.

Rename the % node to "Rem", short for "Remainder". If someone actually manages to successfully find a valid reason for using this then they can choose it explicitly.

Or maybe rename it to "Truncating Remainder" and bury it somewhere under Math, because I can guarantee it's not what you want.

Describe alternatives you've considered

The usual (((x % D) + D) % D) workaround as mentioned above.

Alternatively, based on the definition of a remainder, one can do x - floor(x / D), but I suspect the numerical accuracy is worse.

Additional context

Languages which have both truncation remainder and modulus under explicit names include Cobol, Common Lisp, Scheme. Cobol and Common Lisp both call these rem and mod, while Scheme uses the longer names of remainder and modulo.

Languages which present % as modulus include Lua, Perl 5, Pure Data, Python, Raku, Ruby, Tcl 8.6. Emacs Lisp presents it as mod, and appears to not have truncation remainder.

Truncation division does have valid applications for when one is multiplying against a vector magnitude or a speed or a velocity, but I have never seen a valid application for truncation remainder.

Floor division and modulo, on the other hand, are often used with grids to compute cell position and offset within a cell, and modulo is often used for periodic stuff.

Aerizeon commented 3 years ago

Does the Repeat Node do what you want? (Located under Math in the LogiX browser)

Example

iamgreaser commented 3 years ago

...what? That's actually the modulo node?

OK, I think this issue's now fundamentally about renaming and rearranging two nodes which exist.

mralext20 commented 3 years ago

re: renaming etc, duplicate of #795 ?

iamgreaser commented 3 years ago

Possibly... I'll weigh in on the "Repeat" node, but the remaining aspect which I'm still not entirely sure about the "duplicateness" of is that I feel that Neos ends up encouraging people to use the wrong remainder node.

Frooxius commented 3 years ago

Repeat is common name for this function in this context, especially in game programming. Unity uses the same name for this function for example: https://docs.unity3d.com/ScriptReference/Mathf.Repeat.html

I'm not sure that we'd want to change its name, as it would make things more inconsistent - what would be more intuitive to you, will be less intuitive and bizarre to others. This is more issue for documentation and search-ability.

Similarly % is the same modulo operation that you find in a number of programming languages as well - it's how it's commonly defined and we do not want to go against standard there.

iamgreaser commented 3 years ago

Similarly % is the same modulo operation that you find in a number of programming languages as well - it's how it's commonly defined and we do not want to go against standard there.

No, I have to correct this. % is one of two closely-related operations. It depends entirely on the language as to which one it is. Unless adequately defined in the documentation, there is no way to know which one of these without either trying to use it, or trying to do a division which produces an integer. Hence why I am stressing that this should be renamed. Typically it'd be "Remainder" or "Rem".

I messed up when I said Pure Data uses % to denote modulo, it actually uses mod, and says "In addition the % operator (provided for back compatibility) is like mod but acts differently for negative inputs (and might act variously depending on CPU design).".

If you'd prefer to leave this as is, that's up to you, but % is not standardised and therefore still confusing.