{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-|
Copyright   : Predictable Network Solutions Ltd., 2020-2024
License     : BSD-3-Clause
Description : Piecewise functions on the number line. 
-}
module Numeric.Function.Piecewise
    ( -- * Type
      Piecewise

      -- * Basic operations
    , zero
    , fromInterval
    , fromAscPieces
    , toAscPieces
    , intervals

      -- * Structure
    , mapPieces
    , mergeBy
    , trim

      -- * Numerical
    , evaluate
    , translateWith

      -- * Zip
    , zipPointwise
    ) where

import Control.DeepSeq
    ( NFData
    )
import GHC.Generics
    ( Generic
    )

import qualified Data.Function.Class as Fun

{-----------------------------------------------------------------------------
    Type
------------------------------------------------------------------------------}
-- | Internal representation of a single piece,
-- starting at a basepoint of type @a@
-- and containing an object of type @o@.
data Piece a o = Piece
    { forall a o. Piece a o -> a
basepoint :: a
    , forall a o. Piece a o -> o
object :: o
    }
    deriving (Piece a o -> Piece a o -> Bool
(Piece a o -> Piece a o -> Bool)
-> (Piece a o -> Piece a o -> Bool) -> Eq (Piece a o)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a o. (Eq a, Eq o) => Piece a o -> Piece a o -> Bool
$c== :: forall a o. (Eq a, Eq o) => Piece a o -> Piece a o -> Bool
== :: Piece a o -> Piece a o -> Bool
$c/= :: forall a o. (Eq a, Eq o) => Piece a o -> Piece a o -> Bool
/= :: Piece a o -> Piece a o -> Bool
Eq, Int -> Piece a o -> ShowS
[Piece a o] -> ShowS
Piece a o -> String
(Int -> Piece a o -> ShowS)
-> (Piece a o -> String)
-> ([Piece a o] -> ShowS)
-> Show (Piece a o)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a o. (Show a, Show o) => Int -> Piece a o -> ShowS
forall a o. (Show a, Show o) => [Piece a o] -> ShowS
forall a o. (Show a, Show o) => Piece a o -> String
$cshowsPrec :: forall a o. (Show a, Show o) => Int -> Piece a o -> ShowS
showsPrec :: Int -> Piece a o -> ShowS
$cshow :: forall a o. (Show a, Show o) => Piece a o -> String
show :: Piece a o -> String
$cshowList :: forall a o. (Show a, Show o) => [Piece a o] -> ShowS
showList :: [Piece a o] -> ShowS
Show, (forall x. Piece a o -> Rep (Piece a o) x)
-> (forall x. Rep (Piece a o) x -> Piece a o)
-> Generic (Piece a o)
forall x. Rep (Piece a o) x -> Piece a o
forall x. Piece a o -> Rep (Piece a o) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a o x. Rep (Piece a o) x -> Piece a o
forall a o x. Piece a o -> Rep (Piece a o) x
$cfrom :: forall a o x. Piece a o -> Rep (Piece a o) x
from :: forall x. Piece a o -> Rep (Piece a o) x
$cto :: forall a o x. Rep (Piece a o) x -> Piece a o
to :: forall x. Rep (Piece a o) x -> Piece a o
Generic, Piece a o -> ()
(Piece a o -> ()) -> NFData (Piece a o)
forall a. (a -> ()) -> NFData a
forall a o. (NFData a, NFData o) => Piece a o -> ()
$crnf :: forall a o. (NFData a, NFData o) => Piece a o -> ()
rnf :: Piece a o -> ()
NFData)

{- | A function defined piecewise on numerical intervals.
 
* @o@ = type of function on every piece
    e.g. polynomials or other specialized representations of functions
* @'Fun.Domain' o@ = numerical type for the number line, e.g. 'Rational' or 'Double'

A value @f :: Piecewise o@ represents a function

> eval f x = { 0           if -∞ <  x < x1
>            { eval o1 x   if x1 <= x < x2
>            { eval o2 x   if x2 <= x < x3
>            { …
>            { eval on x   if xn <= x < +∞

where @x1, …, xn@ are points on the real number line
(in strictly increasing order)
and where @o1, …, on@ are specialized representations functions,
e.g. polynomials.

In other words, the value @f@ represents a function that
is defined piecewise on half-open intervals.

The function 'intervals' returns the half-open intervals in the middle:

> intervals f = [(x1,x2), (x2,x3), …, (xn-1, xn)]

No attempt is made to merge intervals if the piecewise objects are equal,
e.g. the situation @o1 == o2@ may occur.

-}
data Piecewise o
    = Pieces [Piece (Fun.Domain o) o]
    deriving ((forall x. Piecewise o -> Rep (Piecewise o) x)
-> (forall x. Rep (Piecewise o) x -> Piecewise o)
-> Generic (Piecewise o)
forall x. Rep (Piecewise o) x -> Piecewise o
forall x. Piecewise o -> Rep (Piecewise o) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall o x. Rep (Piecewise o) x -> Piecewise o
forall o x. Piecewise o -> Rep (Piecewise o) x
$cfrom :: forall o x. Piecewise o -> Rep (Piecewise o) x
from :: forall x. Piecewise o -> Rep (Piecewise o) x
$cto :: forall o x. Rep (Piecewise o) x -> Piecewise o
to :: forall x. Rep (Piecewise o) x -> Piecewise o
Generic)

deriving instance (Show (Fun.Domain o), Show o) => Show (Piecewise o)
deriving instance (NFData (Fun.Domain o), NFData o) => NFData (Piecewise o)

{-$Piecewise Invariants

* The empty list represents the zero function.
* The 'basepoint's are in strictly increasing order.
* The internal representation of the function mentioned in the definition is

    > f = Pieces [Piece x1 o1, Piece x2 o2, …, Piece xn on]
-}

{-----------------------------------------------------------------------------
    Operations
------------------------------------------------------------------------------}
-- | The function which is zero everywhere.
zero :: Piecewise o
zero :: forall o. Piecewise o
zero = [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces []

-- | @fromInterval (x1,x2) o@ creates a 'Piecewise' function
-- from a single function @o@ by restricting it to the
-- to half-open interval @x1 <= x < x2@.
-- The result is zero outside this interval.
fromInterval
    :: (Ord (Fun.Domain o), Num o)
    => (Fun.Domain o, Fun.Domain o) -> o -> Piecewise o
fromInterval :: forall o.
(Ord (Domain o), Num o) =>
(Domain o, Domain o) -> o -> Piecewise o
fromInterval (Domain o
x,Domain o
y) o
o = [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces [Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
start o
o, Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
end o
0]
  where
    start :: Domain o
start = Domain o -> Domain o -> Domain o
forall a. Ord a => a -> a -> a
min Domain o
x Domain o
y
    end :: Domain o
end = Domain o -> Domain o -> Domain o
forall a. Ord a => a -> a -> a
max Domain o
x Domain o
y

-- | Build a piecewise function from an ascending list of contiguous pieces.
--
-- /The precondition (`map fst` of input list is ascending) is not checked./
fromAscPieces :: Ord (Fun.Domain o) => [(Fun.Domain o, o)] -> Piecewise o
fromAscPieces :: forall o. Ord (Domain o) => [(Domain o, o)] -> Piecewise o
fromAscPieces = [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces ([Piece (Domain o) o] -> Piecewise o)
-> ([(Domain o, o)] -> [Piece (Domain o) o])
-> [(Domain o, o)]
-> Piecewise o
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Domain o, o) -> Piece (Domain o) o)
-> [(Domain o, o)] -> [Piece (Domain o) o]
forall a b. (a -> b) -> [a] -> [b]
map ((Domain o -> o -> Piece (Domain o) o)
-> (Domain o, o) -> Piece (Domain o) o
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece)

-- | Convert the piecewise function to a list of contiguous pieces
-- where the starting points of the pieces are in ascending order.
toAscPieces :: Ord (Fun.Domain o) => Piecewise o -> [(Fun.Domain o, o)]
toAscPieces :: forall o. Ord (Domain o) => Piecewise o -> [(Domain o, o)]
toAscPieces (Pieces [Piece (Domain o) o]
xos) = [ (Domain o
x, o
o) | Piece Domain o
x o
o <- [Piece (Domain o) o]
xos ]

-- | Intervals on which the piecewise function is defined, in sequence.
-- The last half-open interval, @xn <= x < +∞@, is omitted.
intervals :: Piecewise o -> [(Fun.Domain o, Fun.Domain o)]
intervals :: forall o. Piecewise o -> [(Domain o, Domain o)]
intervals (Pieces [Piece (Domain o) o]
ys) =
    [Domain o] -> [Domain o] -> [(Domain o, Domain o)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Piece (Domain o) o -> Domain o)
-> [Piece (Domain o) o] -> [Domain o]
forall a b. (a -> b) -> [a] -> [b]
map Piece (Domain o) o -> Domain o
forall a o. Piece a o -> a
basepoint [Piece (Domain o) o]
ys) (Int -> [Domain o] -> [Domain o]
forall a. Int -> [a] -> [a]
drop Int
1 ([Domain o] -> [Domain o]) -> [Domain o] -> [Domain o]
forall a b. (a -> b) -> a -> b
$ (Piece (Domain o) o -> Domain o)
-> [Piece (Domain o) o] -> [Domain o]
forall a b. (a -> b) -> [a] -> [b]
map Piece (Domain o) o -> Domain o
forall a o. Piece a o -> a
basepoint [Piece (Domain o) o]
ys)

{-----------------------------------------------------------------------------
    Operations
    Structure
------------------------------------------------------------------------------}
-- | Map the objects of pieces.
mapPieces
    :: Fun.Domain o ~ Fun.Domain o'
    => (o -> o') -> Piecewise o -> Piecewise o'
mapPieces :: forall o o'.
(Domain o ~ Domain o') =>
(o -> o') -> Piecewise o -> Piecewise o'
mapPieces o -> o'
f (Pieces [Piece (Domain o) o]
ps) = [Piece (Domain o') o'] -> Piecewise o'
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces [ Domain o' -> o' -> Piece (Domain o') o'
forall a o. a -> o -> Piece a o
Piece Domain o'
x (o -> o'
f o
o) | Piece Domain o'
x o
o <- [Piece (Domain o) o]
[Piece (Domain o') o]
ps ]

-- | Merge all adjacent pieces whose functions are considered
-- equal by the given predicate.
mergeBy :: Num o => (o -> o -> Bool) -> Piecewise o -> Piecewise o
mergeBy :: forall o. Num o => (o -> o -> Bool) -> Piecewise o -> Piecewise o
mergeBy o -> o -> Bool
eq (Pieces [Piece (Domain o) o]
pieces) = [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces ([Piece (Domain o) o] -> Piecewise o)
-> [Piece (Domain o) o] -> Piecewise o
forall a b. (a -> b) -> a -> b
$ o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
go o
0 [Piece (Domain o) o]
pieces
  where
    go :: o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
go o
_ [] = []
    go o
before (Piece (Domain o) o
p : [Piece (Domain o) o]
ps)
        | o
before o -> o -> Bool
`eq` Piece (Domain o) o -> o
forall a o. Piece a o -> o
object Piece (Domain o) o
p = o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
go o
before [Piece (Domain o) o]
ps
        | Bool
otherwise = Piece (Domain o) o
p Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
go (Piece (Domain o) o -> o
forall a o. Piece a o -> o
object Piece (Domain o) o
p) [Piece (Domain o) o]
ps

-- | Merge all adjacent pieces whose functions are equal according to '(==)'.
trim :: (Eq o, Num o) => Piecewise o -> Piecewise o
trim :: forall o. (Eq o, Num o) => Piecewise o -> Piecewise o
trim = (o -> o -> Bool) -> Piecewise o -> Piecewise o
forall o. Num o => (o -> o -> Bool) -> Piecewise o -> Piecewise o
mergeBy o -> o -> Bool
forall a. Eq a => a -> a -> Bool
(==)

{-----------------------------------------------------------------------------
    Operations
    Evaluation
------------------------------------------------------------------------------}
{-|
Evaluate a piecewise function at a point.

* @'Fun.Domain' ('Piecewise' o) = 'Fun.Domain' o@
* @'Fun.Codomain' ('Piecewise' o) = 'Fun.Codomain' o@
-}
instance (Fun.Function o, Num o, Ord (Fun.Domain o), Num (Fun.Codomain o))
    => Fun.Function (Piecewise o)
  where
    type instance Domain (Piecewise o) = Fun.Domain o
    type instance Codomain (Piecewise o) = Fun.Codomain o
    eval :: Piecewise o -> Domain (Piecewise o) -> Codomain (Piecewise o)
eval = Piecewise o -> Domain o -> Codomain o
Piecewise o -> Domain (Piecewise o) -> Codomain (Piecewise o)
forall o.
(Function o, Num o, Ord (Domain o), Num (Codomain o)) =>
Piecewise o -> Domain o -> Codomain o
evaluate

-- | Evaluate the piecewise function at a point.
-- See 'Piecewise' for the semantics.
evaluate
    :: (Fun.Function o, Num o, Ord (Fun.Domain o), Num (Fun.Codomain o))
    => Piecewise o -> Fun.Domain o -> Fun.Codomain o
evaluate :: forall o.
(Function o, Num o, Ord (Domain o), Num (Codomain o)) =>
Piecewise o -> Domain o -> Codomain o
evaluate (Pieces [Piece (Domain o) o]
pieces) Domain o
x = o -> [Piece (Domain o) o] -> Codomain o
go o
0 [Piece (Domain o) o]
pieces
 where
    go :: o -> [Piece (Domain o) o] -> Codomain o
go o
before [] = o -> Domain o -> Codomain o
forall f. Function f => f -> Domain f -> Codomain f
Fun.eval o
before Domain o
x
    go o
before (Piece (Domain o) o
p:[Piece (Domain o) o]
ps)
        | Piece (Domain o) o -> Domain o
forall a o. Piece a o -> a
basepoint Piece (Domain o) o
p Domain o -> Domain o -> Bool
forall a. Ord a => a -> a -> Bool
<= Domain o
x = o -> [Piece (Domain o) o] -> Codomain o
go (Piece (Domain o) o -> o
forall a o. Piece a o -> o
object Piece (Domain o) o
p) [Piece (Domain o) o]
ps
        | Bool
otherwise = o -> Domain o -> Codomain o
forall f. Function f => f -> Domain f -> Codomain f
Fun.eval o
before Domain o
x

-- | Translate a piecewise function,
-- given a way to translate each piece.
--
-- >  eval (translate' y o) = eval o (x - y)
-- >    implies
-- >    eval (translateWith translate' y p) = eval p (x - y)
translateWith
    :: (Ord (Fun.Domain o), Num (Fun.Domain o), Num o)
    => (Fun.Domain o -> o -> o)
    -> Fun.Domain o -> Piecewise o -> Piecewise o
translateWith :: forall o.
(Ord (Domain o), Num (Domain o), Num o) =>
(Domain o -> o -> o) -> Domain o -> Piecewise o -> Piecewise o
translateWith Domain o -> o -> o
trans Domain o
y (Pieces [Piece (Domain o) o]
pieces) =
    [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces [ Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece (Domain o
x Domain o -> Domain o -> Domain o
forall a. Num a => a -> a -> a
+ Domain o
y) (Domain o -> o -> o
trans Domain o
y o
o) | Piece Domain o
x o
o <- [Piece (Domain o) o]
pieces ]

{-----------------------------------------------------------------------------
    Operations
    Zip
------------------------------------------------------------------------------}
-- | Combine two piecewise functions by combining the pieces
-- with a pointwise operation that preserves @0@.
--
-- For example, `(+)` and `(*)` are pointwise operations on functions,
-- but convolution is not a pointwise operation.
--
-- Preconditions on the argument @f@:
--
-- * @f 0 0 = 0@
-- * @f@ is a pointwise operations on functions,
--   e.g. commutes with pointwise evaluation.
--
-- /The preconditions are not checked!/
zipPointwise
    :: (Ord (Fun.Domain o), Num o)
    => (o -> o -> o)
        -- ^ @f@
    -> Piecewise o -> Piecewise o -> Piecewise o
zipPointwise :: forall o.
(Ord (Domain o), Num o) =>
(o -> o -> o) -> Piecewise o -> Piecewise o -> Piecewise o
zipPointwise o -> o -> o
f (Pieces [Piece (Domain o) o]
xs') (Pieces [Piece (Domain o) o]
ys') =
    [Piece (Domain o) o] -> Piecewise o
forall o. [Piece (Domain o) o] -> Piecewise o
Pieces ([Piece (Domain o) o] -> Piecewise o)
-> [Piece (Domain o) o] -> Piecewise o
forall a b. (a -> b) -> a -> b
$ o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
0 [Piece (Domain o) o]
xs' o
0 [Piece (Domain o) o]
ys'
  where
    -- We split the intervals and combine the pieces in a single pass.
    --
    -- The algorithm is similar to mergesort:
    -- We walk both lists in parallel and generate a new piece by
    -- * taking the basepoint of the nearest piece
    -- * and combining it with the object that was overhanging from
    --   the previous piece (`xhang`, `yhang`)
    go :: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
_ [] o
_ [] = []
    go o
_ (Piece Domain o
x o
ox : [Piece (Domain o) o]
xstail) o
yhang [] =
        Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
x (o -> o -> o
f o
ox o
yhang) Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
ox [Piece (Domain o) o]
xstail o
yhang []
    go o
xhang [] o
_ (Piece Domain o
y o
oy : [Piece (Domain o) o]
ystail) =
        Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
y (o -> o -> o
f o
xhang o
oy) Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
xhang [] o
oy [Piece (Domain o) o]
ystail
    go o
xhang xs :: [Piece (Domain o) o]
xs@(Piece Domain o
x o
ox : [Piece (Domain o) o]
xstail) o
yhang ys :: [Piece (Domain o) o]
ys@(Piece Domain o
y o
oy : [Piece (Domain o) o]
ystail) =
        case Domain o -> Domain o -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Domain o
x Domain o
y of
            Ordering
LT -> Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
x (o -> o -> o
f o
ox    o
yhang) Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
ox [Piece (Domain o) o]
xstail o
yhang [Piece (Domain o) o]
ys
            Ordering
EQ -> Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
x (o -> o -> o
f o
ox    o
oy   ) Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
ox [Piece (Domain o) o]
xstail o
oy [Piece (Domain o) o]
ystail
            Ordering
GT -> Domain o -> o -> Piece (Domain o) o
forall a o. a -> o -> Piece a o
Piece Domain o
y (o -> o -> o
f o
xhang o
oy   ) Piece (Domain o) o -> [Piece (Domain o) o] -> [Piece (Domain o) o]
forall a. a -> [a] -> [a]
: o
-> [Piece (Domain o) o]
-> o
-> [Piece (Domain o) o]
-> [Piece (Domain o) o]
go o
xhang [Piece (Domain o) o]
xs  o
oy [Piece (Domain o) o]
ystail

{-----------------------------------------------------------------------------
    Operations
    Numeric
------------------------------------------------------------------------------}
{-| Algebraic operations '(+)', '(*)' and 'negate' on piecewise functions.

The functions 'abs' and 'signum' are defined using 'abs' and 'signum'
for every piece.

TODO: 'fromInteger' is __undefined__
-}
instance (Ord (Fun.Domain o), Num o) => Num (Piecewise o) where
    + :: Piecewise o -> Piecewise o -> Piecewise o
(+) = (o -> o -> o) -> Piecewise o -> Piecewise o -> Piecewise o
forall o.
(Ord (Domain o), Num o) =>
(o -> o -> o) -> Piecewise o -> Piecewise o -> Piecewise o
zipPointwise o -> o -> o
forall a. Num a => a -> a -> a
(+)
    * :: Piecewise o -> Piecewise o -> Piecewise o
(*) = (o -> o -> o) -> Piecewise o -> Piecewise o -> Piecewise o
forall o.
(Ord (Domain o), Num o) =>
(o -> o -> o) -> Piecewise o -> Piecewise o -> Piecewise o
zipPointwise o -> o -> o
forall a. Num a => a -> a -> a
(*)
    negate :: Piecewise o -> Piecewise o
negate = (o -> o) -> Piecewise o -> Piecewise o
forall o o'.
(Domain o ~ Domain o') =>
(o -> o') -> Piecewise o -> Piecewise o'
mapPieces o -> o
forall a. Num a => a -> a
negate
    abs :: Piecewise o -> Piecewise o
abs = (o -> o) -> Piecewise o -> Piecewise o
forall o o'.
(Domain o ~ Domain o') =>
(o -> o') -> Piecewise o -> Piecewise o'
mapPieces o -> o
forall a. Num a => a -> a
abs
    signum :: Piecewise o -> Piecewise o
signum = (o -> o) -> Piecewise o -> Piecewise o
forall o o'.
(Domain o ~ Domain o') =>
(o -> o') -> Piecewise o -> Piecewise o'
mapPieces o -> o
forall a. Num a => a -> a
signum
    fromInteger :: Integer -> Piecewise o
fromInteger Integer
0 = Piecewise o
forall o. Piecewise o
zero
    fromInteger Integer
_ = String -> Piecewise o
forall a. HasCallStack => String -> a
error String
"TODO: fromInteger not implemented"