# Generic functions with irrationals that work with Symbolics / ModelingToolkit

**URL:** <https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205>\
**Category:** General Usage\
**Tags:** type, modelingtoolkit, symbolics\
**Created:** [June 22, 2022, 9:39pm UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205 "2022-06-22T21:39:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![moble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moble/32/23535_2.png) [@moble](https://discourse.julialang.org/u/moble)\
**Post date:** [June 22, 2022, 9:39pm UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205/1 "2022-06-22T21:39:45Z")

</div>

I have some functions that basically evaluate polynomials with coefficients given by _enormous_ expressions. I want to support multiple precisions — like Float64 and Double64 — but also symbolic operations. And some of the coefficients involve irrationals. Let’s just take \pi as the example, though I actually need quite a few irrationals that I define. To support the various precisions, I simply put the polynomial inside a `let` block, at the start of which I redefine the irrationals (and some other things I need). Here’s a simplified version.

```julia
function p(x)
    let π=oftype(x, π)
        1 + (2//3 + 4π/5) * x
    end
end

```

This seems to work great for the floating-point types. But then I want to do symbolic stuff, like get the expression for `p` when `x` is a `Num`. In the `let` block, `π` is defined to be a `Num` type, which seems great, until I actually do anything with it — like multiply, divide, add, subtract. In those cases, `π` seems to be immediately converted to `Float64`, which is not what I want. This also seems to be a problem when I pass the result to ModelingToolkit.

Is there some way to hold off on evaluating expressions involving `Num(π)`, somewhat like `@register`?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 22, 2022, 10:12pm UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205/2 "2022-06-22T22:12:45Z")

</div>

> [@moble](#):
>
> This seems to work great for the floating-point types. But then I want to do symbolic stuff, like get the expression for `p` when `x` is a `Num`. In the `let` block, `π` is defined to be a `Num` type, which seems great, until I actually do anything with it — like multiply, divide, add, subtract. In those cases, `π` seems to be immediately converted to `Float64`, which is not what I want. This also seems to be a problem when I pass the result to ModelingToolkit.

Open an issue. I don’t think anyone has looked at interactions with Irrationals?

---

<div class="post-metadata">

**Author:** ![moble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moble/32/23535_2.png) [@moble](https://discourse.julialang.org/u/moble)\
**Post date:** [June 23, 2022, 4:00am UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205/3 "2022-06-23T04:00:30Z")

</div>

New issue is [here](https://github.com/JuliaSymbolics/Symbolics.jl/issues/629).

Reading through some of the linked posts, I found a hack that seems to work for me, for now: using things like `Term(identity, π)`.

For the code above, the simplest (and extra hacky) approach is to just add a new method to `oftype`:

```julia
Base.oftype(x::Num, y::Irrational) = Term(identity, y)

```

With that, `p(x)` returns the appropriate type, and retains all appropriate digits of \pi for floating-point input, but leaves the term unevaluated for symbolic input.

Is there a downside to this approach?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 23, 2022, 1:39pm UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205/4 "2022-06-23T13:39:24Z")

</div>

> [@moble](#):
>
> Is there a downside to this approach?

That looks correct to me, but I’d have @shashi review it. Make a PR?

---

<div class="post-metadata">

**Author:** ![moble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moble/32/23535_2.png) [@moble](https://discourse.julialang.org/u/moble)\
**Post date:** [June 24, 2022, 9:12pm UTC](https://discourse.julialang.org/t/generic-functions-with-irrationals-that-work-with-symbolics-modelingtoolkit/83205/5 "2022-06-24T21:12:32Z")

</div>

The `oftype` code above works for me, but wouldn’t work for most cases, so I’m not sure what the PR should be. A slightly more general/useful version might be

```julia
Base.convert(::Type{Num}, y::Irrational) = Symbolics.Term(identity, y)

```

But I think that’s still not what most people would want. From the discussion [here](https://github.com/JuliaSymbolics/Symbolics.jl/issues/496) (and maybe [here](https://discourse.julialang.org/t/symbolic-sqrt-2-and-sin-pi/58633/6)), it looks like people want to be able to do something like `Num(π)` and get the sensible thing, but surely it would be too much to do `Num(y::Irrational) = Term(identity, y)`, since that wouldn’t actually result in a `Num`, right?

I’m happy to do a PR if it helps move in a positive direction, but I feel like this problem calls for more thought and more knowledge of the inner workings than I have.

[But if `Term(identity, y)` is actually used, it might be worth adding a special case to [`show_term`](https://github.com/JuliaSymbolics/SymbolicUtils.jl/blob/c109aa20ac81d408f58b29c05049114f85366379/src/types.jl#L832) to just show the argument if the operation is `identity`, because \mathrm{identity}(\pi) is pretty ugly and could be confusing.]
