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?