diff --git a/docs/src/manual/functions.md b/docs/src/manual/functions.md index ed9d9ac30..c38aaa097 100644 --- a/docs/src/manual/functions.md +++ b/docs/src/manual/functions.md @@ -66,9 +66,77 @@ is the partial derivative of the Julia `min(x,y)` function with respect to `x`. is required in the derivative expression is defined. Note that you only need to define the partial derivatives which are actually computed. +## Registration of Array Functions + +Similar to scalar functions, array functions can be registered to define new primitives for +functions which either take in or return arrays. This is done by using the `@register_array_symbolic` +macro. It acts similarly to the scalar function registration but requires a calculation of the +input and output sizes. For example, let's assume we wanted to have a function that computes the +solution to `Ax = b`, i.e. a linear solve, using an SVD factorization. In Julia, the code for this +would be `svdsolve(A,b) = svd(A)\b`. We would create this function as follows: + +```@example array_registration +using LinearAlgebra, Symbolics + +svdsolve(A, b) = svd(A)\b +@register_array_symbolic svdsolve(A::AbstractMatrix, b::AbstractVector) begin + size = size(b) + eltype = promote_type(eltype(A), eltype(b)) +end +``` + +Now using the function `svdsolve` with symbolic array variables will be kept lazy: + +```@example array_registration +@variables A[1:3, 1:3] b[1:3] +svdsolve(A,b) +``` + +Note that at this time array derivatives cannot be defined. + ## Registration API ```@docs @register_symbolic @register_array_symbolic ``` + +## Direct Registration API (Advanced, Experimental) + +!!! warn + + This is a lower level API which is not as stable as the macro APIs. + +In some circumstances you may need to use the direct API in order to define +registration on functions or types without using the macro. This is done +by directly defining dispatches on symbolic objects. + +A good exmample of this is DataInterpolations.jl's interpolations object. +On an interpolation by a symbolic variable, we generate the symbolic +function (the `term`) for the interpolation function. This looks like: + +```julia +using DataInterpolations, Symbolics, SymbolicUtils +(interp::AbstractInterpolation)(t::Num) = SymbolicUtils.term(interp, unwrap(t)) +``` + +In order for this to work, it is required that we define the `symtype` for the +symbolic type inference. This is done via: + +```julia +SymbolicUtils.promote_symtype(t::AbstractInterpolation, args...) = Real +``` + +Additionally a symbolic name is required: + +```julia +Base.nameof(interp::AbstractInterpolation) = :Interpolation +``` + +The derivative is defined similarly to the macro case: + +```julia +function Symbolics.derivative(interp::AbstractInterpolation, args::NTuple{1, Any}, ::Val{1}) + Symbolics.unwrap(derivative(interp, Symbolics.wrap(args[1]))) +end +``` \ No newline at end of file