# Package to work with piecewise functions?

**URL:** https://discourse.julialang.org/t/package-to-work-with-piecewise-functions/95091
**Category:** General Usage
**Created:** [February 23, 2023, 4:34pm UTC](https://discourse.julialang.org/t/package-to-work-with-piecewise-functions/95091 "2023-02-23T16:34:46Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [February 23, 2023, 4:34pm UTC](https://discourse.julialang.org/t/package-to-work-with-piecewise-functions/95091/1 "2023-02-23T16:34:46Z")

</div>

Hi, @aerappa and I are looking for a package that would allow us to easily represent and work with (mathematical) functions that are defined in a piecewise manner.

To be a bit more specific, assuming we are working with a function such as

f(x) = \begin{cases} e^x & \text{if } x\leq 0 \\ x+1 & \text{otherwise} \end{cases}

we’d like to be able to efficiently represent it as a Julia object and evaluate it or its derivatives at any point using code that could ideally look like (don’t mind the API; I just made it up for the purpose of this post in order to clarify what we need):

```julia
f = PieceWise(exp, 0.0,
               Polynomial([1,1]))
f′ = derivative(f)

f(-1.0), f′(-1.0) # == exp(-1), exp(-1)
f( 1.0), f′( 1.0) # == 2, 1

```

On the one hand, this seems easy enough to implement on our own. On the other hand, it looks general enough that someone might have registered a package to do this (and why reinvent the wheel?). But I haven’t found anything like this (yet!). Does anyone here know of an existing package that would do something this?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [February 23, 2023, 5:02pm UTC](https://discourse.julialang.org/t/package-to-work-with-piecewise-functions/95091/2 "2023-02-23T17:02:48Z")

</div>

```julia
julia> using ForwardDiff

julia> f(x) = x ≤ 0 ? exp(x) : x+1
f (generic function with 1 method)

julia> f′(x) = ForwardDiff.derivative(f, x)
f′ (generic function with 1 method)

julia> f(-1.0), f′(-1.0) # == exp(-1), exp(-1)
(0.36787944117144233, 0.36787944117144233)

julia> f( 1.0), f′( 1.0) # == 2, 1
(2.0, 1.0)

```

[ApproxFun.jl is another way to work with piecewise functions](https://juliaapproximation.github.io/ApproxFun.jl/latest/usage/constructors/) via piecewise polynomial approximations (see its `PiecewiseSegment` type).

---

<div class="post-metadata">

### Author: ![aerappa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aerappa/32/212281_2.png) [@aerappa](https://discourse.julialang.org/u/aerappa)
#### Post date: [March 2, 2023, 4:48pm UTC](https://discourse.julialang.org/t/package-to-work-with-piecewise-functions/95091/3 "2023-03-02T16:48:22Z")

</div>

Thanks for your reply! In our use case, we would like to use `Symbolics.jl` to take derivatives rather than `ForwardDiff.jl`. In particular, the issue I keep running into is the following issue:

```julia
julia> f(x) = x ≤ 0 ? exp(x) : x+1
f (generic function with 1 method)

julia> using Symbolics

julia> @syms x
(x,)

julia> f(x)
ERROR: MethodError: no method matching isless(::SymbolicUtils.BasicSymbolic{Number}, ::Int64)
Closest candidates are:
  isless(::Union{StatsBase.PValue, StatsBase.TestStat}, ::Real) at ~/.julia/packages/StatsBase/XgjIN/src/statmodels.jl:90
  isless(::ColorTypes.AbstractGray, ::Real) at ~/.julia/packages/ColorTypes/1dGw6/src/operations.jl:38
  isless(::SymbolicUtils.Symbolic{<:Real}, ::Real) at ~/.julia/packages/SymbolicUtils/Vzo2s/src/methods.jl:173
  ...
Stacktrace:
 [1] <(x::SymbolicUtils.BasicSymbolic{Number}, y::Int64)
   @ Base ./operators.jl:356
 [2] <=(x::SymbolicUtils.BasicSymbolic{Number}, y::Int64)
   @ Base ./operators.jl:405
 [3] f(x::SymbolicUtils.BasicSymbolic{Number})
   @ Main ./REPL[9]:1
 [4] top-level scope
   @ REPL[12]:1

julia> 

```

Edit: After having a look at [this thread](https://github.com/JuliaSymbolics/Symbolics.jl/issues/225), the following MWE seems pretty good for my needs

```julia
julia> f(x) = ifelse(x ≤ 0.0, exp(2*x), x^2+1)
f (generic function with 1 method)

julia> using Symbolics

julia> @syms x::Real
(x,)

julia> f(x)
ifelse(x <= 0.0, exp(2x), 1 + x^2)

julia> Symbolics.derivative(f(x), x)
ifelse(x <= 0.0, 2exp(2x), 2x)

```

Eventually, I also want to support multiple intervals, so I came up with the (admittedly clunky) solution for the case of two intervals

```julia
julia> ifelse2(c1, c2, x, y, z) = ifelse(c1, x, ifelse(!c2, y, z))
ifelse2 (generic function with 1 method)

julia> f2(x) = ifelse2(x ≤ 2, x > 4, x^2, exp(2*x), 4*x)
f2 (generic function with 1 method)

julia> Symbolics.derivative(f2(x), x)
ifelse(x <= 2, 2x, ifelse(!(x > 4), 2exp(2x), 4))

```
