{- - Fulsom (The Solid Modeller, written in Haskell) - - Copyright 1990,1991,1992,1993 Duncan Sinclair - - Permissiom to use, copy, modify, and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, and - that my name not be used in advertising or publicity pertaining to this - software without specific, written prior permission. I makes no - representations about the suitability of this software for any purpose. - It is provided ``as is'' without express or implied warranty. - - Duncan Sinclair 1993. - - Interval arithmetic package. - -} module Interval(Interval, (#), pt, sqr, tophalf, bothalf, topbit, lo, hi, mid1, mid2, up,down,unpt) where infix 4 #,:#: data Interval a = Pt a | a :#: a deriving (Show{-was:Text-}) pt a = Pt a a # b = a :#: b instance (Ord a, Eq a) => Eq (Interval a) where a == b = a >= b && a <= b -- Not correct - but it will do. a /= b = a > b || a < b instance (Ord a) => Ord (Interval a) where (<) = ivLess (<=) = ivLeEq (>) = ivGreat (>=) = ivGrEq min = ivMin max = ivMax instance (Num a,Ord a,Eq a,Show{-was:Text-} a) => Num (Interval a) where (+) = ivPlus (*) = ivMult negate = ivNegate abs = ivAbs signum = ivSignum fromInteger = ivFromInteger instance (Num a,Ord a,Fractional a) => Fractional (Interval a) where (/) = ivDiv fromRational = ivFromRational -- instance (Fractional a,Ord a,Floating a) => - not this ? instance (RealFloat a) => Floating (Interval a) where pi = Pt pi exp = ivExp log = ivLog sqrt = ivSqrt (**) = ivPower sin = ivSin cos = ivCos tan = ivTan asin = ivAsin acos = ivAcos atan = ivAtan sinh = ivSinh cosh = ivCosh tanh = ivTanh asinh = ivAsinh acosh = ivAcosh atanh = ivAtanh -- Error functions - un-used. error0 = error "Not implemented." error1 a = error "Not implemented." error2 a b = error "Not implemented." error3 a b c = error "Not implemented." error4 a b c d = error "Not implemented." -- Eq class functions -- Ord class functions ivLess (Pt b) (Pt c) = b < c ivLess (a :#: b) (c :#: d) = b < c ivLess (Pt b) (c :#: d) = b < c ivLess (a :#: b) (Pt c) = b < c ivLeEq (Pt b) (Pt d) = b <= d ivLeEq (a :#: b) (c :#: d) = b <= d ivLeEq (Pt b) (c :#: d) = b <= d ivLeEq (a :#: b) (Pt d) = b <= d ivGreat (Pt a) (Pt d) = a > d ivGreat (a :#: b) (c :#: d) = a > d ivGreat (Pt a) (c :#: d) = a > d ivGreat (a :#: b) (Pt d) = a > d ivGrEq (Pt a) (Pt c) = a >= c ivGrEq (a :#: b) (c :#: d) = a >= c ivGrEq (Pt a) (c :#: d) = a >= c ivGrEq (a :#: b) (Pt c) = a >= c ivMin (Pt a) (Pt c) = Pt (min a c) ivMin (a :#: b) (c :#: d) = (min a c) :#: (min b d) ivMin (Pt a) (c :#: d) | a < c = Pt a | otherwise = c :#: min a d ivMin (a :#: b) (Pt c) | c < a = Pt c | otherwise = a :#: min c b ivMax (Pt a) (Pt c) = Pt (max a c) ivMax (a :#: b) (c :#: d) = (max a c) :#: (max b d) ivMax (Pt a) (c :#: d) | a > d = Pt a | otherwise = max a c :#: d ivMax (a :#: b) (Pt c) | c > b = Pt c | otherwise = max c a :#: b -- Num class functions ivPlus (Pt a) (Pt c) = Pt (a+c) ivPlus (a :#: b) (c :#: d) = a+c :#: b+d ivPlus (Pt a) (c :#: d) = a+c :#: a+d ivPlus (a :#: b) (Pt c) = a+c :#: b+c ivNegate (Pt a) = Pt (negate a) ivNegate (a :#: b) = negate b :#: negate a ivMult (Pt a) (Pt c) = Pt (a*c) ivMult (a :#: b) (c :#: d) | (min a c) > 0 = a*c :#: b*d | (max b d) < 0 = b*d :#: a*c | otherwise = minmax [e,f,g,h] where e = b * c f = a * d g = a * c h = b * d ivMult (Pt a) (c :#: d) | a > 0 = a*c :#: a*d | a < 0 = a*d :#: a*c | otherwise = (Pt 0) ivMult (c :#: d) (Pt a) | a > 0 = a*c :#: a*d | a < 0 = a*d :#: a*c | otherwise = (Pt 0) -- minmax finds the lowest, and highest in a list - used for mult. -- Should use foldl rather than foldr minmax [a] = a :#: a minmax (a:as) = case True of True | (a > s) -> f :#: a True | (a < f) -> a :#: s otherwise -> f :#: s where (f :#: s) = minmax as ivAbs (Pt a) = Pt (abs a) ivAbs (a :#: b) | a<=0 && 0<=b = 0 :#: (max (abs a) (abs b)) | a<=b && b<0 = b :#: a | 0 (Interval a) -> (Interval a) ivSin a = error "Floating op not defined." ivCos :: (Floating a) => (Interval a) -> (Interval a) ivCos a = error "Floating op not defined." ivTan :: (Floating a) => (Interval a) -> (Interval a) ivTan a = error "Floating op not defined." ivAsin :: (Floating a) => (Interval a) -> (Interval a) ivAsin a = error "Floating op not defined." ivAcos :: (Floating a) => (Interval a) -> (Interval a) ivAcos a = error "Floating op not defined." ivAtan :: (Floating a) => (Interval a) -> (Interval a) ivAtan a = error "Floating op not defined." ivSinh :: (Floating a) => (Interval a) -> (Interval a) ivSinh a = error "Floating op not defined." ivCosh :: (Floating a) => (Interval a) -> (Interval a) ivCosh a = error "Floating op not defined." ivTanh :: (Floating a) => (Interval a) -> (Interval a) ivTanh a = error "Floating op not defined." ivAsinh :: (Floating a) => (Interval a) -> (Interval a) ivAsinh a = error "Floating op not defined." ivAcosh :: (Floating a) => (Interval a) -> (Interval a) ivAcosh a = error "Floating op not defined." ivAtanh :: (Floating a) => (Interval a) -> (Interval a) ivAtanh a = error "Floating op not defined." -- Extra math functions not part of classes sqr (Pt a) = Pt (a*a) sqr (a :#: b) | a > 0 = a*a :#: b*b | b < 0 = b*b :#: a*a | otherwise = 0 :#: (max e f) where e = a * a f = b * b -- Other Functions specific to interval type tophalf (a :#: b) = (a+b)/2 :#: b bothalf (a :#: b) = a :#: (a+b)/2 topbit (a :#: b) = (a+b)/2-0.001 :#: b lo (a :#: b) = a hi (a :#: b) = b down (a :#: b) = Pt a up (a :#: b) = Pt b unpt (Pt a) = a mid1 (a :#: b) = Pt (a + (b-a)/3) mid2 (a :#: b) = Pt (b - (b-a)/3) -- END --