-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modpi function #2524
Comments
Is this solvable without resorting to BigFloat? |
This SO discussion seems interesting. |
My understanding is that it is solvable without resorting to arbitrary-precision arithmetic. The term to google for is "range reduction", because this problem most commonly shows up in range reduction of trigonometric functions to reduce their argument to be in [0,π/4]. See e.g. this paper. |
openlibm includes |
I already mentioned this where Stefan first brought this up, but |
See also JuliaMath/openlibm#30 |
I'm working on exposing ieee754_rem_pio2, modpi, mod2pi, and modpio2 = mod(_,pi/2). Just finishing up the testing. |
Incidentally, does anyone know the difference between k_rem_pio2.c and e_rem_pio2.c? Thanks! |
|
Thanks. That's the one I've been using. I'll try the whole clone/push/submit pull request thing soon-ish (first time, yay), though I must first get Julia made on Mavericks (doesn't work for me yet :-/ ) |
Thanks pao, it's working now. I needed to a) run "xcode-select --install" to update the Xcode command line tools, and b) put the julia directory in the PATH, rather than just put a soft link to the julia executable from /usr/local/bin. I'm sort of done with testing as well, and will clone now. One problem: my modpi will currently take values (such as 0.7853881633974482) that should remain un-modified and change the last bit (because it internally devolves to a mod pi/2 routine and then adds the correct multiple of pi/2). I'll put in in a check to catch these cases and just return the number. However, this highlights the fact that the implementers of ieee754_rem_pio2 really maximised precision (retaining one more bit) by returning the result in the range [-pi/4, pi/4] rather than [0, pi/2]... :-) |
see here for a summary: http://nbviewer.ipython.org/7443293 Some questions: questions:
After we have: julia> mod(5706674932067741.0,pi) # correct, (new) modpi called julia> mod(5706674932067741,pi) # first arg int: original "mod" called julia> mod(5706674932067741,pi*1) # second arg Float64: original "mod" called julia> mod(5706674932067741.0,pi*1) # second arg Float64: original "mod" called
Could introduce a method that converts ints to floats. The problem being that ints > 2^53 might be truncated, and thus the modpi result be absolutely wrong - should one issue a warning, or throw an error, or silently ignore it? |
I think all we should do is add the modpi functions for float arguments,
|
So, if we do NOT add the mod method for Pi: The value of mod(100.0, pi) would move in the "correct" direction. But it might be confusing that it matters whether the first arg is a float or an int.... |
Why can't you raise |
Thinking about this again, |
What about this: modpi(x::Int32) = modpi(float64(x))
modpi(x::Int64) = if int(float(x))==x modpi(float64(x)) else error("Integer argument to modpi() is too large.") end ? |
That seems reasonable. I would write it like this: modpi(x::Int32) = float32(modpi(float64(x)))
function modpi(x::Int64)
fx = float64(x)
fx == x || error("argument to modpi is too large: $x")
modpi(fx)
end |
@StefanKarpinski Why would you reduce the precision on 32 bit systems? If someone wants a float32, he can convert it himself? |
Stefan, Why not use the two argument version of assert (@asset x "msg") instead of the x || error("msg") form? |
@vtjnash, the usual definition of assertion is restricted to predicates that can never fail unless there is a bug in the software; it seems like bad style to use it to throw ordinary exceptions. |
Sorry for the negative feedback but |
@invarne, two things:
|
@kmsquire I was talking about the conversion to I totally agree that |
@ivarne, my bad, I hadn't noticed the int32 in the signature. I agree with you--it probably should be Float64 by default. |
Sure, I'm not really particularly stuck on that. I believe that we generally convert Int32 values to Float32s but this case is certainly debatable. |
yes, so currently there is no method modpi() for Float32, only for Float64. The int cases are handled differently because we know that every Int32 can be represented as a Float64 exactly, while with large Int64 we might be off by eps=1 or 2 or more, and then modpi becomes quite meaningless (though, come to think of it, one could just add the difference between x::Int64 and fx = int(float(x)) to the result of modpi(float(x)) to get the correct result (might need to modpi it once more).... Might be a bit overkill though). @ivarne, no worries, my first pull request, happy to get feedback. How would I raise InexactError? |
The easiest thing to do for Float32 is just |
I guess we return |
throw(InexactError()) Unfortunatly |
sure, will do. |
I write it that way, others don't. It's a matter of taste. I think it's silly for an error check to take up multiple lines. I certainly think that writing |
+1 for |
@ivarne - for now, I've left the "normal" error, with the informative error msg. Not sure how to do the InexactError with informative error msg. Open for suggestions, obviously. |
The naive definition
modpi(x) = mod(x,pi)
is wildly off for large values ofx
. We should have version ofmodpi
that computes this correctly. cc: @alanedelman.The text was updated successfully, but these errors were encountered: