Function(s) to express nearishness#652
Conversation
|
Nice idea. Two points:
isclose(x, y, rtol, atol) = abs(x-y) <= atol+rtol.*(abs(x)+abs(y)) (Otherwise, you'd get very different behavior for elements where y is zero but x is not.)
I'm assuming that the compiler will recognize that the powers-of-eps computations result in constants, so there shouldn't be any overhead. |
|
This does require some thought and needs to evolve. Also, support arrays, and be extensible. @pao, can you move it to extras for now? Preparing for a 1.0 release, I believe we will be moving more stuff out of base in any case... |
|
To be fair, his version supported arrays. My "eps cleanup" would need additional specifications for x::Array{T} and x::DArray{T}, however. |
|
The asymmetry is also present in the NumPy prototype, so I kept it. It's open for discussion, though. I've also considered the relative tolerance expression As @timholy observed, this does support arrays and scalar/array mixes; I intentionally used @ViralBShah extras/nearequal.jl sound good? |
|
Location sounds fine. -viral On 01-Apr-2012, at 7:31 PM, paoreply@reply.github.com wrote:
|
|
New version incorporating some of the above suggestions. I'm letting Alternatively, I could let |
|
@pao, let me know when you think this is ready for a merge. Would you like the pull request open for some more discussion? I hate those long Matlab function names, but they are actually quite clear about what they do. |
|
isclose(nan, nan) ought to be false, but for this purpose, I guess the behaviour you implemented is what we need. |
|
How about isclosen following MATLAB's isequaln? |
|
Agreed on the long function names; I didn't know about |
|
I didn't know that either - must be a new name. I like it better. Perhaps we can dispense with the "withequalnans" names? I don't think that anyone except Matlab geeks like us actually know about such things, but I could be wrong. :-) -viral On 02-Apr-2012, at 8:36 AM, pao wrote:
|
…lementations. Originally, isclose() treated NaNs as equal, but this conflicts with the conventional default. Since treating NaNs as equal is often useful, that ability is preserved by the implementation of isclosen(). Similarly, isequaln() is included as an equal-NaNs version of isequal().
|
Viral, let's bake this for a few more hours. I'll see if there are any further comments when I wake up in the morning. And if someone could check that I'm doing the UPDATE: I just checked the docs; |
|
@ViralBShah Go for merge. |
|
@JeffBezanson can check the macrology, as he calls it.. |
Function(s) to express nearishness
This reuses the machinery that gives good stacktraces when a user
calls wait on a Task. Since bind internally uses _wait2, this
machinery is bypassed currently.
Currently, julia throws an uninformative stacktrace in this situation:
julia> c = Channel(_ -> error("foo"))
Channel{Any}(sz_max:0,sz_curr:0)
julia> for i in c end
ERROR: foo
Stacktrace:
[1] iterate(::Channel{Any}) at ./channels.jl:459
[2] top-level scope at ./REPL[2]:1
With this change, the stacktrace is much more informative:
julia> for i in c end
ERROR: TaskFailedException:
foo
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] (::var"JuliaLang#1#2")(::Channel{Any}) at ./REPL[4]:1
[3] (::Base.var"JuliaLang#652#653"{var"JuliaLang#1#2",Channel{Any}})() at ./channels.jl:129
Stacktrace:
[1] check_channel_state at ./channels.jl:167 [inlined]
[2] take_unbuffered(::Channel{Any}) at ./channels.jl:405
[3] take! at ./channels.jl:383 [inlined]
[4] iterate(::Channel{Any}, ::Nothing) at ./channels.jl:449
[5] iterate(::Channel{Any}) at ./channels.jl:448
[6] top-level scope at ./REPL[5]:1
This reuses the machinery that gives good stacktraces when a user
calls wait on a Task. Since bind internally uses _wait2, this
machinery is bypassed currently.
Currently, julia throws an uninformative stacktrace in this situation:
julia> c = Channel(_ -> error("foo"))
Channel{Any}(sz_max:0,sz_curr:0)
julia> for i in c end
ERROR: foo
Stacktrace:
[1] iterate(::Channel{Any}) at ./channels.jl:459
[2] top-level scope at ./REPL[2]:1
With this change, the stacktrace is much more informative:
julia> for i in c end
ERROR: TaskFailedException:
foo
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] (::var"#1#2")(::Channel{Any}) at ./REPL[4]:1
[3] (::Base.var"#652#653"{var"#1#2",Channel{Any}})() at ./channels.jl:129
Stacktrace:
[1] check_channel_state at ./channels.jl:167 [inlined]
[2] take_unbuffered(::Channel{Any}) at ./channels.jl:405
[3] take! at ./channels.jl:383 [inlined]
[4] iterate(::Channel{Any}, ::Nothing) at ./channels.jl:449
[5] iterate(::Channel{Any}) at ./channels.jl:448
[6] top-level scope at ./REPL[5]:1
Stdlib: SparseArrays URL: https://github.com/JuliaSparse/SparseArrays.jl.git Stdlib branch: main Julia branch: master Old commit: 6fe51f2 New commit: 26c80c8 Julia version: 1.13.0-DEV SparseArrays version: 1.13.0 Bump invoked by: @IanButterworth Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: JuliaSparse/SparseArrays.jl@6fe51f2...26c80c8 ``` $ git log --oneline 6fe51f2..26c80c8 26c80c8 `ReadOnly`: do not add single-argument methods to `eachindex`, etc (#653) 15ec056 `ReadOnly`: slightly restrict the dispatch on the `setindex!` method (#652) 306605d cholmod: correct the `IndexStyle` method additions (#650) 74aaeeb `ReadOnly` fixes: prevent adding some methods of `size`, `axes`, `eltype` (#649) b823108 Bump actions/checkout from 4 to 5 (#647) ``` Co-authored-by: IanButterworth <1694067+IanButterworth@users.noreply.github.com>
This is a first shot at expressing nearishness in Julia, taking as inspiration NumPy's
allclose()function. It doesn't handle Inf/NaN the same asnumpy.allclose(), and doesn't handle all the possible types that R'sall.equal()can apparently handle.So, what is needed from those other functions here (or for specific types), noting that
isequal()already exists to express actual equality? The single commit is the simplest thing that could possibly work, but I'll add optimized things (like mapping it toisequal()for integer types) before merge if I'm on the right path and this is something we want.Whether this belongs in base/ is certainly up for discussion as well.
Input from everyone certainly helpful, but I do want to make sure @dmbates gets to see this, since he got me started thinking about it.
numpy.allclose()is defined at https://github.com/numpy/numpy/blob/master/numpy/core/numeric.py#L1963