packages feed

colour-space-0.2.0.0: test/tasty/test.hs

-- |
-- Module      : test
-- Copyright   : (c) Justus Sagemüller 2022
-- License     : GPL v3
-- 
-- Maintainer  : (@) jsag $ hvl.no
-- Stability   : experimental
-- Portability : portable
-- 

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE UnicodeSyntax       #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DerivingStrategies  #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TupleSections       #-}
{-# LANGUAGE CPP                 #-}

import Math.Manifold.Core.PseudoAffine
import Data.Manifold.Types
import Data.Manifold.WithBoundary
import Data.VectorSpace
import Data.Semigroup

import Data.Colour.Manifold
import Data.Colour.Manifold.Internal
import Data.Colour
import Data.Colour.SRGB.Linear

import Test.Tasty
import Test.Tasty.QuickCheck
import qualified Test.QuickCheck as QC
import System.Random (Random)
import Text.Printf

main :: IO ()
main = do
  putStrLn "here"
  defaultMain $ testGroup "Tests"
   [ testGroup "Sanity checks"
    [ testProperty "Self equality"
     $ \(c :: Colour ℝ) -> c ≈≈≈ c
    , testProperty "Equality nontriviality"
     . QC.expectFailure $ \(c :: Colour ℝ) d -> c ≈≈≈ d
    ]
   , testGroup "Manifold laws"
    [ testProperty "Zero displacement"
     $ \(c :: Colour ℝ) -> case toInterior c of
          Nothing -> undefined
          Just ci -> case c .+^| zeroV of
            Right c' -> c'≈≈≈ci
    , testProperty "Boundary retrieval"
     $ \ce -> separateInterior (fromBoundary ce :: Colour ℝ) ≈≈≈ Left ce
    , testProperty "Interior retrieval"
     $ \ci -> separateInterior (fromInterior ci :: Colour ℝ) ≈≈≈ Right ci
    , testProperty "Difference re-addition"
     $ \(c :: Colour ℝ) d
         -> let Just v = c.--.d
            in QC.counterexample (printf "v = %s\n" (show v)) $ case d .+^| v of
                   Left (cb, η) -> QC.property (abs η < 1e-6) .&&. fromBoundary cb ≈≈≈ c
                   Right ci     -> fromInterior ci ≈≈≈ c
    , testProperty "Displacement re-subtraction"
     $ \(c :: Colour ℝ) v
         -> case c .+^| v of
              Left (db, η) -> let w = fromBoundary db.--!c
                                  μ = v<.>w
                                  λ = v<.>v
                              in QC.property (μ>=0 && μ<=λ)
                                     .&&. v^*(μ/λ) ≈≈≈ w
                                     .&&. w^*(1+η) ≈≈≈ v
              Right di     -> fromInterior di.--!c ≈≈≈ v
    ]
   ]


infix 4 ≈≈, ≈≈≈

class NearEq a where
  (≈≈) :: a -> a -> Bool

instance NearEq ℝ where
  n ≈≈ m
   | abs n<=1, m<=1  = abs (n-m) < 1e-9
   | otherwise       = abs (n-m) < 1e-9 * (abs n + abs n)
instance (NearEq a, NearEq b) => NearEq (a,b) where
  (x,y) ≈≈ (ξ,υ) = x≈≈ξ && y≈≈υ
instance (NearEq a, NearEq b, NearEq c) => NearEq (a,b,c) where
  (x,y,z) ≈≈ (ξ,υ,ζ) = x≈≈ξ && y≈≈υ && z≈≈ζ
instance NearEq a => NearEq (RGB a) where
  RGB r g b ≈≈ RGB ρ γ β = r≈≈ρ && g≈≈γ && b≈≈β
instance NearEq a => NearEq (Maybe a) where
  Just p ≈≈ Just q = p≈≈q
  Nothing ≈≈ Nothing = True
  _ ≈≈ _ = False
instance (NearEq a, NearEq b) => NearEq (Either a b) where
  Left p ≈≈ Left q = p≈≈q
  Right p ≈≈ Right q = p≈≈q
  _ ≈≈ _ = False
instance NearEq D¹ where
  D¹ p ≈≈ D¹ q = abs (p-q) < 1e-9
instance NearEq S² where
  p ≈≈ q = magnitude (p.-~.q) < 1e-9

instance (NearEq a, Fractional a) => NearEq (Colour a) where
  c ≈≈ ζ = toRGB c ≈≈ toRGB ζ
instance NearEq ColourNeedle where
  ColourNeedle v ≈≈ ColourNeedle w = v ≈≈ w
instance (Fractional a, Random a) => QC.Arbitrary (Colour a) where
  arbitrary = rgb <$> QC.choose (0,1) <*> QC.choose (0,1) <*> QC.choose (0,1)
instance NearEq ColourBoundary where
  ColourBoundarySphere v ≈≈ ColourBoundarySphere w = v ≈≈ w

(≈≈≈) :: (NearEq a, Eq a, Show a)
      => a -> a -> QC.Property
p≈≈≈q
 | p≈≈q       = QC.property True
 | otherwise  = p===q




instance InnerSpace ColourNeedle where
  ColourNeedle c <.> ColourNeedle d = pr+pg+pb
   where RGB pr pg pb = (*)<$>c<*>d