Definition of mignitude
Closed this issue · 14 comments
Could you clarify the definition of mignitude
?
-- | \"mignitude\"
--
-- >>> mignitude (1 ... 20)
-- 1
--
-- >>> mignitude (-20 ... 10)
-- 10
--
-- >>> mignitude (singleton 5)
-- 5
--
-- >>> mignitude empty
-- 0
mignitude :: (Num a, Ord a) => Interval a -> a
mignitude (I a b) = on min abs a b
mignitude Empty = 0
{-# INLINE mignitude #-}
I expected the answer to the second test case, mignitude (-20 ... 10)
, to be 0
, not 10
, because that is the smallest number that could be in the interval.
mignitude i = let (I a b) = abs i
in on min abs a b
Trying to google an official definition isn't getting me very far. Though I did find a couple of libraries for other languages that take my view of that test case, e.g. https://mvngu.googlecode.com/hg/onepage/sage/rings/real_mpfi/sage.rings.real_mpfi.RealIntervalFieldElement.mignitude.html.
Whoops, I think my try doesn't match my definition either.
mignitude = inf . abs
Relatedly, it seems to me that magnitude Empty
should be nan
and not 0
.
I'd be okay with taking the smallest absolute value in the interval as its definition.
I have no real preference re NaN
vs 0
. Your preference trumps my apathy. Make it so. ;)
One benefit of 0 is that it means it is defined for all Num
, not just Fractional
though.
Yeah, I agree that the extra context is a drawback. I suppose it doesn't matter to me, really. Except that it seems wrong to use the inf . abs
definition/implementation if inf Empty = nan
without changing the Empty
case. I can't come up with a justification for using 0
other than avoiding the context.
Maybe inf Empty
is actually undefined
instead of the trick of pulling in nan
through Fractional
? The nan
trick is really nice for Interval Double
, but really isn't much different from undefined
for other Fractional
types. That seems like a big change though.
Switching to a separate exception type across the board could be problematic, NaN
is quiet. exceptions blow up sky high, but perhaps that'd be an acceptable price.
I could see building an EmptyIntervalException
and throwing it as a more robustly catchable form of error, after all these inf/sup cases for Empty shouldn't be used, so we can yell sanely I guess. I already cleaned up the code so we don't use inf
and sup
internally very much.
I was just writing it up that way to see how it looked, but I don't know how to rewrite the doctest for the case that would now be an error case.
I don't know anything about haskell's exception system apart from writing error "Empty interval"
. I will read up I guess.
Oh, and I guess what I was getting at is that NaN
is quiet, but nan
is only quiet when it is at a type where there is a quiet NaN
, so the problem of it blowing up sky high (sort of) already exists.
inf (Empty :: Interval Rational)
is "*** Exception: Ratio has zero denominator".
Just pushed something. Take a look and see what you think.
OK, good. Hold on a minute, I have a few tweaks on top of that that I will make mergeable with it.
Should there be a related change to this, I can't tell:
-- | 'realToFrac' will use the midpoint
instance Real a => Real (Interval a) where
toRational Empty = nan
toRational (I ra rb) = a + (b - a) / 2 where
a = toRational ra
b = toRational rb
{-# INLINE toRational #-}
Yes, that should also throw EmptyInterval
. I changed it in the other type. Missed one apparently.
Looks fixed to me.