Skip to content
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

clamp function should check that "lo" < "hi" #8006

Closed
gasagna opened this issue Aug 14, 2014 · 14 comments
Closed

clamp function should check that "lo" < "hi" #8006

gasagna opened this issue Aug 14, 2014 · 14 comments
Labels
won't change Indicates that work won't continue on an issue or pull request

Comments

@gasagna
Copy link
Contributor

gasagna commented Aug 14, 2014

Hi,

playing around in math.jl I found that the clamp function does not check that "lo" is less than "hi", leading to unpredicted behaviour. For example clamp(5, 6, 4) returns 4, which I regard as a bug.

Cheers,

Davide

@staticfloat
Copy link
Member

See #8007 for a possible solution

@staticfloat
Copy link
Member

Tim Holy came up with a good compromise between speed and usability. The tension is between checking the bounds over and over again, (which is bad) and performing checking at all (which is good) so Tim suggested:

Build a ClampType which gets checked upon construction, then use it to clamp many different values without needing to check again?

The only bad thing about this is that it's not quite as simple as just calling clamp(). It would be great if the compiler could recognize that the work we're doing inside of clamp() could be hoisted out of loops, but that sounds pretty hard, so the next best thing we've got is the following:

clamper = Clamp(lo, hi) # <--- This can throw an exception
output_data = [clamper(x) for x in input_data]

@JeffBezanson
Copy link
Member

If the clamp function, checks and all, is inlined, then the compiler will be able to hoist the check out of the loop (assuming the bounds are constant of course). Adding a ClampType is way too involved for such a simple function.

@staticfloat
Copy link
Member

Then the approach in #8007, (quick link to the diff) as long as inlining is possible, could be performant?

@timholy
Copy link
Member

timholy commented Sep 17, 2014

If you really need it to be inlined and have trouble achieving that, see #8297. Fairly soon I hope to have another PR that will depend on that one. If no objections get raised in the meantime, that's the point I'll hit "merge."

@eschnett
Copy link
Contributor

I don't like the idea of an "undefined" result for such a simple function as clamp. Would it really be too difficult to modify @inbounds, or to introduce a new function @inrange?

The latter (@inrange) would also be useful for sqrt, asin, log, etc., removing the need for checking for input that would lead to a nan or an exception.

@StefanKarpinski
Copy link
Member

What are you proposing that the effect of @inrange would be?

@JeffBezanson
Copy link
Member

I feel there is an obvious implementation of clamp in terms of comparison
and ?. That is what you would write if the function didn't exist. So, I
think clamp can be defined in terms of that implementation. No checks, no
undefined cases.

@eschnett
Copy link
Contributor

Jeff

There is no single obvious implementation -- there are two obvious implementations, depending on whether you perform the "min" or the "max" operation first. If you change the order, the result will differ iff minval>maxval.

Actually, the OpenCL standard defines clamp as fmin(fmax(x, minval), maxval). Maybe we should use this as the obvious implementation.

@eschnett
Copy link
Contributor

Stefan

@inrange would omit the range check that some find offensive since perceived as too expensive in some occasions. The use case would be the same as for @inbounds -- usually not necessary if llvm is clever enough to hoist the check out of the loop, but sometimes still improving performance.

@JeffBezanson
Copy link
Member

Yes, +1 for the opengl approach. Obvious might not be the right word, but
opengl did the right thing by establishing a definition like that.

@staticfloat
Copy link
Member

We basically have the same functionality as OpenCL right now, so should we just close this as wontfix?

@vtjnash vtjnash closed this as completed Mar 25, 2016
@vtjnash
Copy link
Member

vtjnash commented Mar 25, 2016

agreed

@vtjnash vtjnash added the won't change Indicates that work won't continue on an issue or pull request label Mar 25, 2016
@eschnett
Copy link
Contributor

There could be a checked_clamp, folded into general checked arithmetic that could be made available as a package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
won't change Indicates that work won't continue on an issue or pull request
Projects
None yet
Development

No branches or pull requests

7 participants