# Difference between rem2pi and mod2pi?

I’m trying to understand the difference between `rem2pi(x, RoundNearest)` and `mod2pi` (or more precisely `mod2pi - π`) from Base, Math functions. Is that correct that roughly speaking both function return the same thing, that is the principal value of an angle between -π and +π?

I understand from the doc that `mod(x, y)` is the same as `rem(x, y, RoundDown)`, but things gets complicated when it says that `mod2pi(x)` is different from `mod(x, 2π)`

When it says `mod2pi(x)` is different from `mod(x, 2π)`, it just means that `mod(x, 2π)` uses a floating point representation of `2pi`, while `mod2pi` uses the mathematical number. This makes a difference for large inputs, since the rounding error in `2pi` will get multiplied by `floor(x/2pi)`.

1 Like

Thanks. So is it correct that `mod2pi(x)` is the same as `rem2pi(x, RoundDown)`?

And then, since the doc of `rem2pi(x, RoundDown)` says it return a number in [0, 2π], how is `mod2pi - π` different from `rem2pi(x, RoundNearest)` which return a number in [-π, π]? Are those the same except for the extraneous substraction (which of course brings some error)? Or are there some input values which return different output values?

``````julia> rem2pi(-1.0, RoundNearest)
-1.0

julia> mod2pi(-1.0)
5.283185307179586
``````

negative numbers strike again.

1 Like

Good catch! Also, I now realize that my reasoning about substracting π to `mod2pi(x)` is silly.

So it seems that for my usecase, I should stick with `rem2pi(x, RoundNearest)`.

I’m not sure what you mean by “negative numbers strike again.”, but my first implementation, before discovering `rem2pi` and friends was `(x+π) % 2π - π` which at first seems to work but indeed breaks when `(x+π)` is negative. This lead me to the surprising discovery that `rem(x, y)` output range depends on the sign of `x` by default (i.e. when not specifying the rounding mode argument which I didn’t know it existed!). Is it this kind of “surprise for new users” that you were thinking of?

What’s wrong with it? `-1.0+2pi=5.283185307179586` so it’s in the correct range…

1 Like

@pierre-haessig This is the same as the difference between the `rem` and `mod` functions (as specified by ieee). `rem` returns a result with the same sign as the divisor. `mod` is periodic. These definitions correspond when the divisor and dividend have the same sign.

1 Like

Thanks for the context. In fact, I think the suprise for me was mostly about coming from Python where `-1 % 3` returns 2 (I just check to be sure!) while Julia returns -1.

Digging further in Python, I just found out about the relatively new (Python 3.7+) function `math.remainder` which claims to be the “IEEE 754-style remainder”. Since the doc says it returns `r` such that |r| ≤ y/2, this maps to Julia’s `rem` used with `RoundNearest` if I’m not mistaken.

About realizing one of my proposition was silly: it’s just that I thought `mod2pi(x) - π` would give the principal angle in [-π, π]. But in fact, it should be `mod2pi(x+π) - π`. Otherwise, the output range is correct, but the value is wrong by 180°…

By the way, I can access the doc of `rem(x, y, r::RoundingMode=RoundToZero)` through the REPL, but oddly enough I don’t see it in the doc Base.rem which is only about `rem(x, y)`. Why is that?