umka-lang icon indicating copy to clipboard operation
umka-lang copied to clipboard

Modulo operator

Open ske2004 opened this issue 6 months ago • 5 comments

Right now doing -1 % 3 yields -1, this is the remainder operator (and it's stated as remainder in the docs).

This seems less useful than modulo, one of the issues I encountered in practice was dealing with tilemaps. My tilemaps have chunks of 8x8. When you index a tile in negative coordinates, you first compute which chunk it belongs to floor(pos/8), then you need to get tile index within that chunk. But remainder will return a negative index which isn't valid.

-1         0                    | pos
[01234567][01234567][01234567]  | chunk
        ^- -1=-1     ^- 8=0
        wrong        ok

So either % should be altered to perform modulo (like in Python, for example), or there should be a built-in to perform modulo. I'm more partial towards overriding % or maybe having a %% operator.

The expected behavior is as follows: a % b (or mod(a, b)) (or a %% b) returns a with respect to boundary b using b's sign. examples: 1 % 3 == 1, 3 % 3 == 0, -1 % 3 == 2, 1 % -3 == -2, 1.75 % -3 = -1.25

ske2004 avatar Jun 13 '25 10:06 ske2004

I found the implementation I want is called "floored"

(In that case, maybe it can be called fmod as a built in, but ain't that a bit confusing? I don't mind it personally)

Image

ske2004 avatar Jun 13 '25 10:06 ske2004

@ske2004 I definitely won't change the semantics of the % operator, because:

  • If I do it, I will also have to change the semantics of /. Not only can it break existing code, but it will also lead to counter-intuitive results, such as -3 / 1000000 == -1. Sadly, this is the case in Python and Lua 5, but, at least, the operator is named // rather than / in both
  • It will break the symmetry between positive and negative numbers. So I can legitimately ask, why floored and not ceiling division?
  • In most popular languages (C, C++, C#, Java, JS/TS, Go, Rust, Swift, PHP, Zig), the % operator means truncated division. The only notable exceptions are Python and Lua 5
  • Almost all languages that support floored division (except Lua 5) also support truncated division.

However, we can consider adding a new built-in or library function for floored division.

vtereshkov avatar Jun 14 '25 18:06 vtereshkov

I will most likely introduce the two new functions to std.um, each returning both the quotient and remainder:

fn floordiv*(a, b: int): (int, int)
fn ffloordiv*(a, b: real): (real, real)

vtereshkov avatar Jun 17 '25 23:06 vtereshkov

I will most likely introduce the two new functions to std.um, each returning both the quotient and remainder:

fn floordiv*(a, b: int): (int, int)
fn ffloordiv*(a, b: real): (real, real)

I don't like it to be honest, let's hold off for now.

ske2004 avatar Jun 18 '25 01:06 ske2004

Okay, if we know how to do floored division as floor(a / b), we can only add std::fmod(a, b) or std::floormod(a, b).

vtereshkov avatar Jun 18 '25 09:06 vtereshkov