packages feed

sbv-14.8: Data/SBV/Compilers/C/Finite.hs

-----------------------------------------------------------------------------
-- |
-- Module    : Data.SBV.Compilers.C.Finite
-- Copyright : (c) Levent Erkok
-- License   : BSD3
-- Maintainer: erkokl@gmail.com
-- Stability : experimental
--
-- Finite SMT-object domains shared by C collection lowering.
-----------------------------------------------------------------------------

{-# OPTIONS_GHC -Wall -Werror #-}

module Data.SBV.Compilers.C.Finite (finiteDomainSize) where

import qualified Data.Set as Set

import Data.SBV.Core.Data

-- | Count distinct SMT objects without imposing a machine-integer limit.
-- All NaN encodings denote one object; signed zeros remain distinct. The
-- constructor callback resolves ADT references without a module dependency
-- cycle. Recursive and unbounded domains return 'Nothing'.
finiteDomainSize :: (Kind -> [[Kind]]) -> Kind -> Maybe Integer
finiteDomainSize constructorsOf = count Set.empty
 where count _ KBool                 = Just 2
       count _ (KBounded _ width)     = Just (2 ^ width)
       count _ KFloat                = Just (2 ^ (32 :: Int) - 2 ^ (24 :: Int) + 3)
       count _ KDouble               = Just (2 ^ (64 :: Int) - 2 ^ (53 :: Int) + 3)
       count _ KChar                 = Just 0x30000
       count _ (KFP eb sb)            = Just (2 ^ (eb + sb) - 2 ^ sb + 3)
       count seen (KTuple fields)     = product <$> mapM (count seen) fields
       count seen kind
         | isRoundingMode kind = Just 5
         | concrete kind, kind `Set.notMember` seen
         = sum <$> mapM (fmap product . mapM (count (Set.insert kind seen))) (constructorsOf kind)
         | True = Nothing

       concrete KApp{} = True
       concrete kind   = isADT kind && not (isUninterpreted kind)