Numeric limits in spire.math?

64 views
Skip to first unread message

Jacek Królikowski

unread,
Jun 29, 2014, 6:11:06 PM6/29/14
to spire...@googlegroups.com
Today I rewrote some code that I'm working on to be more generic using spire.math Numeric and Order. All in all it was a great experience and I'm pretty sure I'll be using spire for all my numeric and algebraic needs in scala. I have encountered one minor nuisance: In a place where I used Double as a common denominator of sorts in the existing algorithm I set one variable's value to Double.MaxValue and it served as an accumulator of sorts later on. When I replaced Double in this place in an instance of Numeric I had to modify the code slightly. Now it wasn't really a problem and I could rewrite it in a number of ways, even increasing the code quality at the same time, but it made me wonder if there's a need for an equivalent to MaxValue in spire - something like what <numeric_limits> has to offer in C++. If I understand the situation correctly it would suffice to create a type class Limit and provide instances of it for all instances of Numeric with Limit.minValue and Limit.maxValue in a similar fashion there exists Numeric.zero.

Now my question is - how sound is this idea? Is there a reason why this shouldn't be done? I can see that most code could be rewritten not to need it but I can imagine situations where having numeric limits in spire would be benefitial.

Cheers

Erik Osheim

unread,
Jun 29, 2014, 8:28:51 PM6/29/14
to Jacek Królikowski, spire...@googlegroups.com
On Sun, Jun 29, 2014 at 03:11:06PM -0700, Jacek Królikowski wrote:
> Now my question is - how sound is this idea? Is there a reason why this
> shouldn't be done? I can see that most code could be rewritten not to need
> it but I can imagine situations where having numeric limits in spire would
> be benefitial.

Hi Jacek,

I've thought about adding something like this. So far I am undecided.

One point in its favor is that it would be pretty easy to do. I could
easily imagine something like:

trait Limits[A] {
def minValue: Option[A]
def maxValue: Option[A]
}

The reason I've hesitated is that I can't think of a situation where
you would want to use the min/max values without knowing more about
the type. For example, if you look at Double.MaxValue, the "next"
highest value is ~1e292 smaller. I can't think of a generic algorithm
where that would be useful.

Furthermore, we'd have to decide what laws we expected Limits[A]
instances to follow. For example, we might wan to say something like:

forAll { (a: A) =>
Limits[A].maxValue should be >= a
}

However, for Double this would not be correct (due to NaN). We could
say that "Limits[A].maxValue should not be < a" instead, but you see
the problem. Also, how does PositiveInfinity fit in? It's certainly
larger than Double.MaxValue.

I'm open to adding this type class, but I'd like to make sure it's
something that could be useful. We might want something more specific,
like:

trait IsFinite[A] {
def minValue: A
def maxValue: A
}

Or possibly something that capture more of the type's structure, e.g.

trait FloatingPoint[@sp(Float, Double) A] {
def positiveInfinity: A
def negativeInfinity: A
def nan: A
def minValue: A
def maxValue: A
def zero: A
def isFinite(a: A): Boolean
def isInfinite(a: A): Boolean
def isNaN(a: A): Boolean
def ulp(a: A): A
// and so on...
}

Anyway, what do you all think? Are there uses for max value and min
value that I'm missing?

-- Erik

Tom Switzer

unread,
Jun 29, 2014, 8:55:46 PM6/29/14
to Jacek Królikowski, Spire User List
I don't see a reason why it shouldn't be added in some form. It is often useful to understand the limits/limitations of the numbers you are working with for many algorithms. Anyways, just some quick thoughts on this...

With Float & Double, the "largest" value, from an ordering perspective, is really Double.PositiveInfinity, but I'm guessing that is not useful to you. So, we need a way to talk about the "max finite value" (eg. Double.MaxValue), as well as the "max value" (eg. Double.PositiveInfinity).

We probably would also like to know if there is a NaN type and be able to check whether a value is NaN.

Some number types don't have max values, like BigDecimal. It is conceivable that a number type could have a max value, but not a max "finite" value (eg. BigDecimal + Infinity). So checking the limits would need to account for this.

Other than max value, we often would like to know about precision, the "epsilon" of the number type, etc. There is even further concerns, like would checking for overflow/underflow of values for some operations be useful? That's probably getting excessive... but perhaps not.

Anyways, short answer, I think it is useful. I'm interested what others think - especially those who have done more work with nuanced, numeric algorithms with floating point numbers than I have.

Cheers,
Tom

Tom Switzer

unread,
Jun 29, 2014, 9:00:48 PM6/29/14
to Erik Osheim, Jacek Królikowski, Spire User List
Apparently I started typing before you posted this! So, I agree with your points. The FloatingPoint type class is nice, but I think I'd rather shoe horn this type of stuff into a more generic Limits type class. Mainly, I can think of writing a generic algorithm that would work fine with Rational, Int, or Real, but would still like to know of the "limits" (or if there even are any!). Perhaps FloatingPoint would extend Limits and contain methods like nan and ulp.
Reply all
Reply to author
Forward
0 new messages