text:
using Compat
import Compat.String

@testset "Types" begin
    solver = NelderMead()
    T = typeof(solver)
    trace = OptimizationTrace{Float64, T}()
    push!(trace,OptimizationState{Float64, T}(1,1.0,1.0,Dict()))
    push!(trace,OptimizationState{Float64, T}(2,1.0,1.0,Dict()))
    @test length(trace) == 2
    @test trace[end].iteration == 2

    prob = MultivariateProblems.UnconstrainedProblems.examples["Rosenbrock"]
    f_prob = MVP.objective(prob)
    for res in (
            Optim.optimize(f_prob, prob.initial_x, NelderMead()),
            Optim.optimize(f_prob, prob.initial_x, SimulatedAnnealing()),
            Optim.optimize(
                MVP.objective(prob),
                MVP.gradient(prob),
                prob.initial_x,
                LBFGS()
            )
        )
        @test typeof(f_prob(prob.initial_x)) == typeof(Optim.minimum(res))
        @test eltype(prob.initial_x) == eltype(Optim.minimizer(res))

        io = IOBuffer()
        show(io, res)
        s = String(take!(io))
        line_shift = res.method isa Union{SimulatedAnnealing,LBFGS} ? 5 : 1

        lines = split(s, '\n')
        @test lines[4] |> contains("Final objective value")
        @test lines[7] |> contains("Algorithm")
        @test lines[9] |> contains("Convergence measures")
        @test lines[13 + line_shift] |> contains("Iterations")
        @test lines[14 + line_shift] |> contains("f(x) calls")
        if res.method isa NelderMead
            @test lines[10] |> contains("√(Σ(yᵢ-ȳ)²)/n ≤ 1.0e-08")
        elseif res.method isa Union{SimulatedAnnealing,LBFGS}
            @test lines[10] |> contains("|x - x'|")
            @test lines[11] |> contains("|x - x'|/|x'|")
            @test lines[12] |> contains("|f(x) - f(x')|")
            @test lines[13] |> contains("|f(x) - f(x')|/|f(x')|")
            @test lines[14] |> contains("|g(x)|")
        end
    end

    io = IOBuffer()
    res = show(io, MIME"text/plain"(), Optim.Options(x_abstol = 10.0))
    @test String(take!(io)) |> contains("x_abstol = 10.0")
end


text:
using AdventOfCode
using Test

@testset "Year2021 Day25" begin
    example = IOBuffer(
        "v...>>.vv>\n" *
        ".vv>>.vv..\n" *
        ">>.>v>...v\n" *
        ">>v>>.>.v.\n" *
        "v>v.vv.v..\n" *
        ">.>>..v...\n" *
        ".vv..>.>v.\n" *
        "v.v..>>v.v\n" *
        "....v..v.>"
    )
    @test AdventOfCode.Year2021.Day25.solve(example) == 58
end

ext: jl


text:
using Pkg

Pkg.add.(["DifferentialEquations",
        "Plots",
        "MAT",
        "HDF5",
        "IJulia",
        "MultivariateStats",
        "ProgressMeter",
        "FFTW",
        "DSP"])

using IJulia # install IJulia kernel


text:
module ArrayifiedArrays

using Swizzles.Properties
using Swizzles.ScalarArrays
using Swizzles.WrapperArrays
using Swizzles.StylishArrays

using Swizzles

using Base: dataids, unaliascopy, unalias
using Base.Broadcast: Broadcasted, Extruded
using Base.Broadcast: BroadcastStyle, Style, DefaultArrayStyle, AbstractArrayStyle
using Base.Broadcast: instantiate, broadcastable, _broadcast_getindex, combine_eltypes, extrude, broadcast_unalias

export ArrayifiedArray, arrayify, preprocess

struct ArrayifiedArray{T, N, Arg} <: StylishArray{T, N}
    arg::Arg
    @inline function ArrayifiedArray{T, N, Arg}(arg::Arg) where {T, N, Arg}
        return new{T, N, typeof(arg)}(arg)
    end
end

@inline function ArrayifiedArray(arg)
    arr = ArrayifiedArray{Any}(arg)
    return ArrayifiedArray{Properties.eltype_bound(arr)}(arg)
end

@inline function ArrayifiedArray{T}(arg) where {T}
    arg = instantiate(broadcastable(arg))
    return ArrayifiedArray{T, ndims(arg), typeof(arg)}(arg)
end

@inline function ArrayifiedArray{T}(arg::Tuple) where {T}
    return ArrayifiedArray{T, 1, typeof(arg)}(arg)
end

@inline function ArrayifiedArray{T}(arg::Broadcasted{<:AbstractArrayStyle{0}, Nothing}) where {T}
    return ArrayifiedArray{T, 0, typeof(arg)}(arg)
end

@inline function ArrayifiedArray{T}(arg::Broadcasted{Style{Tuple}, Nothing}) where {T}
    return ArrayifiedArray{T, 1, typeof(arg)}(arg)
end

@inline function ArrayifiedArray{T, N}(arg) where {T, N}
    arg = instantiate(broadcastable(arg))
    return ArrayifiedArray{T, N, typeof(arg)}(arg)
end

@inline ArrayifiedArray{T}(arr::ArrayifiedArray{S, N, Arg}) where {T, S, N, Arg} = ArrayifiedArray{T, N, Arg}(arr.arg)
@inline ArrayifiedArray{T, N}(arr::ArrayifiedArray{S, N, Arg}) where {T, S, N, Arg} = ArrayifiedArray{T, N, Arg}(arr.arg)
@inline ArrayifiedArray{T, N, Arg}(arr::ArrayifiedArray{S, N, Arg}) where {T, S, N, Arg} = ArrayifiedArray{T, N, Arg}(arr.arg)

@inline function Properties.eltype_bound(arr::ArrayifiedArray)
    if arr.arg isa AbstractArray
        T = Properties.eltype_bound(arr.arg)
        if T <: eltype(arr)
            return T
        end
    else
        T = eltype(arr.arg)
        if T <: eltype(arr)
            return T
        else
            return eltype(arr)
        end
    end
end

@inline Base.eltype(bc::Broadcasted) = combine_eltypes(bc.f, bc.args)
@inline Base.similar(bc::Broadcasted) = similar(bc, eltype(bc))
@inline Base.similar(bc::Broadcasted, args...) = similar(bc, eltype(bc), args...)
@inline Base.similar(bc::Broadcasted{DefaultArrayStyle{0}}) = ScalarArray{eltype(bc)}()

@inline function Properties.eltype_bound(arr::ArrayifiedArray{<:Any, <:Any, <:Broadcasted})
    return combine_eltypes(arr.arg.f, arr.arg.args)
end

function Base.show(io::IO, arr::ArrayifiedArray{T, N}) where {T, N}
    print(io, ArrayifiedArray{T, N}) #Showing the arg type (although maybe useful since it's allowed to differ), will likely be redundant.
    print(io, '(', arr.arg, ')')
    nothing
end

arrayify(arg::AbstractArray) = arg
arrayify(arg) = ArrayifiedArray(arg)

#The general philosophy of a ArrayifiedArray is that it should use broadcast to answer questions unless it's arg is an abstract Array, then it should fall back to the parent
#We can go through and add more base Abstract Array stuff later.
Base.parent(arr::ArrayifiedArray) = arr
WrapperArrays.iswrapper(arr::ArrayifiedArray) = arr.arg isa AbstractArray

Base.dataids(arr::ArrayifiedArray) = dataids(arr.arg)
Base.unaliascopy(arr::ArrayifiedArray{T, N, Arg}) where {T, N, Arg} = ArrayifiedArray{T, N, Arg}(unaliascopy(arr.arg))
Base.unalias(dst, arr::ArrayifiedArray{T, N, Arg}) where {T, N, Arg} = ArrayifiedArray{T, N, Arg}(unalias(dst, arr.arg))

@inline Base.axes(arr::ArrayifiedArray) = axes(arr.arg)

@inline Base.size(arr::ArrayifiedArray) = map(length, axes(arr.arg))

@inline Base.eltype(arr::ArrayifiedArray{T}) where {T} = T

@inline Base.eachindex(arr::ArrayifiedArray{T, N, <:AbstractArray}) where {T, N} = eachindex(arr.arg)
@inline Base.eachindex(arr::ArrayifiedArray) = _eachindex(axes(arr))
_eachindex(t::Tuple{Any}) = t[1]
_eachindex(t::Tuple) = CartesianIndices(t)

Base.ndims(::Type{<:ArrayifiedArray{T, N}}) where {T, N} = N
Base.ndims(::ArrayifiedArray{T, N}) where {T, N} = N

Base.length(arr::ArrayifiedArray{T, N, <:AbstractArray}) where {T, N} = length(arr.arg)
Base.length(arr::ArrayifiedArray) = prod(map(length, axes(arr)))

#FIXME define some IndexStyle stuffs
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray{<:Any, <:Any, <:Broadcasted}, I::Int) = _broadcast_getindex(arr.arg, I)
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray{<:Any, <:Any, <:Broadcasted}, I::CartesianIndex) = _broadcast_getindex(arr.arg, I)
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray{<:Any, <:Any, <:Broadcasted}, I::Int...) = _broadcast_getindex(arr.arg, CartesianIndex(I))
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray{<:Any, <:Any, <:Broadcasted}) = _broadcast_getindex(arr.arg, 1)
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray, I::Int) = getindex(arr.arg, I)
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray, I::Int...) = getindex(arr.arg, I...)
Base.@propagate_inbounds Base.getindex(arr::ArrayifiedArray) = getindex(arr.arg)

Base.@propagate_inbounds Base.setindex!(arr::ArrayifiedArray, x, I::Int) = setindex(arr.arg, x, I)
Base.@propagate_inbounds Base.setindex!(arr::ArrayifiedArray, x, I::Int...) = setindex(arr.arg, x, I...)
Base.@propagate_inbounds Base.setindex!(arr::ArrayifiedArray, x) = setindex(arr.arg, x)

@inline myidentity(x) = x

@inline Base.Broadcast.broadcastable(arr::ArrayifiedArray) = broadcastable(arr.arg)

#This should do the same thing as Broadcast preprocess does, but apply the ArrayifiedArrays preprocess first
@inline Base.Broadcast.preprocess(dst, arr::AbstractArray) = extrude(broadcast_unalias(dst, preprocess(dst, arr)))
@inline Base.Broadcast.preprocess(dst, ext::Extruded) = Extruded(broadcast_unalias(dst, preprocess(dst, ext.x)), ext.keeps, ext.defaults) #make broadcast safe for double-preprocessing
@inline preprocess(dst, bc::Broadcasted) = Base.Broadcast.preprocess(dst, bc)
@inline function preprocess(dst, arr)
    if iswrapper(arr)
        adopt(arr, preprocess(dst, parent(arr)))
    else
        arr
    end
end
@inline function preprocess(dst, arr::ArrayifiedArray{T, N}) where {T, N}
    if arr.arg isa AbstractArray
        return preprocess(dst, arr)
    end
    arg = Base.Broadcast.preprocess(dst, arr.arg)
    return ArrayifiedArray{T, N, typeof(arg)}(arg)
end

@inline Base.Broadcast.BroadcastStyle(::Type{ArrayifiedArray{T, N, Arg}}) where {T, N, Arg} = BroadcastStyle(Arg)

end


text:
# Julia wrapper for header: /usr/include/scip/cons_xor.h
# Automatically generated using Clang.jl wrap_c

function SCIPincludeConshdlrXor(scip)
    ccall((:SCIPincludeConshdlrXor, libscip), SCIP_RETCODE, (Ptr{SCIP_},), scip)
end

function SCIPcreateConsXor(scip, cons, name, rhs, nvars, vars, initial, separate, enforce, check, propagate, _local, modifiable, dynamic, removable, stickingatnode)
    ccall((:SCIPcreateConsXor, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Ptr{Ptr{SCIP_CONS}}, Cstring, UInt32, Cint, Ptr{Ptr{SCIP_VAR}}, UInt32, UInt32, UInt32, UInt32, UInt32, UInt32, UInt32, UInt32, UInt32, UInt32), scip, cons, name, rhs, nvars, vars, initial, separate, enforce, check, propagate, _local, modifiable, dynamic, removable, stickingatnode)
end

function SCIPcreateConsBasicXor(scip, cons, name, rhs, nvars, vars)
    ccall((:SCIPcreateConsBasicXor, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Ptr{Ptr{SCIP_CONS}}, Cstring, UInt32, Cint, Ptr{Ptr{SCIP_VAR}}), scip, cons, name, rhs, nvars, vars)
end

function SCIPgetNVarsXor(scip, cons)
    ccall((:SCIPgetNVarsXor, libscip), Cint, (Ptr{SCIP_}, Ptr{SCIP_CONS}), scip, cons)
end

function SCIPgetVarsXor(scip, cons)
    ccall((:SCIPgetVarsXor, libscip), Ptr{Ptr{SCIP_VAR}}, (Ptr{SCIP_}, Ptr{SCIP_CONS}), scip, cons)
end

function SCIPgetIntVarXor(scip, cons)
    ccall((:SCIPgetIntVarXor, libscip), Ptr{SCIP_VAR}, (Ptr{SCIP_}, Ptr{SCIP_CONS}), scip, cons)
end

function SCIPgetRhsXor(scip, cons)
    ccall((:SCIPgetRhsXor, libscip), UInt32, (Ptr{SCIP_}, Ptr{SCIP_CONS}), scip, cons)
end


text:
const nodejs_version = v"12.13.0"
basedir = @__DIR__

if isdefined(Base, :LIBEXECDIR)
    const exe7z = joinpath(Sys.BINDIR, Base.LIBEXECDIR, "7z.exe")
else
    const exe7z = joinpath(Sys.BINDIR, "7z.exe")
end

if Sys.islinux()
    if (Sys.ARCH in (:x86_64, :i686, :i586, :i486, :i386)) && sizeof(Int) == 8
        download_filename_base = "node-v$(nodejs_version)-linux-x64"
        download_filename_ext = "tar.xz"
    elseif (Sys.ARCH in (:x86_64, :i686, :i586, :i486, :i386)) && sizeof(Int) == 4
        download_filename_base = "node-v$(nodejs_version)-linux-x86"
        download_filename_ext = "tar.xz"
    elseif (Sys.ARCH in (:arm,)) && sizeof(Int) == 8
        download_filename_base = "node-v$(nodejs_version)-linux-arm64"
        download_filename_ext = "tar.xz"
    elseif (Sys.ARCH in (:arm,)) && sizeof(Int) == 4
        download_filename_base = "node-v$(nodejs_version)-linux-armv7l"
        download_filename_ext = "tar.xz"
    else
        error("Unsupported platform.")
    end
elseif Sys.isapple()
    download_filename_base = "node-v$(nodejs_version)-darwin-x64"
    download_filename_ext = "tar.gz"
elseif Sys.iswindows()
    if sizeof(Int) == 8
        download_filename_base = "node-v$(nodejs_version)-win-x64"
        download_filename_ext = "zip"
    elseif sizeof(Int) == 4
        download_filename_base = "node-v$(nodejs_version)-win-x86"
        download_filename_ext = "zip"
    else
        error("Unsupported platform.")
    end
else
    error("Unsupported platform.")
end
download_folder = joinpath(basedir, "downloads")
download_filename_full = joinpath(download_folder, "$download_filename_base.$download_filename_ext")

bin_folder = joinpath(basedir, "bin")

install_folder = joinpath(bin_folder, download_filename_base)

# "https://nodejs.org/dist/v6.10.3/node-v6.10.3-win-x64.zip"
# "https://nodejs.org/dist/v6.10.3/node-v6.10.3-darwin-x64.tar.gz"
# "https://nodejs.org/dist/v6.10.3/node-v6.10.3-linux-x64.tar.xz"

base_url = "https://nodejs.org/dist/v$nodejs_version"

@static if Sys.iswindows()
    binary_name = "node.exe"
    npm_binary_name = "npm.cmd"
else
    binary_name = "node"
    npm_binary_name = "npm"
end

binary_target_path = Sys.iswindows() ? joinpath(install_folder, binary_name) : joinpath(install_folder, "bin", binary_name)

# Do we need to download?
if !isfile(download_filename_full)
    @info("Downloading Node.js binary")
    rm(download_folder, force=true, recursive=true)

    mkpath(download_folder)

    cd(download_folder) do
        download_url = "$base_url/$download_filename_base.$download_filename_ext"
        download(download_url, basename(download_url))
    end
end

if !isfile(binary_target_path)
    @info("Extracting Node.js binary")
    if Sys.iswindows()
        rm(string("\\\\?\\", bin_folder), force=true, recursive=true)
    else
        rm(bin_folder, force=true, recursive=true)
    end

    mkpath(bin_folder)

    if Sys.iswindows()

        cd(bin_folder) do
            read(`$exe7z x $download_filename_full`)
        end
    elseif Sys.islinux()
        read(pipeline(`unxz -c $download_filename_full `, `tar xv --directory=$bin_folder`))
    else
        read(`tar -xzf $download_filename_full --directory=$bin_folder`)
    end
end

npm_script_target_path = Sys.iswindows() ? joinpath(install_folder, "node_modules", "npm", "bin", "npm-cli.js") : joinpath(install_folder, "bin", "npm")
npm_executable_path = Sys.iswindows() ? joinpath(install_folder, npm_binary_name) : joinpath(install_folder, "bin", npm_binary_name)

open(joinpath(dirname(@__FILE__), "deps.jl"), "w") do f
    write(f, """
const node_executable_path = "$(escape_string(binary_target_path))"
const npm_script_path = "$(escape_string(npm_script_target_path))"
const npm_executable_path = "$(escape_string(npm_executable_path))"
""")

end


text:
#   Unit "mdm.jl" of the PosDefManifoldML Package for Julia language

#   MIT License
#   Copyright (c) 2019,
#   Marco Congedo, CNRS, Grenoble, France:
#   https://sites.google.com/site/marcocongedo/home
#   Saloni Jain, Indian Institute of Technology, Kharagpur, India

# ? CONTENTS :
#   This unit implements the Riemannian minimum distance to mean
#   machine learning classifier using package PosDefManifold.

"""
Abstract type for MDM (Minimum Distance to Mean)
machine learning models
"""
abstract type MDMmodel<:PDmodel end

"""
```
mutable struct MDM <: MDMmodel
    metric  :: Metric = Fisher;
    featDim :: Int
    means   :: ℍVector
    imeans  :: ℍVector
end
```

MDM machine learning models are incapsulated in this
mutable structure. MDM models have three fields:
`.metric`, `.featDim` and `.means`.

The field `metric`, of type
[Metric](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#Metric::Enumerated-type-1),
is to be specified by the user.
It is the metric that will be adopted to compute the class means
and the distances to the mean.

The field `featDim` is the dimension of the manifold in which
the model acts. This is given by ``n(n+1)/2``, where ``n``
is the dimension of the PD matrices.
This field is not to be specified by the user, instead,
it is computed when the MDM model is fit using the [`fit`](@ref)
function and is accessible only thereafter.

The field `means` is an
[ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%E2%84%8DVector-type-1)
holding the class means, i.e., one mean for each class.
This field is not to be specified by the user, instead,
the means are computed when the MDM model is fitted using the
[`fit`](@ref) function and are accessible only thereafter.

The field `imeans` is an ℍVector holding the inverse of the
matrices in `means`. This also is not to be specified by the user,
is computed when the model is fitted and is accessible only thereafter.
It is used to optimize the computation of distances if the
model is fitted useing the Fisher metric (default).

**Examples**:
```
using PosDefManifoldML, PosDefManifold

# create an empty model
m = MDM(Fisher)

# since the Fisher metric is the default metric,
# this is equivalent to
m = MDM()
```

Note that in general you need to invoke these constructors
only when an MDM model is needed as an argument to a function,
otherwise you can more simply create and fit an MDM model using
the [`fit`](@ref) function.

"""
mutable struct MDM <: MDMmodel
    metric :: Metric
    featDim
    means
    imeans
    function MDM(metric :: Metric = Fisher;
              featDim = nothing,
              means   = nothing,
              imeans  = nothing)
        new(metric, featDim, means)
    end
end

"""
```
function fit(model :: MDMmodel,
              𝐏Tr   :: ℍVector,
              yTr   :: IntVector;
       w        :: Vector = [],
       ✓w       :: Bool  = true,
       meanInit :: Union{ℍVector, Nothing} = nothing,
       tol      :: Real  = 1e-5,
       verbose  :: Bool  = true,
       ⏩       :: Bool  = true)
```

Fit an [`MDM`](@ref) machine learning model,
with training data `𝐏Tr`, of type
[ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%E2%84%8DVector-type-1),
and corresponding labels `yTr`, of type [IntVector](@ref).
Return the fitted model.

Labels must be provided using the natural numbers, i.e.,
`1` for the first class, `2` for the second class, etc.

Fitting an MDM model involves only computing a mean of all the
matrices in each class. Those class means are computed according
to the metric specified by the [`MDM`](@ref) constructor.

Optional keyword argument `w` is a vector of non-negative weights
associated with the matrices in `𝐏Tr`.
This weights are used to compute the mean for each class.
See method (3) of the [mean](https://marco-congedo.github.io/PosDefManifold.jl/dev/riemannianGeometry/#Statistics.mean)
function for the meaning of the arguments
`w`, `✓w` and `⏩`, to which they are passed.
Keep in mind that here the weights should sum up to 1
separatedly for each class, which is what is ensured by this
function if `✓w` is true.

Optional keyword argument `tol` is the tolerance required for those algorithms
that compute the mean iteratively (they are those adopting the Fisher, logde0
or Wasserstein metric). It defaults to 1e-5. For details on this argument see
the functions that are called for computing the means:
- Fisher metric: [gmean](https://marco-congedo.github.io/PosDefManifold.jl/dev/riemannianGeometry/#PosDefManifold.geometricMean)
- logdet0 metric: [ld0mean](https://marco-congedo.github.io/PosDefManifold.jl/dev/riemannianGeometry/#PosDefManifold.logdet0Mean)
- Wasserstein metric: [Wasmean](https://marco-congedo.github.io/PosDefManifold.jl/dev/riemannianGeometry/#PosDefManifold.wasMean).
For those algorithm an initialization can be provided with optional keyword
argument `meanInit`. If provided, this must be a vector of `Hermitian`
matrices of the [ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%F0%9D%95%84Vector-type-1)
type and must contain as many initializations as classes, in the
natural order corresponding to the class labels (see above).

If `verbose` is true (default), information is printed in the REPL.
This option is included to allow repeated calls to this function
without crowding the REPL.

**See**: [notation & nomenclature](@ref), [the ℍVector type](@ref).

**See also**: [`predict`](@ref), [`cvAcc`](@ref).

**Examples**
```
using PosDefManifoldML, PosDefManifold

# generate some data
PTr, PTe, yTr, yTe=gen2ClassData(10, 30, 40, 60, 80, 0.25)

# create and fit a model:
m=fit(MDM(Fisher), PTr, yTr)
```

"""
function fit(model :: MDMmodel,
              𝐏Tr   :: ℍVector,
              yTr   :: IntVector;
       w        :: Vector = [],
       ✓w       :: Bool   = true,
       meanInit :: Union{ℍVector, Nothing} = nothing,
       tol      :: Real   = 1e-5,
       verbose  :: Bool   = true,
       ⏩       :: Bool   = true)

    ⌚=now()

    ℳ=deepcopy(model) # output model

    k=length(𝐏Tr) # number of matrices
    !_check_fit(ℳ, k, length(yTr), length(w), 0, "MDM") && return

    verbose && println(greyFont, "Computing class means...")
    z = length(unique(yTr)) # number of classes
    𝐏 = [ℍ[] for i = 1:z]
    W = [Float64[] for i = 1:z]
    for j = 1:k push!(𝐏[yTr[j]], 𝐏Tr[j]) end
    if !isempty(w) for j = 1:k push!(W[yTr[j]], w[j]) end end

    meanInit==nothing ? ℳ.means = ℍVector([getMean(ℳ.metric, 𝐏[i];
                                              w=W[i], ✓w=✓w, tol=tol, ⏩=⏩) for i=1:z]) :
                        ℳ.means = ℍVector([getMean(ℳ.metric, 𝐏[i];
                                             w=W[i], ✓w=✓w, meanInit=meanInit[i], tol=tol, ⏩=⏩) for i=1:z])

    # store the inverse of the means for optimizing distance computations
    # if the metric is Fisher and the matrices are small
    if ℳ.metric==Fisher && size(𝐏Tr[1], 1)<=100
        if ⏩
            ℳ.imeans=ℍVector(undef, length(ℳ.means))
            @threads for i=1:length(ℳ.means) @inbounds ℳ.imeans[i]=inv(ℳ.means[i]) end
        else
            ℳ.imeans=ℍVector([inv(G) for G ∈ ℳ.means])
        end
    end

    ℳ.featDim =_triNum(𝐏Tr[1])

    verbose && println(defaultFont, "Done in ", now()-⌚,".")
    return ℳ
end

"""
```
function predict(model  :: MDMmodel,
                 𝐏Te    :: ℍVector,
                 what   :: Symbol = :labels;
        verbose :: Bool = true,
        ⏩     :: Bool = true)
```
Given an [`MDM`](@ref) `model` trained (fitted) on ``z`` classes
and a testing set of ``k`` positive definite matrices `𝐏Te` of type
[ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%E2%84%8DVector-type-1),

if `what` is `:labels` or `:l` (default), return
the predicted **class labels** for each matrix in `𝐏Te`,
as an [IntVector](@ref).
For MDM models, the predicted class 'label' of an unlabeled matrix is the
serial number of the class whose mean is the closest to the matrix
(minimum distance to mean).
The labels are '1' for class 1, '2' for class 2, etc;

if `what` is `:probabilities` or `:p`, return the predicted **probabilities**
for each matrix in `𝐏Te` to belong to a all classes, as a ``k``-vector
of ``z`` vectors holding reals in ``[0, 1]`` (probabilities).
The 'probabilities' are obtained passing to a
[softmax function](https://en.wikipedia.org/wiki/Softmax_function)
minus the squared distances of each unlabeled matrix to all class means;

if `what` is `:f` or `:functions`, return the **output function** of the model.
The ratio of the squared distance to all classes to
their geometric mean gives the 'functions'.

If `verbose` is true (default), information is printed in the REPL.
This option is included to allow repeated calls to this function
without crowding the REPL.

It f `⏩` is true (default), the computation of distances is multi-threaded.

**See**: [notation & nomenclature](@ref), [the ℍVector type](@ref).

**See also**: [`fit`](@ref), [`cvAcc`](@ref), [`predictErr`](@ref).

**Examples**
```
using PosDefManifoldML, PosDefManifold

# generate some data
PTr, PTe, yTr, yTe=gen2ClassData(10, 30, 40, 60, 80)

# craete and fit an MDM model
m=fit(MDM(Fisher), PTr, yTr)

# predict labels
yPred=predict(m, PTe, :l)

# prediction error
predErr=predictErr(yTe, yPred)

# predict probabilities
predict(m, PTe, :p)

# output functions
predict(m, PTe, :f)

```
"""
function predict(model  :: MDMmodel,
                 𝐏Te    :: ℍVector,
                 what   :: Symbol = :labels;
            verbose :: Bool = true,
            ⏩     :: Bool = true)

    if !_whatIsValid(what, "predict (MDM model)") return end
    ⌚=now()

    verbose && println(greyFont, "Computing distances...")
    D = getDistances(model.metric, model.means, 𝐏Te; imeans=model.imeans, ⏩=⏩)
    (z, k)=size(D)

    verbose && println("Predicting...")
    if     what == :functions || what == :f
           gmeans=[PosDefManifold.mean(Fisher, D[:, j]) for j = 1:k]
           func(j::Int)=[D[i, j]/gmeans[j] for i=1:z]
           🃏 = [func(j) for j = 1:k]
    elseif what == :labels || what == :l
           🃏 = [findmin(D[:, j])[2] for j = 1:k]
    elseif what == :probabilities || what == :p
           🃏 = [softmax(-D[:, j]) for j = 1:k]
    end

    verbose && println(defaultFont, "Done in ", now()-⌚,".")
    verbose && println(titleFont, "\nPredicted ",_what2Str(what),":", defaultFont)
    return 🃏
end

"""
```
function getMean(metric :: Metric,
                 𝐏      :: ℍVector;
              w        :: Vector = [],
              ✓w       :: Bool    = true,
              meanInit :: Union{ℍ, Nothing} = nothing,
              tol      :: Real   = 0.,
              ⏩      :: Bool    = true)
```

Typically, you will not need this function as it is called by the
[`fit`](@ref) function.

Given a `metric` of type
[Metric](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#Metric::Enumerated-type-1),
an [ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%E2%84%8DVector-type-1)
of Hermitian matrices `𝐏` and an optional
non-negative real weights vector `w`,
return the (weighted) mean of the matrices in `𝐏`.
This is used to fit MDM models.

This function calls the appropriate mean functions of package
[PostDefManifold](https://marco-congedo.github.io/PosDefManifold.jl/dev/),
depending on the chosen `metric`,
and check that, if the mean is found by an iterative algorithm,
then the iterative algorithm converges.

See method (3) of the [mean](https://marco-congedo.github.io/PosDefManifold.jl/dev/riemannianGeometry/#Statistics.mean)
function for the meaning of the optional keyword arguments
`w`, `✓w`, `meanInit`, `tol` and `⏩`, to which they are passed.

The returned mean is flagged by Julia as an Hermitian matrix
(see [LinearAlgebra](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/)).

"""
function getMean(metric :: Metric,
                 𝐏      :: ℍVector;
              w        :: Vector = [],
              ✓w       :: Bool    = true,
              meanInit :: Union{ℍ, Nothing} = nothing,
              tol      :: Real   = 0.,
              ⏩      :: Bool    = true)

  tol==0. ? tolerance = √eps(real(eltype(𝐏[1]))) : tolerance = tol

  if      metric == Fisher
              G, iter, convergence = gMean(𝐏; w=w, ✓w=✓w, init=meanInit, tol=tolerance, ⏩=⏩)
  elseif  metric == logdet0
              G, iter, convergence = ld0Mean(𝐏; w=w, ✓w=✓w, init=meanInit, tol=tolerance, ⏩=⏩)
  elseif  metric == Wasserstein
              G, iter, convergence = wasMean(𝐏; w=w, ✓w=✓w, init=meanInit, tol=tolerance, ⏩=⏩)
  else        G = mean(metric, 𝐏, w=w, ✓w=✓w, ⏩=⏩)
  end

  if metric ∈ (Fisher, logdet0, Wasserstein) && convergence > tolerance
      tolerance == 0. ? toltype="default" : toltype="chosen"
      @error 📌*", getMean function: the iterative algorithm for computing
      the means did not converge using the "*toltype*" tolerance.
      Check your data and try an higher tolerance (with the `tol`=... argument)."
  else
      return G
  end
end

"""
```
function getDistances(metric :: Metric,
                      means  :: ℍVector,
                      𝐏      :: ℍVector;
                imeans  :: Union{ℍVector, Nothing} = false,
                scale   :: Bool = false,
                ⏩      :: Bool = true)
```
Typically, you will not need this function as it is called by the
[`predict`](@ref) function.

Given an [ℍVector](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#%E2%84%8DVector-type-1)
`𝐏` holding ``k`` Hermitian matrices and
an ℍVector `means` holding ``z`` matrix means,
return the *square of the distance* of each matrix in `𝐏` to the means
in `means`.

The squared distance is computed according to the chosen `metric`, of type
[Metric](https://marco-congedo.github.io/PosDefManifold.jl/dev/MainModule/#Metric::Enumerated-type-1).
See [metrics](https://marco-congedo.github.io/PosDefManifold.jl/dev/introToRiemannianGeometry/#metrics-1)
for details on the supported distance functions.

The computation of distances is optimized for the Fisher metric
if an ℍVector holding the inverse of the means in `means` is passed as
optional keyword argument `imeans`.

If `scale` is true,
the distances are divided by the size of the matrices in `𝐏`.
This is used to compare disctances computed on manifolds with
different dimensions.

If `⏩` is true, the distances are computed using multi-threading,
unless the number of threads Julia is instructed to use is <2 or <3k.

The result is a ``z``x``k`` matrix of squared distances.

"""
function getDistances(metric :: Metric,
             means  :: ℍVector,
             𝐏      :: ℍVector;
          imeans :: Union{ℍVector, Nothing} = false,
          scale  :: Bool = false,
          ⏩    :: Bool = true)

    z, k = length(means), length(𝐏)
    if ⏩
        D = Matrix{eltype(𝐏[1])}(undef, z, k)
        threads, ranges = _GetThreadsAndLinRanges(length(𝐏), "getDistances")

        dist(i::Int, r::Int) =
           if metric==Fisher && imeans≠nothing
               for j in ranges[r] D[i, j]=sum(log.(eigvals(imeans[i]*𝐏[j]; permute=false, scale=false)).^2) end
           else
               for j in ranges[r] D[i, j]=distance²(metric, 𝐏[j], means[i]) end
           end

        for i=1:z @threads for r=1:length(ranges) dist(i, r) end end
    else
        D=[distance²(metric, 𝐏[j], means[i]) for i=1:z, j=1:k]
    end
    # optimize in PosDefManifold, don't need to compute all distances for some metrics
    return scale ? D./size(𝐏[1], 1) : D
end

# ++++++++++++++++++++  Show override  +++++++++++++++++++ # (REPL output)
function Base.show(io::IO, ::MIME{Symbol("text/plain")}, M::MDM)
    if M.means==nothing
        println(io, greyFont, "\n↯ MDM machine learning model")
        println(io, "⭒  ⭒    ⭒       ⭒          ⭒")
        println(io, ".metric : ", string(M.metric), defaultFont)
        println(io, "Unfitted model")
    else
        println(io, titleFont, "\n↯ MDM machine learning model")
        println(io, separatorFont, "⭒  ⭒    ⭒       ⭒          ⭒", defaultFont)
        nc=length(M.means)
        n=size(M.means[1], 1)
        println(io, "type    : PD Manifold model")
        println(io, "features: $(n)x$(n) Hermitian matrices")
        println(io, "classes : $(nc)")
        println(io, separatorFont, "Fields  : ")
        # # #
        println(io, greyFont, " MDM Parametrization", defaultFont)
        println(io, separatorFont," .metric  ", defaultFont, string(M.metric))
        println(io, separatorFont," .means   ", defaultFont, "vector of $(nc) Hermitian matrices")
        println(io, separatorFont," .imeans  ", defaultFont, "vector of $(nc) Hermitian matrices")
        println(io, separatorFont," .featDim ", defaultFont, "$(M.featDim) ($(n)*($(n)+1)/2)")
    end
end


text:
#= Generate toy problems =#

function generateToyProblem1()
    vtx = collect(transpose(
        Float64[0 0; 2 0; 4 0; 4 2; 4 4; 2 4; 0 4; 0 2; 2 1; 3 2; 2 3; 1 2]))
    bnd = Int64[1,2,3,4,5,6,7,8]
    elt = [Int64[1,2,9,12,8],
        Int64[2,3,4,10,9],
        Int64[10,4,5,6,11],
        Int64[8,12,11,6,7],
        Int64[9,10,11,12]
    ]
    return vtx, elt, bnd
end

function generateToyProblem2()
    vtx = collect(transpose(Float64[0 0; 0.5 0; 0 1; 1 0; 2 0; 2 1; 1.5 1; 1.5 0.5; 1 1.5]))
    bnd = Int64[1,2,3,4,5,6,7,9]
    elt = [
        Int64[1,2,3],
        Int64[2,4,8,7,9,3],
        Int64[4,5,6,7,8]
    ]
    return vtx, elt, bnd
end

function correctDataToyProblem2()
    nod2e = [
        Int64[1], Int64[1, 2], Int64[1, 2], Int64[2,3], Int64[3], Int64[3],
        Int64[2, 3], Int64[2,3], Int64[2]
    ]
    e2neighs = [
        Int64[0, 2, 0], Int64[0, 3, 3, 0, 0, 1], Int64[0, 0, 0, 2, 2]
    ]
    nedg = Int64(11)
    e2edg = [
        Int64[1, 2, 3], Int64[4, 5, 6, 7, 8, 2], Int64[9, 10, 11, 6, 5]
    ]
    freeedg = [true, false, true, true, false, false, true, true, true, true, true]
    freenod = [true, true, true, true, true, true, true, false, true]
    return nod2e, e2neighs, nedg, e2edg, freeedg, freenod
end

function connectivityToyProblem2()
    conn = [
        Int64[1,2,3], Int64[4,5,6,7,8,-2], Int64[9,10,11,-6,-5]
    ]
    return conn
end


text:
function f(a, b)
    return a + b
end

x = f(1, 2)


text:
module TestCxxDereference
  using CxxWrap

  struct Foo end

  CxxWrap.reference_type_union(::Type{Foo}) = Union{Foo, CxxWrap.CxxBaseRef{Foo}}
  CxxWrap.reference_type_union(::Type{Int}) = Union{Int, Ref{Int}}
  CxxWrap.dereference_argument(x::Ref{Int}) = x[]

  @cxxdereference function foo(a::Foo, b::Int, c...)
    return b + sum(c)
  end

  @cxxdereference unnamedparam(::Type{Int}, x) = Int(x)
end

using Test
using MacroTools

@testset "$(basename(@__FILE__)[1:end-3])" begin

@test TestCxxDereference.foo(TestCxxDereference.Foo(), 2, 1,2,3) == 8
@test_throws MethodError TestCxxDereference.foo(TestCxxDereference.Foo(), Ref(2), 1,2,Ref(3.0))
@test TestCxxDereference.foo(TestCxxDereference.Foo(), Ref(2), 1,2.0,Ref(3)) == 8
@test TestCxxDereference.unnamedparam(Int, 3) == 3

end


text:
int_rules_2_3 = @theory begin

    #= ::Subsection::Closed:: =#
    #= 2.3*Miscellaneous*exponentials =#
    @apply_utils Antiderivative(((~F) ^ (~(c') * (~(a') + ~(b') * ~x))) ^ ~(n'), ~x) => ((~F) ^ (~c * (~a + ~b * ~x))) ^ ~n / (~b * ~c * ~n * log(~F)) <-- FreeQ([~F, ~a, ~b, ~c, ~n], ~x)
    @apply_utils Antiderivative(~u * (~F) ^ (~(c') * ~v), ~x) => Antiderivative(ExpandIntegrand(~u * (~F) ^ (~c * ExpandToSum(~v, ~x)), ~x), ~x) <-- FreeQ([~F, ~c], ~x) && (PolynomialQ(~u, ~x) && (LinearQ(~v, ~x) && TrueQ($UseGamma)))
    @apply_utils Antiderivative(~u * (~F) ^ (~(c') * ~v), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~c * ExpandToSum(~v, ~x)), ~u, ~x), ~x) <-- FreeQ([~F, ~c], ~x) && (PolynomialQ(~u, ~x) && (LinearQ(~v, ~x) && Not(TrueQ($UseGamma))))
    @apply_utils Antiderivative((~u) ^ ~(m') * (~F) ^ (~(c') * ~v) * ~w, ~x) => With([b = Coefficient(~v, ~x, 1), d = Coefficient(~u, ~x, 0), e = Coefficient(~u, ~x, 1), f = Coefficient(~w, ~x, 0), g = Coefficient(~w, ~x, 1)], (g * (~u) ^ (~m + 1) * (~F) ^ (~c * ~v)) / (b * ~c * e * log(~F)) <-- EqQ(e * g * (~m + 1) - b * ~c * (e * f - d * g) * log(~F), 0)) <-- FreeQ([~F, ~c, ~m], ~x) && LinearQ([~u, ~v, ~w], ~x)
    @apply_utils Antiderivative(~w * (~u) ^ ~(m') * (~F) ^ (~(c') * ~v), ~x) => Antiderivative(ExpandIntegrand(~w * NormalizePowerOfLinear(~u, ~x) ^ ~m * (~F) ^ (~c * ExpandToSum(~v, ~x)), ~x), ~x) <-- FreeQ([~F, ~c], ~x) && (PolynomialQ(~w, ~x) && (LinearQ(~v, ~x) && (PowerOfLinearQ(~u, ~x) && (IntegerQ(~m) && TrueQ($UseGamma)))))
    @apply_utils Antiderivative(~w * (~u) ^ ~(m') * (~F) ^ (~(c') * ~v), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~c * ExpandToSum(~v, ~x)), ~w * NormalizePowerOfLinear(~u, ~x) ^ ~m, ~x), ~x) <-- FreeQ([~F, ~c], ~x) && (PolynomialQ(~w, ~x) && (LinearQ(~v, ~x) && (PowerOfLinearQ(~u, ~x) && (IntegerQ(~m) && Not(TrueQ($UseGamma))))))
    @apply_utils Antiderivative(~w * (~u) ^ ~(m') * (~F) ^ (~(c') * ~v), ~x) => Module([uu = NormalizePowerOfLinear(~u, ~x), z], z = If(PowerQ(uu) && FreeQ(uu(2), ~x), uu(1) ^ (~m * uu(2)), uu ^ ~m); (uu ^ ~m / z) * Antiderivative(ExpandIntegrand(~w * z * (~F) ^ (~c * ExpandToSum(~v, ~x)), ~x), ~x)) <-- FreeQ([~F, ~c, ~m], ~x) && (PolynomialQ(~w, ~x) && (LinearQ(~v, ~x) && (PowerOfLinearQ(~u, ~x) && Not(IntegerQ(~m)))))
    @apply_utils Antiderivative((~F) ^ (~(c') * (~(a') + ~(b') * ~x)) * log(~(d') * ~x) ^ ~(n') * (~e + ~(h') * (~(f') + ~(g') * ~x) * log(~(d') * ~x)), ~x) => (~e * ~x * (~F) ^ (~c * (~a + ~b * ~x)) * log(~d * ~x) ^ (~n + 1)) / (~n + 1) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~n], ~x) && (EqQ(~e - ~f * ~h * (~n + 1), 0) && (EqQ(~g * ~h * (~n + 1) - ~b * ~c * ~e * log(~F), 0) && NeQ(~n, -1)))
    @apply_utils Antiderivative((~x) ^ ~(m') * (~F) ^ (~(c') * (~(a') + ~(b') * ~x)) * log(~(d') * ~x) ^ ~(n') * (~e + ~(h') * (~(f') + ~(g') * ~x) * log(~(d') * ~x)), ~x) => (~e * (~x) ^ (~m + 1) * (~F) ^ (~c * (~a + ~b * ~x)) * log(~d * ~x) ^ (~n + 1)) / (~n + 1) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x) && (EqQ(~e * (~m + 1) - ~f * ~h * (~n + 1), 0) && (EqQ(~g * ~h * (~n + 1) - ~b * ~c * ~e * log(~F), 0) && NeQ(~n, -1)))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x)), ~x) => (~F) ^ (~a + ~b * (~c + ~d * ~x)) / (~b * ~d * log(~F)) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x)
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ 2), ~x) => ((~F) ^ ~a * sqrt(pi) * erfi((~c + ~d * ~x) * Rt(~b * log(~F), 2))) / (2 * ~d * Rt(~b * log(~F), 2)) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && PosQ(~b)
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ 2), ~x) => ((~F) ^ ~a * sqrt(pi) * erf((~c + ~d * ~x) * Rt(-(~b) * log(~F), 2))) / (2 * ~d * Rt(-(~b) * log(~F), 2)) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && NegQ(~b)
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~c + ~d * ~x) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / ~d - ~b * ~n * log(~F) * Antiderivative((~c + ~d * ~x) ^ ~n * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && (IntegerQ(2 / ~n) && ILtQ(~n, 0))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => With([k = Denominator(~n)], (k / ~d) * Subst(Antiderivative((~x) ^ (k - 1) * (~F) ^ (~a + ~b * (~x) ^ (k * ~n)), ~x), ~x, (~c + ~d * ~x) ^ (1 / k))) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && (IntegerQ(2 / ~n) && Not(IntegerQ(~n)))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => (-((~F) ^ ~a) * (~c + ~d * ~x) * Gamma(1 / ~n, -(~b) * (~c + ~d * ~x) ^ ~n * log(~F))) / (~d * ~n * (-(~b) * (~c + ~d * ~x) ^ ~n * log(~F)) ^ (1 / ~n)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~n], ~x) && Not(IntegerQ(2 / ~n))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~e + ~f * ~x) ^ ~n * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~b * ~f * ~n * (~c + ~d * ~x) ^ ~n * log(~F)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x) && (EqQ(~m, ~n - 1) && EqQ(~d * ~e - ~c * ~f, 0))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n) / (~(e') + ~(f') * ~x), ~x) => ((~F) ^ ~a * ExpIntegralEi(~b * (~c + ~d * ~x) ^ ~n * log(~F))) / (~f * ~n) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x) && EqQ(~d * ~e - ~c * ~f, 0)
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => (1 / (~d * (~m + 1))) * Subst(Antiderivative((~F) ^ (~a + ~b * (~x) ^ 2), ~x), ~x, (~c + ~d * ~x) ^ (~m + 1)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~m, ~n], ~x) && EqQ(~n, 2 * (~m + 1))
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~c + ~d * ~x) ^ ((~m - ~n) + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~b * ~d * ~n * log(~F)) - (((~m - ~n) + 1) / (~b * ~n * log(~F))) * Antiderivative((~c + ~d * ~x) ^ (~m - ~n) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && (IntegerQ((2 * (~m + 1)) / ~n) && (LtQ(0, (~m + 1) / ~n, 5) && (IntegerQ(~n) && (LtQ(0, ~n, ~m + 1) || LtQ(~m, ~n, 0)))))
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~c + ~d * ~x) ^ ((~m - ~n) + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~b * ~d * ~n * log(~F)) - (((~m - ~n) + 1) / (~b * ~n * log(~F))) * Antiderivative((~c + ~d * ~x) ^ Simplify(~m - ~n) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~m, ~n], ~x) && (IntegerQ(2 * Simplify((~m + 1) / ~n)) && (LtQ(0, Simplify((~m + 1) / ~n), 5) && (Not(RationalQ(~m)) && SumSimplerQ(~m, -(~n)))))
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~c + ~d * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~d * (~m + 1)) - ((~b * ~n * log(~F)) / (~m + 1)) * Antiderivative((~c + ~d * ~x) ^ (~m + ~n) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && (IntegerQ((2 * (~m + 1)) / ~n) && (LtQ(-4, (~m + 1) / ~n, 5) && (IntegerQ(~n) && (GtQ(~n, 0) && LtQ(~m, -1) || GtQ(-(~n), 0) && LeQ(-(~n), ~m + 1)))))
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~c + ~d * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~d * (~m + 1)) - ((~b * ~n * log(~F)) / (~m + 1)) * Antiderivative((~c + ~d * ~x) ^ Simplify(~m + ~n) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~m, ~n], ~x) && (IntegerQ(2 * Simplify((~m + 1) / ~n)) && (LtQ(-4, Simplify((~m + 1) / ~n), 5) && (Not(RationalQ(~m)) && SumSimplerQ(~m, ~n))))
    @apply_utils Antiderivative((~(c') + ~(d') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => With([k = Denominator(~n)], (k / ~d) * Subst(Antiderivative((~x) ^ (k * (~m + 1) - 1) * (~F) ^ (~a + ~b * (~x) ^ (k * ~n)), ~x), ~x, (~c + ~d * ~x) ^ (1 / k))) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~m, ~n], ~x) && (IntegerQ((2 * (~m + 1)) / ~n) && (LtQ(0, (~m + 1) / ~n, 5) && Not(IntegerQ(~n))))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~e + ~f * ~x) ^ ~m / (~c + ~d * ~x) ^ ~m) * Antiderivative((~c + ~d * ~x) ^ ~m * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~m, ~n], ~x) && (EqQ(~d * ~e - ~c * ~f, 0) && (IntegerQ(2 * Simplify((~m + 1) / ~n)) && (Not(IntegerQ(~m)) && (NeQ(~f, ~d) && NeQ(~c * ~e, 0)))))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => With([p = Simplify((~m + 1) / ~n)], ((-((~F) ^ ~a) * (~f / ~d) ^ ~m) / (~d * ~n * (-(~b) * log(~F)) ^ p)) * Simplify(FunctionExpand(Gamma(p, -(~b) * (~c + ~d * ~x) ^ ~n * log(~F)))) <-- IGtQ(p, 0)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~m, ~n], ~x) && (EqQ(~d * ~e - ~c * ~f, 0) && Not(TrueQ($UseGamma)))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((-((~F) ^ ~a) * (~e + ~f * ~x) ^ (~m + 1)) / (~f * ~n * (-(~b) * (~c + ~d * ~x) ^ ~n * log(~F)) ^ ((~m + 1) / ~n))) * Gamma((~m + 1) / ~n, -(~b) * (~c + ~d * ~x) ^ ~n * log(~F)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~m, ~n], ~x) && EqQ(~d * ~e - ~c * ~f, 0)
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ 2), ~x) => ((~f * (~e + ~f * ~x) ^ (~m - 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2)) / (2 * ~b * (~d) ^ 2 * log(~F)) + ((~d * ~e - ~c * ~f) / ~d) * Antiderivative((~e + ~f * ~x) ^ (~m - 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2), ~x)) - (((~m - 1) * (~f) ^ 2) / (2 * ~b * (~d) ^ 2 * log(~F))) * Antiderivative((~e + ~f * ~x) ^ (~m - 2) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && (NeQ(~d * ~e - ~c * ~f, 0) && (FractionQ(~m) && GtQ(~m, 1)))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ 2), ~x) => ((~f * (~e + ~f * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2)) / ((~m + 1) * (~f) ^ 2) + ((2 * ~b * ~d * (~d * ~e - ~c * ~f) * log(~F)) / ((~f) ^ 2 * (~m + 1))) * Antiderivative((~e + ~f * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2), ~x)) - ((2 * ~b * (~d) ^ 2 * log(~F)) / ((~f) ^ 2 * (~m + 1))) * Antiderivative((~e + ~f * ~x) ^ (~m + 2) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && (NeQ(~d * ~e - ~c * ~f, 0) && LtQ(~m, -1))
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => ((~e + ~f * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n)) / (~f * (~m + 1)) - ((~b * ~d * ~n * log(~F)) / (~f * (~m + 1))) * Antiderivative((~e + ~f * ~x) ^ (~m + 1) * (~c + ~d * ~x) ^ (~n - 1) * (~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && (NeQ(~d * ~e - ~c * ~f, 0) && (IGtQ(~n, 2) && LtQ(~m, -1)))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') / (~(c') + ~(d') * ~x)) / (~(e') + ~(f') * ~x), ~x) => (~d / ~f) * Antiderivative((~F) ^ (~a + ~b / (~c + ~d * ~x)) / (~c + ~d * ~x), ~x) - ((~d * ~e - ~c * ~f) / ~f) * Antiderivative((~F) ^ (~a + ~b / (~c + ~d * ~x)) / ((~c + ~d * ~x) * (~e + ~f * ~x)), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && NeQ(~d * ~e - ~c * ~f, 0)
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') / (~(c') + ~(d') * ~x)), ~x) => ((~e + ~f * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b / (~c + ~d * ~x))) / (~f * (~m + 1)) + ((~b * ~d * log(~F)) / (~f * (~m + 1))) * Antiderivative(((~e + ~f * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b / (~c + ~d * ~x))) / (~c + ~d * ~x) ^ 2, ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && (NeQ(~d * ~e - ~c * ~f, 0) && ILtQ(~m, -1))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n) / (~(e') + ~(f') * ~x), ~x) => Unintegrable((~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n) / (~e + ~f * ~x), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x) && NeQ(~d * ~e - ~c * ~f, 0)
    @apply_utils Antiderivative((~u) ^ ~(m') * (~F) ^ ~v, ~x) => Antiderivative(ExpandToSum(~u, ~x) ^ ~m * (~F) ^ ExpandToSum(~v, ~x), ~x) <-- FreeQ([~F, ~m], ~x) && (LinearQ(~u, ~x) && (BinomialQ(~v, ~x) && Not(LinearMatchQ(~u, ~x) && BinomialMatchQ(~v, ~x))))
    @apply_utils Antiderivative(~u * (~F) ^ (~(a') + ~(b') * (~(c') + ~(d') * ~x) ^ ~n), ~x) => Antiderivative(ExpandLinearProduct((~F) ^ (~a + ~b * (~c + ~d * ~x) ^ ~n), ~u, ~c, ~d, ~x), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~n], ~x) && PolynomialQ(~u, ~x)
    @apply_utils Antiderivative(~(u') * (~F) ^ (~(a') + ~(b') * ~v), ~x) => Antiderivative(~u * (~F) ^ (~a + ~b * NormalizePowerOfLinear(~v, ~x)), ~x) <-- FreeQ([~F, ~a, ~b], ~x) && (PolynomialQ(~u, ~x) && (PowerOfLinearQ(~v, ~x) && Not(PowerOfLinearMatchQ(~v, ~x))))
    #= Antiderivative((~u')*(~F)^((~a')+(~b')*(~v)^(~n)),~x) :=  Antiderivative(u*F^(a+b*ExpandToSum(v,x)^n),x) <-- FreeQ([F,a,b,n],x) &&  PolynomialQ(u,x) && LinearQ(v,x) && Not(LinearMatchQ(v,x)) =#
    #= Antiderivative((~u')*(~F)^(~u),~x) := Antiderivative(u*F^ExpandToSum(u,x),x) <--  FreeQ(F,x) && PolynomialQ(u,x) && BinomialQ(u,x) &&  Not(BinomialMatchQ(u,x)) =#
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') / (~(c') + ~(d') * ~x)) / ((~(e') + ~(f') * ~x) * (~(g') + ~(h') * ~x)), ~x) => (-(~d) / (~f * (~d * ~g - ~c * ~h))) * Subst(Antiderivative((~F) ^ ((~a - (~b * ~h) / (~d * ~g - ~c * ~h)) + (~d * ~b * ~x) / (~d * ~g - ~c * ~h)) / ~x, ~x), ~x, (~g + ~h * ~x) / (~c + ~d * ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f], ~x) && EqQ(~d * ~e - ~c * ~f, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(e') + (~(f') * (~(a') + ~(b') * ~x)) / (~(c') + ~(d') * ~x)), ~x) => (~F) ^ (~e + (~f * ~b) / ~d) * Antiderivative((~g + ~h * ~x) ^ ~m, ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m], ~x) && EqQ(~b * ~c - ~a * ~d, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(e') + (~(f') * (~(a') + ~(b') * ~x)) / (~(c') + ~(d') * ~x)), ~x) => Antiderivative((~g + ~h * ~x) ^ ~m * (~F) ^ ((~d * ~e + ~b * ~f) / ~d - (~f * (~b * ~c - ~a * ~d)) / (~d * (~c + ~d * ~x))), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m], ~x) && (NeQ(~b * ~c - ~a * ~d, 0) && EqQ(~d * ~g - ~c * ~h, 0))
    @apply_utils Antiderivative((~F) ^ (~(e') + (~(f') * (~(a') + ~(b') * ~x)) / (~(c') + ~(d') * ~x)) / (~(g') + ~(h') * ~x), ~x) => (~d / ~h) * Antiderivative((~F) ^ (~e + (~f * (~a + ~b * ~x)) / (~c + ~d * ~x)) / (~c + ~d * ~x), ~x) - ((~d * ~g - ~c * ~h) / ~h) * Antiderivative((~F) ^ (~e + (~f * (~a + ~b * ~x)) / (~c + ~d * ~x)) / ((~c + ~d * ~x) * (~g + ~h * ~x)), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h], ~x) && (NeQ(~b * ~c - ~a * ~d, 0) && NeQ(~d * ~g - ~c * ~h, 0))
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~m * (~F) ^ (~(e') + (~(f') * (~(a') + ~(b') * ~x)) / (~(c') + ~(d') * ~x)), ~x) => ((~g + ~h * ~x) ^ (~m + 1) * (~F) ^ (~e + (~f * (~a + ~b * ~x)) / (~c + ~d * ~x))) / (~h * (~m + 1)) - ((~f * (~b * ~c - ~a * ~d) * log(~F)) / (~h * (~m + 1))) * Antiderivative(((~g + ~h * ~x) ^ (~m + 1) * (~F) ^ (~e + (~f * (~a + ~b * ~x)) / (~c + ~d * ~x))) / (~c + ~d * ~x) ^ 2, ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h], ~x) && (NeQ(~b * ~c - ~a * ~d, 0) && (NeQ(~d * ~g - ~c * ~h, 0) && ILtQ(~m, -1)))
    @apply_utils Antiderivative((~F) ^ (~(e') + (~(f') * (~(a') + ~(b') * ~x)) / (~(c') + ~(d') * ~x)) / ((~(g') + ~(h') * ~x) * (~(i') + ~(j') * ~x)), ~x) => (-(~d) / (~h * (~d * ~i - ~c * ~j))) * Subst(Antiderivative((~F) ^ ((~e + (~f * (~b * ~i - ~a * ~j)) / (~d * ~i - ~c * ~j)) - ((~b * ~c - ~a * ~d) * ~f * ~x) / (~d * ~i - ~c * ~j)) / ~x, ~x), ~x, (~i + ~j * ~x) / (~c + ~d * ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h], ~x) && EqQ(~d * ~g - ~c * ~h, 0)
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => (~F) ^ (~a - (~b) ^ 2 / (4 * ~c)) * Antiderivative((~F) ^ ((~b + 2 * ~c * ~x) ^ 2 / (4 * ~c)), ~x) <-- FreeQ([~F, ~a, ~b, ~c], ~x)
    @apply_utils Antiderivative((~F) ^ ~v, ~x) => Antiderivative((~F) ^ ExpandToSum(~v, ~x), ~x) <-- FreeQ(~F, ~x) && (QuadraticQ(~v, ~x) && Not(QuadraticMatchQ(~v, ~x)))
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => (~e * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (2 * ~c * log(~F)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && EqQ(~b * ~e - 2 * ~c * ~d, 0)
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => (~e * (~d + ~e * ~x) ^ (~m - 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (2 * ~c * log(~F)) - (((~m - 1) * (~e) ^ 2) / (2 * ~c * log(~F))) * Antiderivative((~d + ~e * ~x) ^ (~m - 2) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && (EqQ(~b * ~e - 2 * ~c * ~d, 0) && GtQ(~m, 1))
    @apply_utils Antiderivative((~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2) / (~(d') + ~(e') * ~x), ~x) => (1 / (2 * ~e)) * (~F) ^ (~a - (~b) ^ 2 / (4 * ~c)) * ExpIntegralEi(((~b + 2 * ~c * ~x) ^ 2 * log(~F)) / (4 * ~c)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && EqQ(~b * ~e - 2 * ~c * ~d, 0)
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => ((~d + ~e * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (~e * (~m + 1)) - ((2 * ~c * log(~F)) / ((~e) ^ 2 * (~m + 1))) * Antiderivative((~d + ~e * ~x) ^ (~m + 2) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && (EqQ(~b * ~e - 2 * ~c * ~d, 0) && LtQ(~m, -1))
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => (~e * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (2 * ~c * log(~F)) - ((~b * ~e - 2 * ~c * ~d) / (2 * ~c)) * Antiderivative((~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && NeQ(~b * ~e - 2 * ~c * ~d, 0)
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => ((~e * (~d + ~e * ~x) ^ (~m - 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (2 * ~c * log(~F)) - ((~b * ~e - 2 * ~c * ~d) / (2 * ~c)) * Antiderivative((~d + ~e * ~x) ^ (~m - 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x)) - (((~m - 1) * (~e) ^ 2) / (2 * ~c * log(~F))) * Antiderivative((~d + ~e * ~x) ^ (~m - 2) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && (NeQ(~b * ~e - 2 * ~c * ~d, 0) && GtQ(~m, 1))
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) ^ ~m * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => (((~d + ~e * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2)) / (~e * (~m + 1)) - (((~b * ~e - 2 * ~c * ~d) * log(~F)) / ((~e) ^ 2 * (~m + 1))) * Antiderivative((~d + ~e * ~x) ^ (~m + 1) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x)) - ((2 * ~c * log(~F)) / ((~e) ^ 2 * (~m + 1))) * Antiderivative((~d + ~e * ~x) ^ (~m + 2) * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && (NeQ(~b * ~e - 2 * ~c * ~d, 0) && LtQ(~m, -1))
    @apply_utils Antiderivative((~(d') + ~(e') * ~x) ^ ~(m') * (~F) ^ (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => Unintegrable((~d + ~e * ~x) ^ ~m * (~F) ^ (~a + ~b * ~x + ~c * (~x) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~m], ~x)
    @apply_utils Antiderivative((~u) ^ ~(m') * (~F) ^ ~v, ~x) => Antiderivative(ExpandToSum(~u, ~x) ^ ~m * (~F) ^ ExpandToSum(~v, ~x), ~x) <-- FreeQ([~F, ~m], ~x) && (LinearQ(~u, ~x) && (QuadraticQ(~v, ~x) && Not(LinearMatchQ(~u, ~x) && QuadraticMatchQ(~v, ~x))))
    @apply_utils Antiderivative((~x) ^ ~(m') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x)) * (~(a') + ~(b') * (~F) ^ ~v) ^ ~p, ~x) => With([u = IntHide((~F) ^ (~e * (~c + ~d * ~x)) * (~a + ~b * (~F) ^ ~v) ^ ~p, ~x)], Dist((~x) ^ ~m, u, ~x) - ~m * Antiderivative((~x) ^ (~m - 1) * u, ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e], ~x) && (EqQ(~v, 2 * ~e * (~c + ~d * ~x)) && (GtQ(~m, 0) && ILtQ(~p, 0)))
    @apply_utils Antiderivative(((~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(n') * (~a + ~(b') * ((~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(n')) ^ ~(p'), ~x) => (1 / (~d * ~e * ~n * log(~F))) * Subst(Antiderivative((~a + ~b * ~x) ^ ~p, ~x), ~x, ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~n, ~p], ~x)
    @apply_utils Antiderivative(((~G) ^ (~(h') * (~(f') + ~(g') * ~x))) ^ ~(m') * (~a + ~(b') * ((~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(n')) ^ ~(p'), ~x) => (((~G) ^ (~h * (~f + ~g * ~x))) ^ ~m / ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) * Antiderivative(((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n * (~a + ~b * ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) ^ ~p, ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n, ~p], ~x) && EqQ(~d * ~e * ~n * log(~F), ~g * ~h * ~m * log(~G))
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => With([m = FullSimplify((~g * ~h * log(~G)) / (~d * ~e * log(~F)))], ((Denominator(m) * (~G) ^ (~f * ~h - (~c * ~g * ~h) / ~d)) / (~d * ~e * log(~F))) * Subst(Antiderivative((~x) ^ (Numerator(m) - 1) * (~a + ~b * (~x) ^ Denominator(m)) ^ ~p, ~x), ~x, (~F) ^ ((~e * (~c + ~d * ~x)) / Denominator(m))) <-- LeQ(m, -1) || GeQ(m, 1)) <-- FreeQ([~F, ~G, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~p], ~x)
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => With([m = FullSimplify((~d * ~e * log(~F)) / (~g * ~h * log(~G)))], (Denominator(m) / (~g * ~h * log(~G))) * Subst(Antiderivative((~x) ^ (Denominator(m) - 1) * (~a + ~b * (~F) ^ (~c * ~e - (~d * ~e * ~f) / ~g) * (~x) ^ Numerator(m)) ^ ~p, ~x), ~x, (~G) ^ ((~h * (~f + ~g * ~x)) / Denominator(m))) <-- LtQ(m, -1) || GtQ(m, 1)) <-- FreeQ([~F, ~G, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~p], ~x)
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => Antiderivative(expand((~G) ^ (~h * (~f + ~g * ~x)) * (~a + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p, ~x), ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h], ~x) && IGtQ(~p, 0)
    # Missing due to parse error: Antiderivative((~G)^((~h')*((~f') + (~g')*(~x)))*((~a) + (~b')*(~F)^((~e')*((~c') + (~d')*(~x))))^(~p), ~x) := a^p*G^(h*(f + g*x))/(g*h*log(G))* HypergeometricFunctions._₂F₁(-p, g*h*log(G)/(d*e*log(F)), g*h*log(G)/(d*e*log(F)) + 1, Simplify(-b/a*F^(e*(c + d*x)))) <-- FreeQ([F, G, a, b, c, d, e, f, g, h, p], x) && (ILtQ(p, 0) || GtQ(a, 0))
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~p, ~x) => ((~a + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p / (1 + (~b / ~a) * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p) * Antiderivative((~G) ^ (~h * (~f + ~g * ~x)) * (1 + (~b / ~a) * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p, ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~p], ~x) && Not(ILtQ(~p, 0) || GtQ(~a, 0))
    @apply_utils Antiderivative((~G) ^ (~(h') * ~u) * (~a + ~(b') * (~F) ^ (~(e') * ~v)) ^ ~p, ~x) => Antiderivative((~G) ^ (~h * ExpandToSum(~u, ~x)) * (~a + ~b * (~F) ^ (~e * ExpandToSum(~v, ~x))) ^ ~p, ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~e, ~h, ~p], ~x) && (LinearQ([~u, ~v], ~x) && Not(LinearMatchQ([~u, ~v], ~x)))
    #= Antiderivative(((~c')+(~d')*(~x))^(~m')*(~F)^((~g')*((~e')+(~f')*(~x)))/((~a)+(~b')*(~F)^((~h')*((~e')+(~f') *(~x)))),~x) := 1/b*Antiderivative((c+d*x)^m*F^((g-h)*(e+f*x)),x) - a/b*Antiderivative((c+d*x)^m*F^((g-h)*(e+f*x))/(a+b*F^(h*(e+f*x))),x) <--  FreeQ([F,a,b,c,d,e,f,g,h,m],x) && LeQ(0,g/h-1,g/h) =#
    #= Antiderivative(((~c')+(~d')*(~x))^(~m')*(~F)^((~g')*((~e')+(~f')*(~x)))/((~a)+(~b')*(~F)^((~h')*((~e')+(~f') *(~x)))),~x) := 1/a*Antiderivative((c+d*x)^m*F^(g*(e+f*x)),x) - b/a*Antiderivative((c+d*x)^m*F^((g+h)*(e+f*x))/(a+b*F^(h*(e+f*x))),x) <--  FreeQ([F,a,b,c,d,e,f,g,h,m],x) && LeQ(g/h,g/h+1,0) =#
    @apply_utils Antiderivative((~(e') + ~(f') * ~x) ^ ~(m') * (~(a') + ~(b') * (~F) ^ ~u) ^ ~(p') * (~(c') + ~(d') * (~F) ^ ~v) ^ ~(q'), ~x) => With([w = ExpandIntegrand((~e + ~f * ~x) ^ ~m, (~a + ~b * (~F) ^ ~u) ^ ~p * (~c + ~d * (~F) ^ ~v) ^ ~q, ~x)], Antiderivative(w, ~x) <-- SumQ(w)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~m], ~x) && (IntegersQ(~p, ~q) && (LinearQ([~u, ~v], ~x) && RationalQ(Simplify(~u / ~v))))
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~H) ^ (~(t') * (~(r') + ~(s') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => With([m = FullSimplify((~g * ~h * log(~G) + ~s * ~t * log(~H)) / (~d * ~e * log(~F)))], ((Denominator(m) * (~G) ^ (~f * ~h - (~c * ~g * ~h) / ~d) * (~H) ^ (~r * ~t - (~c * ~s * ~t) / ~d)) / (~d * ~e * log(~F))) * Subst(Antiderivative((~x) ^ (Numerator(m) - 1) * (~a + ~b * (~x) ^ Denominator(m)) ^ ~p, ~x), ~x, (~F) ^ ((~e * (~c + ~d * ~x)) / Denominator(m))) <-- RationalQ(m)) <-- FreeQ([~F, ~G, ~H, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~r, ~s, ~t, ~p], ~x)
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~H) ^ (~(t') * (~(r') + ~(s') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => (~G) ^ ((~f - (~c * ~g) / ~d) * ~h) * Antiderivative((~H) ^ (~t * (~r + ~s * ~x)) * (~b + ~a * (~F) ^ (-(~e) * (~c + ~d * ~x))) ^ ~p, ~x) <-- FreeQ([~F, ~G, ~H, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~r, ~s, ~t], ~x) && (EqQ(~d * ~e * ~p * log(~F) + ~g * ~h * log(~G), 0) && IntegerQ(~p))
    @apply_utils Antiderivative((~G) ^ (~(h') * (~(f') + ~(g') * ~x)) * (~H) ^ (~(t') * (~(r') + ~(s') * ~x)) * (~a + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => Antiderivative(expand((~G) ^ (~h * (~f + ~g * ~x)) * (~H) ^ (~t * (~r + ~s * ~x)) * (~a + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p, ~x), ~x) <-- FreeQ([~F, ~G, ~H, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~r, ~s, ~t], ~x) && IGtQ(~p, 0)
    # Missing due to parse error: Antiderivative((~G)^((~h')*((~f') + (~g')*(~x)))* (~H)^((~t')*((~r') + (~s')*(~x)))*((~a) + (~b')*(~F)^((~e')*((~c') + (~d')*(~x))))^(~p), ~x) := a^p*G^(h*(f + g*x))*H^(t*(r + s*x))/(g*h*log(G) + s*t*log(H))* HypergeometricFunctions._₂F₁(-p, (g*h*log(G) + s*t*log(H))/(d*e* log(F)), (g*h*log(G) + s*t*log(H))/(d*e*log(F)) + 1, Simplify(-b/a*F^(e*(c + d*x)))) <-- FreeQ([F, G, H, a, b, c, d, e, f, g, h, r, s, t], x) && ILtQ(p, 0)
    # Missing due to parse error: Antiderivative((~G)^((~h')*((~f') + (~g')*(~x)))* (~H)^((~t')*((~r') + (~s')*(~x)))*((~a) + (~b')*(~F)^((~e')*((~c') + (~d')*(~x))))^(~p), ~x) := G^(h*(f + g*x))* H^(t*(r + s*x))*(a + b*F^(e*(c + d*x)))^ p/((g*h*log(G) + s*t*log(H))*((a + b*F^(e*(c + d*x)))/a)^p)* HypergeometricFunctions._₂F₁(-p, (g*h*log(G) + s*t*log(H))/(d*e* log(F)), (g*h*log(G) + s*t*log(H))/(d*e*log(F)) + 1, Simplify(-b/a*F^(e*(c + d*x)))) <-- FreeQ([F, G, H, a, b, c, d, e, f, g, h, r, s, t, p], x) && Not(IntegerQ(p))
    @apply_utils Antiderivative((~G) ^ (~(h') * ~u) * (~H) ^ (~(t') * ~w) * (~a + ~(b') * (~F) ^ (~(e') * ~v)) ^ ~p, ~x) => Antiderivative((~G) ^ (~h * ExpandToSum(~u, ~x)) * (~H) ^ (~t * ExpandToSum(~w, ~x)) * (~a + ~b * (~F) ^ (~e * ExpandToSum(~v, ~x))) ^ ~p, ~x) <-- FreeQ([~F, ~G, ~H, ~a, ~b, ~e, ~h, ~t, ~p], ~x) && (LinearQ([~u, ~v, ~w], ~x) && Not(LinearMatchQ([~u, ~v, ~w], ~x)))
    @apply_utils Antiderivative((~F) ^ (~(e') * (~(c') + ~(d') * ~x)) * (~(a') * (~x) ^ ~(n') + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => (~a * (~x) ^ ~n + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ (~p + 1) / (~b * ~d * ~e * (~p + 1) * log(~F)) - ((~a * ~n) / (~b * ~d * ~e * log(~F))) * Antiderivative((~x) ^ (~n - 1) * (~a * (~x) ^ ~n + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p, ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~n, ~p], ~x) && NeQ(~p, -1)
    @apply_utils Antiderivative((~x) ^ ~(m') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x)) * (~(a') * (~x) ^ ~(n') + ~(b') * (~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(p'), ~x) => (((~x) ^ ~m * (~a * (~x) ^ ~n + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ (~p + 1)) / (~b * ~d * ~e * (~p + 1) * log(~F)) - ((~a * ~n) / (~b * ~d * ~e * log(~F))) * Antiderivative((~x) ^ ((~m + ~n) - 1) * (~a * (~x) ^ ~n + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ ~p, ~x)) - (~m / (~b * ~d * ~e * (~p + 1) * log(~F))) * Antiderivative((~x) ^ (~m - 1) * (~a * (~x) ^ ~n + ~b * (~F) ^ (~e * (~c + ~d * ~x))) ^ (~p + 1), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~m, ~n, ~p], ~x) && NeQ(~p, -1)
    @apply_utils Antiderivative((~(f') + ~(g') * ~x) ^ ~(m') / (~(a') + ~(b') * (~F) ^ ~u + ~(c') * (~F) ^ ~v), ~x) => With([q = Rt((~b) ^ 2 - 4 * ~a * ~c, 2)], ((2 * ~c) / q) * Antiderivative((~f + ~g * ~x) ^ ~m / ((~b - q) + 2 * ~c * (~F) ^ ~u), ~x) - ((2 * ~c) / q) * Antiderivative((~f + ~g * ~x) ^ ~m / (~b + q + 2 * ~c * (~F) ^ ~u), ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~f, ~g], ~x) && (EqQ(~v, 2 * ~u) && (LinearQ(~u, ~x) && (NeQ((~b) ^ 2 - 4 * ~a * ~c, 0) && IGtQ(~m, 0))))
    @apply_utils Antiderivative(((~(f') + ~(g') * ~x) ^ ~(m') * (~F) ^ ~u) / (~(a') + ~(b') * (~F) ^ ~u + ~(c') * (~F) ^ ~v), ~x) => With([q = Rt((~b) ^ 2 - 4 * ~a * ~c, 2)], ((2 * ~c) / q) * Antiderivative(((~f + ~g * ~x) ^ ~m * (~F) ^ ~u) / ((~b - q) + 2 * ~c * (~F) ^ ~u), ~x) - ((2 * ~c) / q) * Antiderivative(((~f + ~g * ~x) ^ ~m * (~F) ^ ~u) / (~b + q + 2 * ~c * (~F) ^ ~u), ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~f, ~g], ~x) && (EqQ(~v, 2 * ~u) && (LinearQ(~u, ~x) && (NeQ((~b) ^ 2 - 4 * ~a * ~c, 0) && IGtQ(~m, 0))))
    @apply_utils Antiderivative(((~(f') + ~(g') * ~x) ^ ~(m') * (~h + ~(i') * (~F) ^ ~u)) / (~(a') + ~(b') * (~F) ^ ~u + ~(c') * (~F) ^ ~v), ~x) => With([q = Rt((~b) ^ 2 - 4 * ~a * ~c, 2)], (Simplify((2 * ~c * ~h - ~b * ~i) / q) + ~i) * Antiderivative((~f + ~g * ~x) ^ ~m / ((~b - q) + 2 * ~c * (~F) ^ ~u), ~x) - (Simplify((2 * ~c * ~h - ~b * ~i) / q) - ~i) * Antiderivative((~f + ~g * ~x) ^ ~m / (~b + q + 2 * ~c * (~F) ^ ~u), ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~f, ~g, ~h, ~i], ~x) && (EqQ(~v, 2 * ~u) && (LinearQ(~u, ~x) && (NeQ((~b) ^ 2 - 4 * ~a * ~c, 0) && IGtQ(~m, 0))))
    @apply_utils Antiderivative((~x) ^ ~(m') / (~(a') * (~F) ^ (~(c') + ~(d') * ~x) + ~(b') * (~F) ^ ~v), ~x) => With([u = IntHide(1 / (~a * (~F) ^ (~c + ~d * ~x) + ~b * (~F) ^ ~v), ~x)], (~x) ^ ~m * u - ~m * Antiderivative((~x) ^ (~m - 1) * u, ~x)) <-- FreeQ([~F, ~a, ~b, ~c, ~d], ~x) && (EqQ(~v, -((~c + ~d * ~x))) && GtQ(~m, 0))
    @apply_utils Antiderivative(~u / (~a + ~(b') * (~F) ^ ~v + ~(c') * (~F) ^ ~w), ~x) => Antiderivative((~u * (~F) ^ ~v) / (~c + ~a * (~F) ^ ~v + ~b * (~F) ^ (2 * ~v)), ~x) <-- FreeQ([~F, ~a, ~b, ~c], ~x) && (EqQ(~w, -(~v)) && (LinearQ(~v, ~x) && If(RationalQ(Coefficient(~v, ~x, 1)), GtQ(Coefficient(~v, ~x, 1), 0), LtQ(LeafCount(~v), LeafCount(~w)))))
    @apply_utils Antiderivative((~F) ^ (~(g') * (~(d') + ~(e') * ~x) ^ ~(n')) / (~(a') + ~(b') * ~x + ~(c') * (~x) ^ 2), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~g * (~d + ~e * ~x) ^ ~n), 1 / (~a + ~b * ~x + ~c * (~x) ^ 2), ~x), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~g, ~n], ~x)
    @apply_utils Antiderivative((~F) ^ (~(g') * (~(d') + ~(e') * ~x) ^ ~(n')) / (~a + ~(c') * (~x) ^ 2), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~g * (~d + ~e * ~x) ^ ~n), 1 / (~a + ~c * (~x) ^ 2), ~x), ~x) <-- FreeQ([~F, ~a, ~c, ~d, ~e, ~g, ~n], ~x)
    @apply_utils Antiderivative(((~u) ^ ~(m') * (~F) ^ (~(g') * (~(d') + ~(e') * ~x) ^ ~(n'))) / (~(a') + ~(b') * ~x + ~c * (~x) ^ 2), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~g * (~d + ~e * ~x) ^ ~n), (~u) ^ ~m / (~a + ~b * ~x + ~c * (~x) ^ 2), ~x), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~g, ~n], ~x) && (PolynomialQ(~u, ~x) && IntegerQ(~m))
    @apply_utils Antiderivative(((~u) ^ ~(m') * (~F) ^ (~(g') * (~(d') + ~(e') * ~x) ^ ~(n'))) / (~a + ~c * (~x) ^ 2), ~x) => Antiderivative(ExpandIntegrand((~F) ^ (~g * (~d + ~e * ~x) ^ ~n), (~u) ^ ~m / (~a + ~c * (~x) ^ 2), ~x), ~x) <-- FreeQ([~F, ~a, ~c, ~d, ~e, ~g, ~n], ~x) && (PolynomialQ(~u, ~x) && IntegerQ(~m))
    @apply_utils Antiderivative((~F) ^ ((~(a') + ~(b') * (~x) ^ 4) / (~x) ^ 2), ~x) => (sqrt(pi) * exp(2 * sqrt(-(~a) * log(~F)) * sqrt(-(~b) * log(~F))) * erf((sqrt(-(~a) * log(~F)) + sqrt(-(~b) * log(~F)) * (~x) ^ 2) / ~x)) / (4 * sqrt(-(~b) * log(~F))) - (sqrt(pi) * exp(-2 * sqrt(-(~a) * log(~F)) * sqrt(-(~b) * log(~F))) * erf((sqrt(-(~a) * log(~F)) - sqrt(-(~b) * log(~F)) * (~x) ^ 2) / ~x)) / (4 * sqrt(-(~b) * log(~F))) <-- FreeQ([~F, ~a, ~b], ~x)
    @apply_utils Antiderivative((~x) ^ ~(m') * (ℯ ^ ~x + (~x) ^ ~(m')) ^ ~n, ~x) => -((ℯ ^ ~x + (~x) ^ ~m) ^ (~n + 1)) / (~n + 1) + Antiderivative((ℯ ^ ~x + (~x) ^ ~m) ^ (~n + 1), ~x) + ~m * Antiderivative((~x) ^ (~m - 1) * (ℯ ^ ~x + (~x) ^ ~m) ^ ~n, ~x) <-- RationalQ(~m, ~n) && (GtQ(~m, 0) && (LtQ(~n, 0) && NeQ(~n, -1)))
    @apply_utils Antiderivative(~(u') * (~F) ^ (~(a') * (~(v') + ~(b') * log(~z))), ~x) => Antiderivative(~u * (~F) ^ (~a * ~v) * (~z) ^ (~a * ~b * log(~F)), ~x) <-- FreeQ([~F, ~a, ~b], ~x)
    @apply_utils Antiderivative((~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n')) ^ 2)), ~x) => ((~d + ~e * ~x) / (~e * ~n * (~c * (~d + ~e * ~x) ^ ~n) ^ (1 / ~n))) * Subst(Antiderivative(ℯ ^ (~a * ~f * log(~F) + ~x / ~n + ~b * ~f * log(~F) * (~x) ^ 2), ~x), ~x, log(~c * (~d + ~e * ~x) ^ ~n)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n')) ^ 2)), ~x) => ((~g + ~h * ~x) ^ (~m + 1) / (~h * ~n * (~c * (~d + ~e * ~x) ^ ~n) ^ ((~m + 1) / ~n))) * Subst(Antiderivative(ℯ ^ (~a * ~f * log(~F) + ((~m + 1) * ~x) / ~n + ~b * ~f * log(~F) * (~x) ^ 2), ~x), ~x, log(~c * (~d + ~e * ~x) ^ ~n)) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x) && EqQ(~e * ~g - ~d * ~h, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n')) ^ 2)), ~x) => (1 / (~e) ^ (~m + 1)) * Subst(Antiderivative(ExpandIntegrand((~F) ^ (~f * (~a + ~b * log(~c * (~x) ^ ~n) ^ 2)), ((~e * ~g - ~d * ~h) + ~h * ~x) ^ ~m, ~x), ~x), ~x, ~d + ~e * ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~n], ~x) && IGtQ(~m, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n')) ^ 2)), ~x) => Unintegrable((~g + ~h * ~x) ^ ~m * (~F) ^ (~f * (~a + ~b * log(~c * (~d + ~e * ~x) ^ ~n) ^ 2)), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x)
    @apply_utils Antiderivative((~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => (~c) ^ (2 * ~a * ~b * ~f * log(~F)) * Antiderivative((~d + ~e * ~x) ^ (2 * ~a * ~b * ~f * ~n * log(~F)) * (~F) ^ ((~a) ^ 2 * ~f + (~b) ^ 2 * ~f * log(~c * (~d + ~e * ~x) ^ ~n) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x) && IntegerQ(2 * ~a * ~b * ~f * log(~F))
    @apply_utils Antiderivative((~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => ((~c * (~d + ~e * ~x) ^ ~n) ^ (2 * ~a * ~b * ~f * log(~F)) / (~d + ~e * ~x) ^ (2 * ~a * ~b * ~f * ~n * log(~F))) * Antiderivative((~d + ~e * ~x) ^ (2 * ~a * ~b * ~f * ~n * log(~F)) * (~F) ^ ((~a) ^ 2 * ~f + (~b) ^ 2 * ~f * log(~c * (~d + ~e * ~x) ^ ~n) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~n], ~x) && Not(IntegerQ(2 * ~a * ~b * ~f * log(~F)))
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => (((~h) ^ ~m * (~c) ^ (2 * ~a * ~b * ~f * log(~F))) / (~e) ^ ~m) * Antiderivative((~d + ~e * ~x) ^ (~m + 2 * ~a * ~b * ~f * ~n * log(~F)) * (~F) ^ ((~a) ^ 2 * ~f + (~b) ^ 2 * ~f * log(~c * (~d + ~e * ~x) ^ ~n) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x) && (EqQ(~e * ~g - ~d * ~h, 0) && (IntegerQ(2 * ~a * ~b * ~f * log(~F)) && (IntegerQ(~m) || EqQ(~h, ~e))))
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => (((~g + ~h * ~x) ^ ~m * (~c * (~d + ~e * ~x) ^ ~n) ^ (2 * ~a * ~b * ~f * log(~F))) / (~d + ~e * ~x) ^ (~m + 2 * ~a * ~b * ~f * ~n * log(~F))) * Antiderivative((~d + ~e * ~x) ^ (~m + 2 * ~a * ~b * ~f * ~n * log(~F)) * (~F) ^ ((~a) ^ 2 * ~f + (~b) ^ 2 * ~f * log(~c * (~d + ~e * ~x) ^ ~n) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x) && EqQ(~e * ~g - ~d * ~h, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => (1 / (~e) ^ (~m + 1)) * Subst(Antiderivative(ExpandIntegrand((~F) ^ (~f * (~a + ~b * log(~c * (~x) ^ ~n)) ^ 2), ((~e * ~g - ~d * ~h) + ~h * ~x) ^ ~m, ~x), ~x), ~x, ~d + ~e * ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~n], ~x) && IGtQ(~m, 0)
    @apply_utils Antiderivative((~(g') + ~(h') * ~x) ^ ~(m') * (~F) ^ (~(f') * (~(a') + ~(b') * log(~(c') * (~(d') + ~(e') * ~x) ^ ~(n'))) ^ 2), ~x) => Unintegrable((~g + ~h * ~x) ^ ~m * (~F) ^ (~f * (~a + ~b * log(~c * (~d + ~e * ~x) ^ ~n)) ^ 2), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~f, ~g, ~h, ~m, ~n], ~x)
    @apply_utils Antiderivative(log(~a + ~(b') * ((~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(n')), ~x) => (1 / (~d * ~e * ~n * log(~F))) * Subst(Antiderivative(log(~a + ~b * ~x) / ~x, ~x), ~x, ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~n], ~x) && GtQ(~a, 0)
    @apply_utils Antiderivative(log(~a + ~(b') * ((~F) ^ (~(e') * (~(c') + ~(d') * ~x))) ^ ~(n')), ~x) => ~x * log(~a + ~b * ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) - ~b * ~d * ~e * ~n * log(~F) * Antiderivative((~x * ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n) / (~a + ~b * ((~F) ^ (~e * (~c + ~d * ~x))) ^ ~n), ~x) <-- FreeQ([~F, ~a, ~b, ~c, ~d, ~e, ~n], ~x) && Not(GtQ(~a, 0))
    #= Antiderivative((~u')*((~a')*(~F)^(~v))^(~n),~x) := a^n*Antiderivative(u*F^(n*v),x) <--  FreeQ([F,a],x) && IntegerQ(n) =#
    @apply_utils Antiderivative(~(u') * (~(a') * (~F) ^ ~v) ^ ~n, ~x) => ((~a * (~F) ^ ~v) ^ ~n / (~F) ^ (~n * ~v)) * Antiderivative(~u * (~F) ^ (~n * ~v), ~x) <-- FreeQ([~F, ~a, ~n], ~x) && Not(IntegerQ(~n))
    @apply_utils Antiderivative(~u, ~x) => With([v = FunctionOfExponential(~u, ~x)], (v / D(v, ~x)) * Subst(Antiderivative(FunctionOfExponentialFunction(~u, ~x) / ~x, ~x), ~x, v)) <-- FunctionOfExponentialQ(~u, ~x) && (Not(MatchQ(~u, ~w * (~(a') * (~v) ^ ~n) ^ ~m <-- FreeQ([a, m, n], ~x) && IntegerQ(m * n))) && Not(MatchQ(~u, ℯ ^ (~(c') * (~(a') + ~(b') * ~x)) * (~F)(~v) <-- FreeQ([a, b, c], ~x) && InverseFunctionQ(F(~x)))))
    @apply_utils Antiderivative(~(u') * (~(a') * (~F) ^ ~v + ~(b') * (~F) ^ ~w) ^ ~n, ~x) => Antiderivative(~u * (~F) ^ (~n * ~v) * (~a + ~b * (~F) ^ ExpandToSum(~w - ~v, ~x)) ^ ~n, ~x) <-- FreeQ([~F, ~a, ~b, ~n], ~x) && (ILtQ(~n, 0) && LinearQ([~v, ~w], ~x))
    @apply_utils Antiderivative(~(u') * (~(a') * (~F) ^ ~v + ~(b') * (~G) ^ ~w) ^ ~n, ~x) => Antiderivative(~u * (~F) ^ (~n * ~v) * (~a + ~b * ℯ ^ ExpandToSum(log(~G) * ~w - log(~F) * ~v, ~x)) ^ ~n, ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~n], ~x) && (ILtQ(~n, 0) && LinearQ([~v, ~w], ~x))
    @apply_utils Antiderivative(~(u') * (~(a') * (~F) ^ ~v + ~(b') * (~F) ^ ~w) ^ ~n, ~x) => ((~a * (~F) ^ ~v + ~b * (~F) ^ ~w) ^ ~n / ((~F) ^ (~n * ~v) * (~a + ~b * (~F) ^ ExpandToSum(~w - ~v, ~x)) ^ ~n)) * Antiderivative(~u * (~F) ^ (~n * ~v) * (~a + ~b * (~F) ^ ExpandToSum(~w - ~v, ~x)) ^ ~n, ~x) <-- FreeQ([~F, ~a, ~b, ~n], ~x) && (Not(IntegerQ(~n)) && LinearQ([~v, ~w], ~x))
    @apply_utils Antiderivative(~(u') * (~(a') * (~F) ^ ~v + ~(b') * (~G) ^ ~w) ^ ~n, ~x) => ((~a * (~F) ^ ~v + ~b * (~G) ^ ~w) ^ ~n / ((~F) ^ (~n * ~v) * (~a + ~b * ℯ ^ ExpandToSum(log(~G) * ~w - log(~F) * ~v, ~x)) ^ ~n)) * Antiderivative(~u * (~F) ^ (~n * ~v) * (~a + ~b * ℯ ^ ExpandToSum(log(~G) * ~w - log(~F) * ~v, ~x)) ^ ~n, ~x) <-- FreeQ([~F, ~G, ~a, ~b, ~n], ~x) && (Not(IntegerQ(~n)) && LinearQ([~v, ~w], ~x))
    @apply_utils Antiderivative(~(u') * (~F) ^ ~v * (~G) ^ ~w, ~x) => With([z = ~v * log(~F) + ~w * log(~G)], Antiderivative(~u * NormalizeIntegrand(ℯ ^ z, ~x), ~x) <-- BinomialQ(z, ~x) || PolynomialQ(z, ~x) && LeQ(Exponent(z, ~x), 2)) <-- FreeQ([~F, ~G], ~x)
    @apply_utils Antiderivative((~F) ^ ~u * (~v + ~w) * ~(y'), ~x) => With([z = (~v * ~y) / (log(~F) * D(~u, ~x))], (~F) ^ ~u * z <-- EqQ(D(z, ~x), ~w * ~y)) <-- FreeQ(~F, ~x)
    @apply_utils Antiderivative((~F) ^ ~u * (~v) ^ ~(n') * ~w, ~x) => With([z = log(~F) * ~v * D(~u, ~x) + (~n + 1) * D(~v, ~x)], (Coefficient(~w, ~x, Exponent(~w, ~x)) / Coefficient(z, ~x, Exponent(z, ~x))) * (~F) ^ ~u * (~v) ^ (~n + 1) <-- EqQ(Exponent(~w, ~x), Exponent(z, ~x)) && EqQ(~w * Coefficient(z, ~x, Exponent(z, ~x)), z * Coefficient(~w, ~x, Exponent(~w, ~x)))) <-- FreeQ([~F, ~n], ~x) && (PolynomialQ(~u, ~x) && (PolynomialQ(~v, ~x) && PolynomialQ(~w, ~x)))
    @apply_utils Antiderivative((~(a') + ~(b') * (~F) ^ ((~(c') * sqrt(~(d') + ~(e') * ~x)) / sqrt(~(f') + ~(g') * ~x))) ^ ~(n') / (~(A') + ~(B') * ~x + ~(C') * (~x) ^ 2), ~x) => ((2 * ~e * ~g) / (~C * (~e * ~f - ~d * ~g))) * Subst(Antiderivative((~a + ~b * (~F) ^ (~c * ~x)) ^ ~n / ~x, ~x), ~x, sqrt(~d + ~e * ~x) / sqrt(~f + ~g * ~x)) <-- FreeQ([~a, ~b, ~c, ~d, ~e, ~f, ~g, ~A, ~B, ~C, ~F], ~x) && (EqQ(~C * ~d * ~f - ~A * ~e * ~g, 0) && (EqQ(~B * ~e * ~g - ~C * (~e * ~f + ~d * ~g), 0) && IGtQ(~n, 0)))
    @apply_utils Antiderivative((~(a') + ~(b') * (~F) ^ ((~(c') * sqrt(~(d') + ~(e') * ~x)) / sqrt(~(f') + ~(g') * ~x))) ^ ~(n') / (~A + ~(C') * (~x) ^ 2), ~x) => ((2 * ~e * ~g) / (~C * (~e * ~f - ~d * ~g))) * Subst(Antiderivative((~a + ~b * (~F) ^ (~c * ~x)) ^ ~n / ~x, ~x), ~x, sqrt(~d + ~e * ~x) / sqrt(~f + ~g * ~x)) <-- FreeQ([~a, ~b, ~c, ~d, ~e, ~f, ~g, ~A, ~C, ~F], ~x) && (EqQ(~C * ~d * ~f - ~A * ~e * ~g, 0) && (EqQ(~e * ~f + ~d * ~g, 0) && IGtQ(~n, 0)))
    @apply_utils Antiderivative((~(a') + ~(b') * (~F) ^ ((~(c') * sqrt(~(d') + ~(e') * ~x)) / sqrt(~(f') + ~(g') * ~x))) ^ ~n / (~(A') + ~(B') * ~x + ~(C') * (~x) ^ 2), ~x) => Unintegrable((~a + ~b * (~F) ^ ((~c * sqrt(~d + ~e * ~x)) / sqrt(~f + ~g * ~x))) ^ ~n / (~A + ~B * ~x + ~C * (~x) ^ 2), ~x) <-- FreeQ([~a, ~b, ~c, ~d, ~e, ~f, ~g, ~A, ~B, ~C, ~F, ~n], ~x) && (EqQ(~C * ~d * ~f - ~A * ~e * ~g, 0) && (EqQ(~B * ~e * ~g - ~C * (~e * ~f + ~d * ~g), 0) && Not(IGtQ(~n, 0))))
    @apply_utils Antiderivative((~(a') + ~(b') * (~F) ^ ((~(c') * sqrt(~(d') + ~(e') * ~x)) / sqrt(~(f') + ~(g') * ~x))) ^ ~n / (~A + ~(C') * (~x) ^ 2), ~x) => Unintegrable((~a + ~b * (~F) ^ ((~c * sqrt(~d + ~e * ~x)) / sqrt(~f + ~g * ~x))) ^ ~n / (~A + ~C * (~x) ^ 2), ~x) <-- FreeQ([~a, ~b, ~c, ~d, ~e, ~f, ~g, ~A, ~C, ~F, ~n], ~x) && (EqQ(~C * ~d * ~f - ~A * ~e * ~g, 0) && (EqQ(~e * ~f + ~d * ~g, 0) && Not(IGtQ(~n, 0))))
end

max_stars_repo_path: src/rules/2 Exponentials/2.3 Miscellaneous exponentials.jl