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?