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

function SCIPepsilon(scip)
    ccall((:SCIPepsilon, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPsumepsilon(scip)
    ccall((:SCIPsumepsilon, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPfeastol(scip)
    ccall((:SCIPfeastol, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPlpfeastol(scip)
    ccall((:SCIPlpfeastol, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPdualfeastol(scip)
    ccall((:SCIPdualfeastol, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPbarrierconvtol(scip)
    ccall((:SCIPbarrierconvtol, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPcutoffbounddelta(scip)
    ccall((:SCIPcutoffbounddelta, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPrelaxfeastol(scip)
    ccall((:SCIPrelaxfeastol, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPchgFeastol(scip, feastol)
    ccall((:SCIPchgFeastol, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cdouble), scip, feastol)
end

function SCIPchgLpfeastol(scip, lpfeastol, printnewvalue)
    ccall((:SCIPchgLpfeastol, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cdouble, UInt32), scip, lpfeastol, printnewvalue)
end

function SCIPchgDualfeastol(scip, dualfeastol)
    ccall((:SCIPchgDualfeastol, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cdouble), scip, dualfeastol)
end

function SCIPchgBarrierconvtol(scip, barrierconvtol)
    ccall((:SCIPchgBarrierconvtol, libscip), SCIP_RETCODE, (Ptr{SCIP_}, Cdouble), scip, barrierconvtol)
end

function SCIPchgRelaxfeastol(scip, relaxfeastol)
    ccall((:SCIPchgRelaxfeastol, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, relaxfeastol)
end

function SCIPmarkLimitChanged(scip)
    ccall((:SCIPmarkLimitChanged, libscip), Cvoid, (Ptr{SCIP_},), scip)
end

function SCIPinfinity(scip)
    ccall((:SCIPinfinity, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPgetHugeValue(scip)
    ccall((:SCIPgetHugeValue, libscip), Cdouble, (Ptr{SCIP_},), scip)
end

function SCIPisEQ(scip, val1, val2)
    ccall((:SCIPisEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisLT(scip, val1, val2)
    ccall((:SCIPisLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisLE(scip, val1, val2)
    ccall((:SCIPisLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisGT(scip, val1, val2)
    ccall((:SCIPisGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisGE(scip, val1, val2)
    ccall((:SCIPisGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisInfinity(scip, val)
    ccall((:SCIPisInfinity, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisHugeValue(scip, val)
    ccall((:SCIPisHugeValue, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisZero(scip, val)
    ccall((:SCIPisZero, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisPositive(scip, val)
    ccall((:SCIPisPositive, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisNegative(scip, val)
    ccall((:SCIPisNegative, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisIntegral(scip, val)
    ccall((:SCIPisIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisScalingIntegral(scip, val, scalar)
    ccall((:SCIPisScalingIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val, scalar)
end

function SCIPisFracIntegral(scip, val)
    ccall((:SCIPisFracIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfloor(scip, val)
    ccall((:SCIPfloor, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPceil(scip, val)
    ccall((:SCIPceil, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPround(scip, val)
    ccall((:SCIPround, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfrac(scip, val)
    ccall((:SCIPfrac, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisSumEQ(scip, val1, val2)
    ccall((:SCIPisSumEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumLT(scip, val1, val2)
    ccall((:SCIPisSumLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumLE(scip, val1, val2)
    ccall((:SCIPisSumLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumGT(scip, val1, val2)
    ccall((:SCIPisSumGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumGE(scip, val1, val2)
    ccall((:SCIPisSumGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumZero(scip, val)
    ccall((:SCIPisSumZero, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisSumPositive(scip, val)
    ccall((:SCIPisSumPositive, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisSumNegative(scip, val)
    ccall((:SCIPisSumNegative, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisFeasEQ(scip, val1, val2)
    ccall((:SCIPisFeasEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisFeasLT(scip, val1, val2)
    ccall((:SCIPisFeasLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisFeasLE(scip, val1, val2)
    ccall((:SCIPisFeasLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisFeasGT(scip, val1, val2)
    ccall((:SCIPisFeasGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisFeasGE(scip, val1, val2)
    ccall((:SCIPisFeasGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisFeasZero(scip, val)
    ccall((:SCIPisFeasZero, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisFeasPositive(scip, val)
    ccall((:SCIPisFeasPositive, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisFeasNegative(scip, val)
    ccall((:SCIPisFeasNegative, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisFeasIntegral(scip, val)
    ccall((:SCIPisFeasIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisFeasFracIntegral(scip, val)
    ccall((:SCIPisFeasFracIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfeasFloor(scip, val)
    ccall((:SCIPfeasFloor, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfeasCeil(scip, val)
    ccall((:SCIPfeasCeil, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfeasRound(scip, val)
    ccall((:SCIPfeasRound, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPfeasFrac(scip, val)
    ccall((:SCIPfeasFrac, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisDualfeasEQ(scip, val1, val2)
    ccall((:SCIPisDualfeasEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisDualfeasLT(scip, val1, val2)
    ccall((:SCIPisDualfeasLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisDualfeasLE(scip, val1, val2)
    ccall((:SCIPisDualfeasLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisDualfeasGT(scip, val1, val2)
    ccall((:SCIPisDualfeasGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisDualfeasGE(scip, val1, val2)
    ccall((:SCIPisDualfeasGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisDualfeasZero(scip, val)
    ccall((:SCIPisDualfeasZero, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisDualfeasPositive(scip, val)
    ccall((:SCIPisDualfeasPositive, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisDualfeasNegative(scip, val)
    ccall((:SCIPisDualfeasNegative, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisDualfeasIntegral(scip, val)
    ccall((:SCIPisDualfeasIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisDualfeasFracIntegral(scip, val)
    ccall((:SCIPisDualfeasFracIntegral, libscip), UInt32, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPdualfeasFloor(scip, val)
    ccall((:SCIPdualfeasFloor, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPdualfeasCeil(scip, val)
    ccall((:SCIPdualfeasCeil, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPdualfeasRound(scip, val)
    ccall((:SCIPdualfeasRound, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPdualfeasFrac(scip, val)
    ccall((:SCIPdualfeasFrac, libscip), Cdouble, (Ptr{SCIP_}, Cdouble), scip, val)
end

function SCIPisLbBetter(scip, newlb, oldlb, oldub)
    ccall((:SCIPisLbBetter, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble, Cdouble), scip, newlb, oldlb, oldub)
end

function SCIPisUbBetter(scip, newub, oldlb, oldub)
    ccall((:SCIPisUbBetter, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble, Cdouble), scip, newub, oldlb, oldub)
end

function SCIPisRelEQ(scip, val1, val2)
    ccall((:SCIPisRelEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisRelLT(scip, val1, val2)
    ccall((:SCIPisRelLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisRelLE(scip, val1, val2)
    ccall((:SCIPisRelLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisRelGT(scip, val1, val2)
    ccall((:SCIPisRelGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisRelGE(scip, val1, val2)
    ccall((:SCIPisRelGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumRelEQ(scip, val1, val2)
    ccall((:SCIPisSumRelEQ, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumRelLT(scip, val1, val2)
    ccall((:SCIPisSumRelLT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumRelLE(scip, val1, val2)
    ccall((:SCIPisSumRelLE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumRelGT(scip, val1, val2)
    ccall((:SCIPisSumRelGT, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPisSumRelGE(scip, val1, val2)
    ccall((:SCIPisSumRelGE, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, val1, val2)
end

function SCIPconvertRealToInt(scip, real)
    ccall((:SCIPconvertRealToInt, libscip), Cint, (Ptr{SCIP_}, Cdouble), scip, real)
end

function SCIPconvertRealToLongint(scip, real)
    ccall((:SCIPconvertRealToLongint, libscip), Clonglong, (Ptr{SCIP_}, Cdouble), scip, real)
end

function SCIPisUpdateUnreliable(scip, newvalue, oldvalue)
    ccall((:SCIPisUpdateUnreliable, libscip), UInt32, (Ptr{SCIP_}, Cdouble, Cdouble), scip, newvalue, oldvalue)
end

function SCIPprintReal(scip, file, val, width, precision)
    ccall((:SCIPprintReal, libscip), Cvoid, (Ptr{SCIP_}, Ptr{FILE}, Cdouble, Cint, Cint), scip, file, val, width, precision)
end

function SCIPparseReal(scip, str, value, endptr)
    ccall((:SCIPparseReal, libscip), UInt32, (Ptr{SCIP_}, Cstring, Ptr{Cdouble}, Ptr{Cstring}), scip, str, value, endptr)
end


text:
__precompile__()

module LibGEOS

    # Load in `deps.jl`, complaining if it does not exist
    const depsjl_path = joinpath(@__DIR__, "..", "deps", "deps.jl")
    if !isfile(depsjl_path)
        error("LibGEOS not installed properly, run Pkg.build(\"LibGEOS\"), restart Julia and try again")
    end
    include(depsjl_path)

    using GeoInterface
    import Base: contains

    export  Point, MultiPoint, LineString, MultiLineString, LinearRing, Polygon, MultiPolygon, GeometryCollection,
            parseWKT, geomFromWKT, geomToWKT, readgeom, writegeom,
            project, projectNormalized, interpolate, interpolateNormalized,
            buffer, envelope, intersection, convexhull, difference, symmetricDifference,
            boundary, union, unaryUnion, pointOnSurface, centroid, node,
            polygonize, lineMerge, simplify, topologyPreserveSimplify, uniquePoints, sharedPaths,
            snap, delaunayTriangulation, delaunayTriangulationEdges,
            disjoint, touches, intersects, crosses, within, contains, overlaps, equals, equalsexact, covers, coveredby,
            prepareGeom, prepcontains, prepcontainsproperly, prepcoveredby, prepcovers, prepcrosses,
            prepdisjoint, prepintersects, prepoverlaps, preptouches, prepwithin,
            isEmpty, isSimple, isRing, hasZ, isClosed, isValid, interiorRings, exteriorRing,
            numPoints, startPoint, endPoint, area, geomLength, distance, hausdorffdistance, nearestPoints

    include("geos_c.jl")

    mutable struct GEOSError <: Exception
        msg::String
    end
    Base.showerror(io::IO, err::GEOSError) = print(io, "GEOSError\n\t$(err.msg)")

    function geosjl_errorhandler(message::Ptr{UInt8}, userdata)
        if unsafe_string(message) == "%s"
            throw(GEOSError(unsafe_string(Cstring(userdata))))
        else
            throw(GEOSError(unsafe_string(message)))
        end
    end

    mutable struct GEOSContext
        ptr::GEOSContextHandle_t

        function GEOSContext()
            context = new(GEOS_init_r())
            GEOSContext_setNoticeHandler_r(context.ptr, C_NULL)
            GEOSContext_setErrorHandler_r(context.ptr,
                cfunction(geosjl_errorhandler,Ptr{Void},(Ptr{UInt8},Ptr{Void}))
            )
            finalizer(context, context -> (GEOS_finish_r(context.ptr); context.ptr = C_NULL))
            context
        end
    end

    mutable struct WKTReader
        ptr::Ptr{GEOSWKTReader}

        function WKTReader(context::GEOSContext)
            reader = new(GEOSWKTReader_create_r(context.ptr))
            finalizer(reader, function(reader)
                GEOSWKTReader_destroy_r(context.ptr, reader.ptr)
                reader.ptr = C_NULL
            end)
            reader
        end
    end

    mutable struct WKTWriter
        ptr::Ptr{GEOSWKTWriter}

        function WKTWriter(context::GEOSContext; trim::Bool=true, outputdim::Int=3, roundingprecision::Int=-1)
            writer = new(GEOSWKTWriter_create_r(context.ptr))
            finalizer(writer, function(writer)
                GEOSWKTWriter_destroy_r(context.ptr, writer.ptr)
                GEOSWKTWriter_setTrim_r(context.ptr, writer.ptr, UInt8(trim))
                GEOSWKTWriter_setOutputDimension_r(context.ptr, writer.ptr, outputdim)
                GEOSWKTWriter_setRoundingPrecision_r(context.ptr, writer.ptr, roundingprecision)
                writer.ptr = C_NULL
            end)
            writer
        end
    end

    mutable struct WKBReader
        ptr::Ptr{GEOSWKBReader}

        function WKBReader(context::GEOSContext)
            reader = new(GEOSWKBReader_create_r(context.ptr))
            finalizer(reader, function(reader)
                GEOSWKBReader_destroy_r(context.ptr, reader.ptr)
                reader.ptr = C_NULL
            end)
            reader
        end
    end

    mutable struct WKBWriter
        ptr::Ptr{GEOSWKBWriter}

        function WKBWriter(context::GEOSContext)
            writer = new(GEOSWKBWriter_create_r(context.ptr))
            finalizer(writer, function(writer)
                GEOSWKBWriter_destroy_r(context.ptr, writer.ptr)
                writer.ptr = C_NULL
            end)
            writer
        end
    end

    function __init__()
        # Always check your dependencies from `deps.jl`
        check_deps()

        global const _context = GEOSContext()
    end

    include("geos_functions.jl")
    include("geos_types.jl")
    include("geos_operations.jl")
    include("geo_interface.jl")
    include("deprecated.jl")
end

ext: jl


text:
@block AnthonyWang ["implicits"] begin
    @cell "Implicit equation" ["2d", contour, implicit] begin
        r = range(-5, stop = 5, length = 400)
        (a, b) = -1, 2
        z = ((x,y) -> y.^4 - x.^4 + a .* y.^2 + b .* x.^2).(r, r')
        z2 =  z .* (abs.(z) .< 250)
        contour(r, r, z2)
    end

    @cell "Cube lattice" ["3d", contour, implicit, colormap] begin
        r = range(-3, stop = 3, length = 100)
        me = [((1 ./ x).^2 + (1 ./ y).^2 + (1 ./ z).^2) for x=r, y=r, z=r]
        me2 = me .* (abs.(me) .> 1.5)
        contour(me2, color = :Set2)
    end

    @cell "3D cube with sphere cutout, inside" ["3d", volume, implicit] begin
        scene = Scene()
        r = range(-1, stop = 1, length = 100)
        mat = [(x.^2 + y.^2 + z.^2) for x = r, y = r, z = r]
        mat2 = mat .* (mat .> 1.4)
        #plot the space inside
        volume(mat2, algorithm = :absorptionrgba)
    end

    @cell "3D cube with sphere cutout, outside" ["3d", volume, implicit] begin
        scene = Scene()
        r = range(-1, stop = 1, length = 100)
        mat = [(x.^2 + y.^2 + z.^2) for x=r, y=r, z=r]
        mat2 = mat .* (mat .< 1.4)
        #plot the space outside
        volume(50..100, 50..100, 50..100, mat2, algorithm = :absorptionrgba)
    end

    @cell "Biohazard" ["3d", volume, implicit, algorithm, absorption] begin
        (a, b) = -1, 2
        r = range(-5, stop = 5, length = 100)
        z = ((x,y) -> y.^4 - x.^4 + a.*y.^2 + b.*x.^2).(r, r')
        me = [cos.(2 .* pi .* sqrt.(x.^2 + y.^2)) .* (4 .* z) for x=r, y=r, z=r]
        me2 = me .* (abs.(me) .> z .* 3)
        volume(me2, algorithm = :absorptionrgba)
    end

    @cell "Twisty cube thing" ["3d", implicit, contour, colormap, colorrange] begin
        (a, b) = -1, 2
        r = range(-2, stop = 2, length = 100)
        z = ((x,y) -> x + y).(r, r') ./ 5
        me = [z .* sin.(3 .* (atan.(y ./ x) .+ z.^2 .+ pi .* (x .> 0))) for x=r, y=r, z=r]
        me2 = me .* (me .> z .* 0.25)
        contour(me2, levels = 6, colormap = :Spectral)
    end

    @cell "Spacecraft from a galaxy far, far away" ["3d", implicit, contour, surface, inequalities, colormap, colorrange] begin
        N = 100
        r = range(-1, stop = 1, length = N)

        # bunch of equations and inequalities
        f1(x,y,z) = x.^2 .+ y.^2 .+ z.^2 #center sphere
        f2(x,y,z) = y.^2 .+ z.^2 #command deck cylinder thing
        f3(x,y,z) = x.^2 .+ 4 .* y.^2 #controls the flattened cylinder connecting center pod to wings
        f4(x,y,z) = (y .* 0.7 .+ 0.05) #defines the diagonal spokes
        f5(x,y,z) = (y .* 0.7 .- 0.05) #defines the diagonal spokes
        f6(x,y,z) = abs.(x) + 0.3 .* abs.(y) #frame part of the wings

        e1(x,y,z) = 0.12 .* (1 .- abs.(z)) #limits of a hexagonal tube in the inside of the craft
        e2(x,y,z) = abs.(z) .* (abs.(z) .< 0.95) #outer limits of the wing plane
        e3(x,y,z) = abs.(z) .* (abs.(z) .> 0.9) #inner limits of the wing plane
        e4(x,y,z) = (abs.(x) + abs.(0.3 .*y)) .* ((abs.(x) + abs.(0.3 .* y)) .< 1) #frame of the wings
        e5(x,y,z) = abs.(z) .* (abs.(z) .< 1.05) #outside thickness of wing frames, including the spokes
        e6(x,y,z) = abs.(z) .* (abs.(z) .> 0.80) #inside thickness of wing frames, including the spokes
        e7(x,y,z) = abs.(x) .* (abs.(x) .< 0.7) #length of the straight bars part of frames
        e8(x,y,z) = abs.(y) .* (abs.(y) .> 0.9) #width of the straight bars part of frames
        e9(x,y,z) = abs.(y) .* (abs.(y) .< 0.035) #the thickness of the horizontal reinforcing bar on the wing planes

        amp = 15 #this just amplifies the "strength" of a volume, so that it shows up more clearly in the plot

        # spawn the tie fighter
        me = [(f1(x,y,z) .* f1(x,y,z).<0.2) .+ ((f2(x,y,z) .* f2(x,y,z).<0.02).*((x.<0.68).*(x.>0.50))) .+ amp .* (f3(x,y,z) .* (f3(x,y,z) .< e1(x,y,z))) .+ (e2(x,y,z).*e3(x,y,z).*e4(x,y,z)) .+ (e5(x,y,z).*e6(x,y,z)).*((e7(x,y,z)).*(e8(x,y,z)) .+ e9(x,y,z) .+ ((x.>f5(x,y,z)).*x).*((x.<f4(x,y,z)).*x) .+ (((-).(x).>f5(x,y,z)).*x).*(((-).(x).<f4(x,y,z)).*x) .+ ((f6(x,y,z).*(f6(x,y,z).<1.05)).*(f6(x,y,z).*(f6(x,y,z).>0.95)))) for x=r, y=r, z=r]

        me2 = me
        for i = 1:length(r)
            me2[:,:,i] = me2[:,:,i] .- min(me2[:,:,i]...)
            me2[:,:,i] = me2[:,:,i] ./ max(me2[:,:,i]...)
        end
        contour(me2, colormap = :Purples, colorrange = (0.001,0.6), alpha = 1.0, levels = 10)
    end

end


text:
@testset "result" begin

    @testset "summarize" begin
        @testset "standard" begin
            res = OneClassActiveLearning.Result(Dict(:hash => 1))
            for i in 0:5
                for e in [:metric]
                    push!(res.al_history, e, i, float(i))
                    if i > 0
                        push!(res.al_history, :query_history, i, i)
                        push!(res.al_history, :query_label, i, iseven(i) ? :outlier : :inlier)
                    end
                end
            end
            OneClassActiveLearning.al_summarize!(res)
            al_summary = res.al_summary[:metric]
            @test al_summary[:start_quality] == 0.0
            @test al_summary[:end_quality] == 5.0
            @test al_summary[:maximum] == 5.0
            @test al_summary[:ramp_up] == [1.0, 2.0, 3.0, 4.0, 5.0]
            @test al_summary[:quality_range] == 5.0
            @test al_summary[:total_quality_range] == 5.0
            @test al_summary[:average_end_quality] == [2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
            @test al_summary[:average_quality_change] == 1.0
            @test al_summary[:learning_stability] == [1.0, 1.0, 1.0, 1.0, 1.0]
            @test al_summary[:average_gain] == 1.0
            @test al_summary[:average_loss] == 0.0
            @test al_summary[:ratio_of_outlier_queries] == 2 / 5
        end

        @testset "1 query" begin
            res = OneClassActiveLearning.Result(Dict(:hash => 1))
            for i in 0:1
                for e in [:metric]
                    push!(res.al_history, e, i, float(i))
                end
            end
            push!(res.al_history, :query_history, 1, 1)
            push!(res.al_history, :query_label, 1, :inlier)
            OneClassActiveLearning.al_summarize!(res)
            al_summary = res.al_summary[:metric]
            @test al_summary[:start_quality] == 0.0
            @test al_summary[:end_quality] == 1.0
            @test al_summary[:maximum] == 1.0
            @test al_summary[:ramp_up] == [1.0]
            @test al_summary[:quality_range] == 1.0
            @test al_summary[:total_quality_range] == 1.0
            @test al_summary[:average_end_quality] == [0.5, 1.0]
            @test al_summary[:average_quality_change] == 1.0
            @test al_summary[:learning_stability] == [1.0]
            @test al_summary[:average_gain] == 1.0
            @test al_summary[:average_loss] == 0.0
            @test al_summary[:ratio_of_outlier_queries] == 0.0
        end

        @testset "1 query 0 improvement" begin
            res = OneClassActiveLearning.Result(Dict(:hash => 1))
            for i in 0:1
                for e in [:metric]
                    push!(res.al_history, e, i, 0.0)
                end
            end
            push!(res.al_history, :query_history, 1, 1)
            push!(res.al_history, :query_label, 1, :inlier)
            OneClassActiveLearning.al_summarize!(res)
            al_summary = res.al_summary[:metric]
            @test al_summary[:start_quality] == 0.0
            @test al_summary[:end_quality] == 0.0
            @test al_summary[:maximum] == 0.0
            @test al_summary[:ramp_up] == [0.0]
            @test al_summary[:quality_range] == 0.0
            @test al_summary[:total_quality_range] == 0.0
            @test al_summary[:average_end_quality] == [0.0, 0.0]
            @test al_summary[:average_quality_change] == 0.0
            @test al_summary[:learning_stability] == [0.0]
            @test al_summary[:average_gain] == 0.0
            @test al_summary[:average_loss] == 0.0
            @test al_summary[:ratio_of_outlier_queries] == 0.0
        end
    end
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct Operation <: SwaggerModel
    name::Any # spec type: Union{ Nothing, String } # spec name: name
    display::Any # spec type: Union{ Nothing, OperationDisplay } # spec name: display
    origin::Any # spec type: Union{ Nothing, String } # spec name: origin

    function Operation(;name=nothing, display=nothing, origin=nothing)
        o = new()
        validate_property(Operation, Symbol("name"), name)
        setfield!(o, Symbol("name"), name)
        validate_property(Operation, Symbol("display"), display)
        setfield!(o, Symbol("display"), display)
        validate_property(Operation, Symbol("origin"), origin)
        setfield!(o, Symbol("origin"), origin)
        o
    end
end # type Operation

const _property_map_Operation = Dict{Symbol,Symbol}(Symbol("name")=>Symbol("name"), Symbol("display")=>Symbol("display"), Symbol("origin")=>Symbol("origin"))
const _property_types_Operation = Dict{Symbol,String}(Symbol("name")=>"String", Symbol("display")=>"OperationDisplay", Symbol("origin")=>"String")
Base.propertynames(::Type{ Operation }) = collect(keys(_property_map_Operation))
Swagger.property_type(::Type{ Operation }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_Operation[name]))}
Swagger.field_name(::Type{ Operation }, property_name::Symbol) =  _property_map_Operation[property_name]

const _allowed_Operation_origin = ["user", "system", "user,system"]

function check_required(o::Operation)
    true
end

function validate_property(::Type{ Operation }, name::Symbol, val)
    if name === Symbol("origin")
        Swagger.validate_param(name, "Operation", :enum, val, _allowed_Operation_origin)
    end
end


text:
include("../src/MsgPackRpcClient.jl")

using MsgPackRpcClient

session = MsgPackRpcClientSession.create() # MsgPackRpcClientSession.Session(nothing, nothing, 1)

the_number_of_call = 10000
results = {}

for i in 1:the_number_of_call
  result = MsgPackRpcClient.call(session, "hello")
  push!(results, result)
end

for result in results
  println(result)
end

session.destroy() # MsgPackRpcClientSession.destroy(session)

max_stars_repo_name: keithseahus/msgpack-rpc-julia

max_issues_repo_name: keithseahus/msgpack-rpc-julia

max_forks_repo_name: keithseahus/msgpack-rpc-julia


text:
using Test, LinearAlgebra
using DiffEqEigTool


text:
## calcular o gradiente
function force_pair(delta_x, delta_y, r, data)

    drdx = (delta_x)/r #delta_x -> calculado com imagem mínima
    drdy = (delta_y)/r #delya_y -> calculado com iamgem mínima

    dudr = (6*data.eps4*data.sig6)*(r^6-(2*data.sig6))/r^13

    dudx = dudr*drdx
    dudy = dudr*drdy
    return (-dudx, -dudy)

end

# calcular a resultante das forças atuando em cada partícula
function lj_force!(p,  data, first_atom, next_atom, forces_list)
    np = length(p) # Number of particles
    u = 0
    for ip in 1:np
        icell = trunc(Int64,p[ip][1]/data.cutoff)+1
        jcell = trunc(Int64,p[ip][2]/data.cutoff)+1
        for k in icell-1:icell+1
          for l in jcell-1:jcell+1
                i, j = wrap_cell([data.nc, data.nc], k, l)
                jp = first_atom[i, j]
                while jp > 0
                    if ip < jp
                        r, delta_x, delta_y = minimg(p[ip], p[jp], data.side)
                        if r <= data.cutoff
                            force = force_pair(delta_x, delta_y, r, data)
                            forces_list[ip] += [force[1], force[2]]
                            forces_list[jp] -= [force[1], force[2]]
                            u += upair(r,data)
                        end
                    end
                    jp = next_atom[jp]
                end
            end
        end
    end
    return u
end


text:
#==============================================================================#
# WorkSpaces.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/workspaces-2015-04-08.normal.json
#==============================================================================#

__precompile__()

module WorkSpaces

using AWSCore

"""
    using AWSSDK.WorkSpaces.associate_ip_groups
    associate_ip_groups([::AWSConfig], arguments::Dict)
    associate_ip_groups([::AWSConfig]; DirectoryId=, GroupIds=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "AssociateIpGroups", arguments::Dict)
    workspaces([::AWSConfig], "AssociateIpGroups", DirectoryId=, GroupIds=)

# AssociateIpGroups Operation

Associates the specified IP access control group with the specified directory.

# Arguments

## `DirectoryId = ::String` -- *Required*
The ID of the directory.

## `GroupIds = [::String, ...]` -- *Required*
The IDs of one or more IP access control groups.

# Returns

`AssociateIpGroupsResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `ResourceLimitExceededException`, `InvalidResourceStateException`, `AccessDeniedException` or `OperationNotSupportedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/AssociateIpGroups)
"""
@inline associate_ip_groups(aws::AWSConfig=default_aws_config(); args...) = associate_ip_groups(aws, args)

@inline associate_ip_groups(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "AssociateIpGroups", args)

@inline associate_ip_groups(args) = associate_ip_groups(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.authorize_ip_rules
    authorize_ip_rules([::AWSConfig], arguments::Dict)
    authorize_ip_rules([::AWSConfig]; GroupId=, UserRules=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "AuthorizeIpRules", arguments::Dict)
    workspaces([::AWSConfig], "AuthorizeIpRules", GroupId=, UserRules=)

# AuthorizeIpRules Operation

Adds one or more rules to the specified IP access control group.

This action gives users permission to access their WorkSpaces from the CIDR address ranges specified in the rules.

# Arguments

## `GroupId = ::String` -- *Required*
The ID of the group.

## `UserRules = [[ ... ], ...]` -- *Required*
The rules to add to the group.
```
 UserRules = [[
        "ipRule" =>  ::String,
        "ruleDesc" =>  ::String
    ], ...]
```

# Returns

`AuthorizeIpRulesResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `ResourceLimitExceededException`, `InvalidResourceStateException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/AuthorizeIpRules)
"""
@inline authorize_ip_rules(aws::AWSConfig=default_aws_config(); args...) = authorize_ip_rules(aws, args)

@inline authorize_ip_rules(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "AuthorizeIpRules", args)

@inline authorize_ip_rules(args) = authorize_ip_rules(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.create_ip_group
    create_ip_group([::AWSConfig], arguments::Dict)
    create_ip_group([::AWSConfig]; GroupName=, <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "CreateIpGroup", arguments::Dict)
    workspaces([::AWSConfig], "CreateIpGroup", GroupName=, <keyword arguments>)

# CreateIpGroup Operation

Creates an IP access control group.

An IP access control group provides you with the ability to control the IP addresses from which users are allowed to access their WorkSpaces. To specify the CIDR address ranges, add rules to your IP access control group and then associate the group with your directory. You can add rules when you create the group or at any time using [AuthorizeIpRules](@ref).

There is a default IP access control group associated with your directory. If you don't associate an IP access control group with your directory, the default group is used. The default group includes a default rule that allows users to access their WorkSpaces from anywhere. You cannot modify the default IP access control group for your directory.

# Arguments

## `GroupName = ::String` -- *Required*
The name of the group.

## `GroupDesc = ::String`
The description of the group.

## `UserRules = [[ ... ], ...]`
The rules to add to the group.
```
 UserRules = [[
        "ipRule" =>  ::String,
        "ruleDesc" =>  ::String
    ], ...]
```

# Returns

`CreateIpGroupResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceLimitExceededException`, `ResourceAlreadyExistsException`, `ResourceCreationFailedException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/CreateIpGroup)
"""
@inline create_ip_group(aws::AWSConfig=default_aws_config(); args...) = create_ip_group(aws, args)

@inline create_ip_group(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "CreateIpGroup", args)

@inline create_ip_group(args) = create_ip_group(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.create_tags
    create_tags([::AWSConfig], arguments::Dict)
    create_tags([::AWSConfig]; ResourceId=, Tags=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "CreateTags", arguments::Dict)
    workspaces([::AWSConfig], "CreateTags", ResourceId=, Tags=)

# CreateTags Operation

Creates the specified tags for the specified WorkSpace.

# Arguments

## `ResourceId = ::String` -- *Required*
The ID of the WorkSpace. To find this ID, use [DescribeWorkspaces](@ref).

## `Tags = [[ ... ], ...]` -- *Required*
The tags. Each WorkSpace can have a maximum of 50 tags.
```
 Tags = [[
        "Key" => <required> ::String,
        "Value" =>  ::String
    ], ...]
```

# Returns

`CreateTagsResult`

# Exceptions

`ResourceNotFoundException`, `InvalidParameterValuesException` or `ResourceLimitExceededException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/CreateTags)
"""
@inline create_tags(aws::AWSConfig=default_aws_config(); args...) = create_tags(aws, args)

@inline create_tags(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "CreateTags", args)

@inline create_tags(args) = create_tags(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.create_workspaces
    create_workspaces([::AWSConfig], arguments::Dict)
    create_workspaces([::AWSConfig]; Workspaces=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "CreateWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "CreateWorkspaces", Workspaces=)

# CreateWorkspaces Operation

Creates one or more WorkSpaces.

This operation is asynchronous and returns before the WorkSpaces are created.

# Arguments

## `Workspaces = [[ ... ], ...]` -- *Required*
The WorkSpaces to create. You can specify up to 25 WorkSpaces.
```
 Workspaces = [[
        "DirectoryId" => <required> ::String,
        "UserName" => <required> ::String,
        "BundleId" => <required> ::String,
        "VolumeEncryptionKey" =>  ::String,
        "UserVolumeEncryptionEnabled" =>  ::Bool,
        "RootVolumeEncryptionEnabled" =>  ::Bool,
        "WorkspaceProperties" =>  [
            "RunningMode" =>  "AUTO_STOP" or "ALWAYS_ON",
            "RunningModeAutoStopTimeoutInMinutes" =>  ::Int,
            "RootVolumeSizeGib" =>  ::Int,
            "UserVolumeSizeGib" =>  ::Int,
            "ComputeTypeName" =>  "VALUE", "STANDARD", "PERFORMANCE", "POWER" or "GRAPHICS"
        ],
        "Tags" =>  [[
            "Key" => <required> ::String,
            "Value" =>  ::String
        ], ...]
    ], ...]
```

# Returns

`CreateWorkspacesResult`

# Exceptions

`ResourceLimitExceededException` or `InvalidParameterValuesException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/CreateWorkspaces)
"""
@inline create_workspaces(aws::AWSConfig=default_aws_config(); args...) = create_workspaces(aws, args)

@inline create_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "CreateWorkspaces", args)

@inline create_workspaces(args) = create_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.delete_ip_group
    delete_ip_group([::AWSConfig], arguments::Dict)
    delete_ip_group([::AWSConfig]; GroupId=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DeleteIpGroup", arguments::Dict)
    workspaces([::AWSConfig], "DeleteIpGroup", GroupId=)

# DeleteIpGroup Operation

Deletes the specified IP access control group.

You cannot delete an IP access control group that is associated with a directory.

# Arguments

## `GroupId = ::String` -- *Required*
The ID of the IP access control group.

# Returns

`DeleteIpGroupResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `ResourceAssociatedException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DeleteIpGroup)
"""
@inline delete_ip_group(aws::AWSConfig=default_aws_config(); args...) = delete_ip_group(aws, args)

@inline delete_ip_group(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DeleteIpGroup", args)

@inline delete_ip_group(args) = delete_ip_group(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.delete_tags
    delete_tags([::AWSConfig], arguments::Dict)
    delete_tags([::AWSConfig]; ResourceId=, TagKeys=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DeleteTags", arguments::Dict)
    workspaces([::AWSConfig], "DeleteTags", ResourceId=, TagKeys=)

# DeleteTags Operation

Deletes the specified tags from the specified WorkSpace.

# Arguments

## `ResourceId = ::String` -- *Required*
The ID of the WorkSpace. To find this ID, use [DescribeWorkspaces](@ref).

## `TagKeys = [::String, ...]` -- *Required*
The tag keys.

# Returns

`DeleteTagsResult`

# Exceptions

`ResourceNotFoundException` or `InvalidParameterValuesException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DeleteTags)
"""
@inline delete_tags(aws::AWSConfig=default_aws_config(); args...) = delete_tags(aws, args)

@inline delete_tags(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DeleteTags", args)

@inline delete_tags(args) = delete_tags(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_ip_groups
    describe_ip_groups([::AWSConfig], arguments::Dict)
    describe_ip_groups([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeIpGroups", arguments::Dict)
    workspaces([::AWSConfig], "DescribeIpGroups", <keyword arguments>)

# DescribeIpGroups Operation

Describes one or more of your IP access control groups.

# Arguments

## `GroupIds = [::String, ...]`
The IDs of one or more IP access control groups.

## `NextToken = ::String`
The token for the next set of results. (You received this token from a previous call.)

## `MaxResults = ::Int`
The maximum number of items to return.

# Returns

`DescribeIpGroupsResult`

# Exceptions

`InvalidParameterValuesException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeIpGroups)
"""
@inline describe_ip_groups(aws::AWSConfig=default_aws_config(); args...) = describe_ip_groups(aws, args)

@inline describe_ip_groups(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeIpGroups", args)

@inline describe_ip_groups(args) = describe_ip_groups(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_tags
    describe_tags([::AWSConfig], arguments::Dict)
    describe_tags([::AWSConfig]; ResourceId=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeTags", arguments::Dict)
    workspaces([::AWSConfig], "DescribeTags", ResourceId=)

# DescribeTags Operation

Describes the specified tags for the specified WorkSpace.

# Arguments

## `ResourceId = ::String` -- *Required*
The ID of the WorkSpace. To find this ID, use [DescribeWorkspaces](@ref).

# Returns

`DescribeTagsResult`

# Exceptions

`ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeTags)
"""
@inline describe_tags(aws::AWSConfig=default_aws_config(); args...) = describe_tags(aws, args)

@inline describe_tags(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeTags", args)

@inline describe_tags(args) = describe_tags(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_workspace_bundles
    describe_workspace_bundles([::AWSConfig], arguments::Dict)
    describe_workspace_bundles([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeWorkspaceBundles", arguments::Dict)
    workspaces([::AWSConfig], "DescribeWorkspaceBundles", <keyword arguments>)

# DescribeWorkspaceBundles Operation

Describes the available WorkSpace bundles.

You can filter the results using either bundle ID or owner, but not both.

# Arguments

## `BundleIds = [::String, ...]`
The IDs of the bundles. This parameter cannot be combined with any other filter.

## `Owner = ::String`
The owner of the bundles. This parameter cannot be combined with any other filter.

Specify `AMAZON` to describe the bundles provided by AWS or null to describe the bundles that belong to your account.

## `NextToken = ::String`
The token for the next set of results. (You received this token from a previous call.)

# Returns

`DescribeWorkspaceBundlesResult`

# Exceptions

`InvalidParameterValuesException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeWorkspaceBundles)
"""
@inline describe_workspace_bundles(aws::AWSConfig=default_aws_config(); args...) = describe_workspace_bundles(aws, args)

@inline describe_workspace_bundles(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeWorkspaceBundles", args)

@inline describe_workspace_bundles(args) = describe_workspace_bundles(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_workspace_directories
    describe_workspace_directories([::AWSConfig], arguments::Dict)
    describe_workspace_directories([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeWorkspaceDirectories", arguments::Dict)
    workspaces([::AWSConfig], "DescribeWorkspaceDirectories", <keyword arguments>)

# DescribeWorkspaceDirectories Operation

Describes the available AWS Directory Service directories that are registered with Amazon WorkSpaces.

# Arguments

## `DirectoryIds = [::String, ...]`
The identifiers of the directories. If the value is null, all directories are retrieved.

## `NextToken = ::String`
The token for the next set of results. (You received this token from a previous call.)

# Returns

`DescribeWorkspaceDirectoriesResult`

# Exceptions

`InvalidParameterValuesException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeWorkspaceDirectories)
"""
@inline describe_workspace_directories(aws::AWSConfig=default_aws_config(); args...) = describe_workspace_directories(aws, args)

@inline describe_workspace_directories(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeWorkspaceDirectories", args)

@inline describe_workspace_directories(args) = describe_workspace_directories(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_workspaces
    describe_workspaces([::AWSConfig], arguments::Dict)
    describe_workspaces([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "DescribeWorkspaces", <keyword arguments>)

# DescribeWorkspaces Operation

Describes the specified WorkSpaces.

You can filter the results using bundle ID, directory ID, or owner, but you can specify only one filter at a time.

# Arguments

## `WorkspaceIds = [::String, ...]`
The IDs of the WorkSpaces. This parameter cannot be combined with any other filter.

Because the [CreateWorkspaces](@ref) operation is asynchronous, the identifier it returns is not immediately available. If you immediately call [DescribeWorkspaces](@ref) with this identifier, no information is returned.

## `DirectoryId = ::String`
The ID of the directory. In addition, you can optionally specify a specific directory user (see `UserName`). This parameter cannot be combined with any other filter.

## `UserName = ::String`
The name of the directory user. You must specify this parameter with `DirectoryId`.

## `BundleId = ::String`
The ID of the bundle. All WorkSpaces that are created from this bundle are retrieved. This parameter cannot be combined with any other filter.

## `Limit = ::Int`
The maximum number of items to return.

## `NextToken = ::String`
The token for the next set of results. (You received this token from a previous call.)

# Returns

`DescribeWorkspacesResult`

# Exceptions

`InvalidParameterValuesException` or `ResourceUnavailableException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeWorkspaces)
"""
@inline describe_workspaces(aws::AWSConfig=default_aws_config(); args...) = describe_workspaces(aws, args)

@inline describe_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeWorkspaces", args)

@inline describe_workspaces(args) = describe_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.describe_workspaces_connection_status
    describe_workspaces_connection_status([::AWSConfig], arguments::Dict)
    describe_workspaces_connection_status([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DescribeWorkspacesConnectionStatus", arguments::Dict)
    workspaces([::AWSConfig], "DescribeWorkspacesConnectionStatus", <keyword arguments>)

# DescribeWorkspacesConnectionStatus Operation

Describes the connection status of the specified WorkSpaces.

# Arguments

## `WorkspaceIds = [::String, ...]`
The identifiers of the WorkSpaces. You can specify up to 25 WorkSpaces.

## `NextToken = ::String`
The token for the next set of results. (You received this token from a previous call.)

# Returns

`DescribeWorkspacesConnectionStatusResult`

# Exceptions

`InvalidParameterValuesException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DescribeWorkspacesConnectionStatus)
"""
@inline describe_workspaces_connection_status(aws::AWSConfig=default_aws_config(); args...) = describe_workspaces_connection_status(aws, args)

@inline describe_workspaces_connection_status(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DescribeWorkspacesConnectionStatus", args)

@inline describe_workspaces_connection_status(args) = describe_workspaces_connection_status(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.disassociate_ip_groups
    disassociate_ip_groups([::AWSConfig], arguments::Dict)
    disassociate_ip_groups([::AWSConfig]; DirectoryId=, GroupIds=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "DisassociateIpGroups", arguments::Dict)
    workspaces([::AWSConfig], "DisassociateIpGroups", DirectoryId=, GroupIds=)

# DisassociateIpGroups Operation

Disassociates the specified IP access control group from the specified directory.

# Arguments

## `DirectoryId = ::String` -- *Required*
The ID of the directory.

## `GroupIds = [::String, ...]` -- *Required*
The IDs of one or more IP access control groups.

# Returns

`DisassociateIpGroupsResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `InvalidResourceStateException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/DisassociateIpGroups)
"""
@inline disassociate_ip_groups(aws::AWSConfig=default_aws_config(); args...) = disassociate_ip_groups(aws, args)

@inline disassociate_ip_groups(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "DisassociateIpGroups", args)

@inline disassociate_ip_groups(args) = disassociate_ip_groups(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.modify_workspace_properties
    modify_workspace_properties([::AWSConfig], arguments::Dict)
    modify_workspace_properties([::AWSConfig]; WorkspaceId=, WorkspaceProperties=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "ModifyWorkspaceProperties", arguments::Dict)
    workspaces([::AWSConfig], "ModifyWorkspaceProperties", WorkspaceId=, WorkspaceProperties=)

# ModifyWorkspaceProperties Operation

Modifies the specified WorkSpace properties.

# Arguments

## `WorkspaceId = ::String` -- *Required*
The ID of the WorkSpace.

## `WorkspaceProperties = [ ... ]` -- *Required*
The properties of the WorkSpace.
```
 WorkspaceProperties = [
        "RunningMode" =>  "AUTO_STOP" or "ALWAYS_ON",
        "RunningModeAutoStopTimeoutInMinutes" =>  ::Int,
        "RootVolumeSizeGib" =>  ::Int,
        "UserVolumeSizeGib" =>  ::Int,
        "ComputeTypeName" =>  "VALUE", "STANDARD", "PERFORMANCE", "POWER" or "GRAPHICS"
    ]
```

# Returns

`ModifyWorkspacePropertiesResult`

# Exceptions

`InvalidParameterValuesException`, `InvalidResourceStateException`, `OperationInProgressException`, `UnsupportedWorkspaceConfigurationException`, `ResourceNotFoundException`, `AccessDeniedException` or `ResourceUnavailableException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/ModifyWorkspaceProperties)
"""
@inline modify_workspace_properties(aws::AWSConfig=default_aws_config(); args...) = modify_workspace_properties(aws, args)

@inline modify_workspace_properties(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "ModifyWorkspaceProperties", args)

@inline modify_workspace_properties(args) = modify_workspace_properties(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.modify_workspace_state
    modify_workspace_state([::AWSConfig], arguments::Dict)
    modify_workspace_state([::AWSConfig]; WorkspaceId=, WorkspaceState=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "ModifyWorkspaceState", arguments::Dict)
    workspaces([::AWSConfig], "ModifyWorkspaceState", WorkspaceId=, WorkspaceState=)

# ModifyWorkspaceState Operation

Sets the state of the specified WorkSpace.

To maintain a WorkSpace without being interrupted, set the WorkSpace state to `ADMIN_MAINTENANCE`. WorkSpaces in this state do not respond to requests to reboot, stop, start, or rebuild. An AutoStop WorkSpace in this state is not stopped. Users can log into a WorkSpace in the `ADMIN_MAINTENANCE` state.

# Arguments

## `WorkspaceId = ::String` -- *Required*
The ID of the WorkSpace.

## `WorkspaceState = "AVAILABLE" or "ADMIN_MAINTENANCE"` -- *Required*
The WorkSpace state.

# Returns

`ModifyWorkspaceStateResult`

# Exceptions

`InvalidParameterValuesException`, `InvalidResourceStateException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/ModifyWorkspaceState)
"""
@inline modify_workspace_state(aws::AWSConfig=default_aws_config(); args...) = modify_workspace_state(aws, args)

@inline modify_workspace_state(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "ModifyWorkspaceState", args)

@inline modify_workspace_state(args) = modify_workspace_state(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.reboot_workspaces
    reboot_workspaces([::AWSConfig], arguments::Dict)
    reboot_workspaces([::AWSConfig]; RebootWorkspaceRequests=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "RebootWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "RebootWorkspaces", RebootWorkspaceRequests=)

# RebootWorkspaces Operation

Reboots the specified WorkSpaces.

You cannot reboot a WorkSpace unless its state is `AVAILABLE` or `UNHEALTHY`.

This operation is asynchronous and returns before the WorkSpaces have rebooted.

# Arguments

## `RebootWorkspaceRequests = [["WorkspaceId" => <required> ::String], ...]` -- *Required*
The WorkSpaces to reboot. You can specify up to 25 WorkSpaces.

# Returns

`RebootWorkspacesResult`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/RebootWorkspaces)
"""
@inline reboot_workspaces(aws::AWSConfig=default_aws_config(); args...) = reboot_workspaces(aws, args)

@inline reboot_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "RebootWorkspaces", args)

@inline reboot_workspaces(args) = reboot_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.rebuild_workspaces
    rebuild_workspaces([::AWSConfig], arguments::Dict)
    rebuild_workspaces([::AWSConfig]; RebuildWorkspaceRequests=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "RebuildWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "RebuildWorkspaces", RebuildWorkspaceRequests=)

# RebuildWorkspaces Operation

Rebuilds the specified WorkSpace.

You cannot rebuild a WorkSpace unless its state is `AVAILABLE`, `ERROR`, or `UNHEALTHY`.

Rebuilding a WorkSpace is a potentially destructive action that can result in the loss of data. For more information, see [Rebuild a WorkSpace](http://docs.aws.amazon.com/workspaces/latest/adminguide/reset-workspace.html).

This operation is asynchronous and returns before the WorkSpaces have been completely rebuilt.

# Arguments

## `RebuildWorkspaceRequests = [["WorkspaceId" => <required> ::String], ...]` -- *Required*
The WorkSpace to rebuild. You can specify a single WorkSpace.

# Returns

`RebuildWorkspacesResult`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/RebuildWorkspaces)
"""
@inline rebuild_workspaces(aws::AWSConfig=default_aws_config(); args...) = rebuild_workspaces(aws, args)

@inline rebuild_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "RebuildWorkspaces", args)

@inline rebuild_workspaces(args) = rebuild_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.revoke_ip_rules
    revoke_ip_rules([::AWSConfig], arguments::Dict)
    revoke_ip_rules([::AWSConfig]; GroupId=, UserRules=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "RevokeIpRules", arguments::Dict)
    workspaces([::AWSConfig], "RevokeIpRules", GroupId=, UserRules=)

# RevokeIpRules Operation

Removes one or more rules from the specified IP access control group.

# Arguments

## `GroupId = ::String` -- *Required*
The ID of the group.

## `UserRules = [::String, ...]` -- *Required*
The rules to remove from the group.

# Returns

`RevokeIpRulesResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `InvalidResourceStateException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/RevokeIpRules)
"""
@inline revoke_ip_rules(aws::AWSConfig=default_aws_config(); args...) = revoke_ip_rules(aws, args)

@inline revoke_ip_rules(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "RevokeIpRules", args)

@inline revoke_ip_rules(args) = revoke_ip_rules(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.start_workspaces
    start_workspaces([::AWSConfig], arguments::Dict)
    start_workspaces([::AWSConfig]; StartWorkspaceRequests=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "StartWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "StartWorkspaces", StartWorkspaceRequests=)

# StartWorkspaces Operation

Starts the specified WorkSpaces.

You cannot start a WorkSpace unless it has a running mode of `AutoStop` and a state of `STOPPED`.

# Arguments

## `StartWorkspaceRequests = [["WorkspaceId" =>  ::String], ...]` -- *Required*
The WorkSpaces to start. You can specify up to 25 WorkSpaces.

# Returns

`StartWorkspacesResult`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/StartWorkspaces)
"""
@inline start_workspaces(aws::AWSConfig=default_aws_config(); args...) = start_workspaces(aws, args)

@inline start_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "StartWorkspaces", args)

@inline start_workspaces(args) = start_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.stop_workspaces
    stop_workspaces([::AWSConfig], arguments::Dict)
    stop_workspaces([::AWSConfig]; StopWorkspaceRequests=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "StopWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "StopWorkspaces", StopWorkspaceRequests=)

# StopWorkspaces Operation

Stops the specified WorkSpaces.

You cannot stop a WorkSpace unless it has a running mode of `AutoStop` and a state of `AVAILABLE`, `IMPAIRED`, `UNHEALTHY`, or `ERROR`.

# Arguments

## `StopWorkspaceRequests = [["WorkspaceId" =>  ::String], ...]` -- *Required*
The WorkSpaces to stop. You can specify up to 25 WorkSpaces.

# Returns

`StopWorkspacesResult`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/StopWorkspaces)
"""
@inline stop_workspaces(aws::AWSConfig=default_aws_config(); args...) = stop_workspaces(aws, args)

@inline stop_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "StopWorkspaces", args)

@inline stop_workspaces(args) = stop_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.terminate_workspaces
    terminate_workspaces([::AWSConfig], arguments::Dict)
    terminate_workspaces([::AWSConfig]; TerminateWorkspaceRequests=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "TerminateWorkspaces", arguments::Dict)
    workspaces([::AWSConfig], "TerminateWorkspaces", TerminateWorkspaceRequests=)

# TerminateWorkspaces Operation

Terminates the specified WorkSpaces.

Terminating a WorkSpace is a permanent action and cannot be undone. The user's data is destroyed. If you need to archive any user data, contact Amazon Web Services before terminating the WorkSpace.

You can terminate a WorkSpace that is in any state except `SUSPENDED`.

This operation is asynchronous and returns before the WorkSpaces have been completely terminated.

# Arguments

## `TerminateWorkspaceRequests = [["WorkspaceId" => <required> ::String], ...]` -- *Required*
The WorkSpaces to terminate. You can specify up to 25 WorkSpaces.

# Returns

`TerminateWorkspacesResult`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/TerminateWorkspaces)
"""
@inline terminate_workspaces(aws::AWSConfig=default_aws_config(); args...) = terminate_workspaces(aws, args)

@inline terminate_workspaces(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "TerminateWorkspaces", args)

@inline terminate_workspaces(args) = terminate_workspaces(default_aws_config(), args)

"""
    using AWSSDK.WorkSpaces.update_rules_of_ip_group
    update_rules_of_ip_group([::AWSConfig], arguments::Dict)
    update_rules_of_ip_group([::AWSConfig]; GroupId=, UserRules=)

    using AWSCore.Services.workspaces
    workspaces([::AWSConfig], "UpdateRulesOfIpGroup", arguments::Dict)
    workspaces([::AWSConfig], "UpdateRulesOfIpGroup", GroupId=, UserRules=)

# UpdateRulesOfIpGroup Operation

Replaces the current rules of the specified IP access control group with the specified rules.

# Arguments

## `GroupId = ::String` -- *Required*
The ID of the group.

## `UserRules = [[ ... ], ...]` -- *Required*
One or more rules.
```
 UserRules = [[
        "ipRule" =>  ::String,
        "ruleDesc" =>  ::String
    ], ...]
```

# Returns

`UpdateRulesOfIpGroupResult`

# Exceptions

`InvalidParameterValuesException`, `ResourceNotFoundException`, `ResourceLimitExceededException`, `InvalidResourceStateException` or `AccessDeniedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/workspaces-2015-04-08/UpdateRulesOfIpGroup)
"""
@inline update_rules_of_ip_group(aws::AWSConfig=default_aws_config(); args...) = update_rules_of_ip_group(aws, args)

@inline update_rules_of_ip_group(aws::AWSConfig, args) = AWSCore.Services.workspaces(aws, "UpdateRulesOfIpGroup", args)

@inline update_rules_of_ip_group(args) = update_rules_of_ip_group(default_aws_config(), args)

end # module WorkSpaces

#==============================================================================#
# End of file
#==============================================================================#


text:
"""
Dimensions

Sub-module for [`Dimension`](@ref)s wrappers,
and operations on them used in DimensionalData.jl.

To load `Dimensions` types and methods into scope:

```julia
using DimensionalData
using .LookupArrays
```
"""
module Dimensions

import Adapt, ConstructionBase, Extents
using Dates

include("../LookupArrays/LookupArrays.jl")

using .LookupArrays

import .LookupArrays: rebuild, order, span, sampling, locus, val, index, set, _set,
    metadata, bounds, units, basetypeof, unwrap, selectindices, hasselection,
    shiftlocus, maybeshiftlocus, SelectorOrInterval
using .LookupArrays: StandardIndices, SelTuple, CategoricalEltypes,
    LookupArrayTrait, AllMetadata, LookupArraySetters

using Base: tail, OneTo, @propagate_inbounds

export name, label, dimnum, hasdim, hasselection, otherdims, commondims, combinedims,
    setdims, swapdims, sortdims, lookup, set, format, rebuild, key2dim, dim2key,
    basetypeof, basedims, dimstride, dims2indices, slicedims, dimsmatch, comparedims, reducedims

export Dimension, IndependentDim, DependentDim, XDim, YDim, ZDim, TimeDim,
    X, Y, Z, Ti, Dim, AnonDim, Coord

export @dim

include("dimension.jl")
include("primitives.jl")
include("format.jl")
include("indexing.jl")
include("set.jl")
include("show.jl")
include("coord.jl")

end


text:
"""
$(SIGNATURES)

Checks if upcoming integration is a new bit for GPSL1.
"""
function is_upcoming_integration_new_bit(::Type{GPSL1}, prns, num_prns)
    num_prns < 40 && return false
    masked_bit_synchronizer = prns & 0xffffffffff # First 40 bits
    # Upcoming integration will be a new bit if masked_bit_synchronizer contains
    # 20 zeros and 20 ones or 20 ones and 20 zeros
    masked_bit_synchronizer == 0xfffff || masked_bit_synchronizer == 0xfffff00000
end

function get_default_correlator(::Type{GPSL1}, num_ants::NumAnts{N}) where N
    EarlyPromptLateCorrelator(num_ants)
end


text:
# deprecated methods

import Base: convert

@deprecate convert(::Type{LLVMType}, typ::Type, allow_boxed::Core.Bool) convert(LLVMType, typ; allow_boxed=allow_boxed)


text:
using Revise
using AdFem
using PyCall
using LinearAlgebra
using PyPlot
using SparseArrays
using MAT
using ADCMEKit
np = pyimport("numpy")
using PyPlot
using SpecialFunctions

# Parameters setup
NT = 100
dt = 1/NT
Δt = ones(NT)*dt
Δu = 1.0 # fixed Dirichlet boundary condition on the left hand side
n = 10
m = 10n
h = 4. /n
left = bcnode("left", m, n, h)
right = bcnode("right", m, n, h)
dof = (m+1)*(n+1)
Force = zeros(NT, dof)

μ = constant(ones(4*m*n))* 100000.
η = constant(ones(4*m*n))

coef = 2μ*η/(η + μ*dt)
coef = tf.ones_like(coef) * 2.0
mapH = c->begin
  c * diagm(0=>ones(2))
end
H = map(mapH, coef)

# Precompute the mass matrices, stiffness matrix, and damping matrix
# H = diagm(0=>ones(2))
M = constant(compute_fem_mass_matrix1(m, n, h))
K = compute_fem_stiffness_matrix1(H, m, n, h)
C = 0.0 * M + 0.0 * K

# Compute the force term
αt = αscheme_time(Δt)
ub = zeros(dof, NT)
for i = 1:NT
  ub[left, i] .= Δu
  ub[right, i] .= 0.0
  # Force at αt[i]
end
ushift = constant(ub[:,1])
Force = (-K * ub)'

C = K
K = spzero((m+1)*(n+1))

strain_rate = zeros((m+1)*(n+1))
for i = 1:m+1
  for j = 1:n+1
    idx = (j-1)*(m+1)+i
    strain_rate[idx] = (m+1-i)/m
  end
end

# Initial conditions
d0 = zeros(dof)
v0 = zeros(dof)
a0 = zeros(dof)

idof = ones(Bool, dof)
idof[[left;right]] .= false
idof = findall(idof)
# a0 = vector(idof, M[idof, idof]\(Force[1,idof]), dof)
a0 = vector(idof, M[idof, idof]\constant(strain_rate)[idof], dof)

# α scheme time stepping
function solver(A, rhs)
  rhs = scatter_update(rhs, [left;right], zeros(length(left)+length(right)))
  A, _ = fem_impose_Dirichlet_boundary_condition1(A, [left;right], m, n, h)
  A\rhs
end

function αintegration_visco(M::Union{SparseTensor, SparseMatrixCSC},
  C::Union{SparseTensor, SparseMatrixCSC},
  K::Union{SparseTensor, SparseMatrixCSC},
  Force::Union{Array{Float64}, PyObject},
  d0::Union{Array{Float64, 1}, PyObject},
  v0::Union{Array{Float64, 1}, PyObject},
  a0::Union{Array{Float64, 1}, PyObject},
  Δt::Array{Float64}; solve::Union{Missing, Function} = missing)
    n_ = length(Δt)
    ρ = 1.0
    αm = (2ρ-1)/(1+ρ)
    αf = ρ/(1+ρ)
    γ = 1/2-αm+αf
    β = 0.25*(1-αm+αf)^2
    d = length(d0)

    M = isa(M, SparseMatrixCSC) ? constant(M) : M
    C = isa(C, SparseMatrixCSC) ? constant(C) : C
    K = isa(K, SparseMatrixCSC) ? constant(K) : K
    Force, d0, v0, a0, Δt = convert_to_tensor([Force, d0, v0, a0, Δt], [Float64, Float64, Float64, Float64, Float64])

    function equ(dc, vc, ac, σc, εc, dt, Force)
      dn = dc + dt*vc + dt^2/2*(1-2β)*ac
      vn = vc + dt*((1-γ)*ac)

      df = (1-αf)*dn + αf*dc
      vf = (1-αf)*vn + αf*vc
      am = αm*ac

      σn = antiplane_viscosity(-εc/dt, σc, μ, η, dt)
      # σn = -2*εc/dt
      Force_σ = compute_strain_energy_term1(σn, m, n, h)

      # rhs = Force - (M*am + C*vf + K*df) + K * (dc + ushift)  # - Force_σ
      rhs = - (M*am + C*vf + K*df)
      A = (1-αm)*M + (1-αf)*C*dt*γ + (1-αf)*K*β*dt^2

      if !ismissing(solve)
        return solve(A, rhs)
      else
        return A\rhs
      end
    end

    function condition(i, tas...)
      return i<=n_-1
    end
    function body(i, tas...)
      dc_arr, vc_arr, ac_arr, σ_arr, ε_arr = tas
      dc = read(dc_arr, i)
      vc = read(vc_arr, i)
      ac = read(ac_arr, i)
      σc = read(σ_arr, i)
      εc = read(ε_arr, i)
      y = equ(dc, vc, ac, σc, εc, Δt[i], Force[i])
      dn = dc + Δt[i]*vc + Δt[i]^2/2*((1-2β)*ac+2β*y)
      vn = vc + Δt[i]*((1-γ)*ac+γ*y)
      εnew = eval_strain_on_gauss_pts1(dn + ushift, m, n, h)
      σnew = antiplane_viscosity((εnew-εc)/Δt[i], σc, μ, η, Δt[i])
      # σnew = 2*(εnew-εc)/dt
      i+1, write(dc_arr, i+1, dn), write(vc_arr, i+1, vn),
          write(ac_arr, i+1, y), write(σ_arr, i+1, σnew),
          write(ε_arr, i+1, εnew)
    end

    dM = TensorArray(n_); vM = TensorArray(n_);
    aM = TensorArray(n_); σM = TensorArray(n_)
    εM = TensorArray(n_)
    dM = write(dM, 1, d0)
    vM = write(vM, 1, v0)
    aM = write(aM, 1, a0)
    σM = write(σM, 1, constant(zeros(4*m*n,2)))
    εM = write(εM, 1, constant(zeros(4*m*n,2)))
    i = constant(1, dtype=Int32)
    _, d, v, a = while_loop(condition, body, [i,dM, vM, aM, σM, εM])
    stack(d), stack(v), stack(a)
end

d, v, a = αintegration_visco(M, C, K, Force, d0, v0, a0, Δt; solve = solver)

# Simulation
sess = Session()
d_, v_, a_ = run(sess, [d, v, a])
# visualize_potential(permutedims(reshape(d_, NT, m+1, n+1), [1,3,2])[:,1:n,1:m], m, n, h)

# close("all")
# for α in [0.25, 0.5, 0.75, 1.0]
#   idx = Int64(round(α/dt))
#   @info idx
#   t = α*tR
#   # κ = 2.
#   # plot((0:m)*h, erfc.((0:m)*h/2/√t/√κ))
#   plot((0:m)*h, d_[idx,  1:m+1], "+--", label="\$t/T=$α\$")
# end
# xlim(0, 5.0)
# legend()

plot(d_[:,1:m+1])
pcolormesh(reshape(d_[end,:], m+1, n+1)')

max_stars_repo_name: ADCMEMarket/ADCMEImages

max_issues_repo_name: ADCMEMarket/ADCMEImages

max_forks_repo_name: ADCMEMarket/ADCMEImages


text:
using JAC: HalfInt
using JAC.AngularMomentum: clebschgordan, wigner3j, wigner6j, wigner9j

@testset "Wigner symbols" begin
    @testset "clebschgordan" begin
        @test iszero(clebschgordan(1, 0, 1, 0, 1/2, 0))
        @test iszero(clebschgordan(1, 0, 1, 0, 1, 1))
        @test clebschgordan(5/2, 3/2, 0, 0, 5//2, 3//2) ≈ 1
        @test clebschgordan(AngularJ64(5//2), AngularM64(3//2),
                            AngularJ64(0),    AngularM64(0),
                            AngularJ64(5//2), AngularM64(3//2)) ≈ 1
        @test clebschgordan(1/2,  1/2, 1/2,  1/2, 1,  1) ≈ 1
        @test clebschgordan(1/2,  1/2, 1/2, -1/2, 1,  0) ≈ √(1/2)
        @test clebschgordan(1/2, -1/2, 1/2,  1/2, 1,  0) ≈ √(1/2)
        @test clebschgordan(1/2, -1/2, 1/2, -1/2, 1, -1) ≈ 1
        @test clebschgordan(1/2,  1/2, 1/2, -1/2, 0,  0) ≈ √(1/2)
        @test clebschgordan(1/2, -1/2, 1/2,  1/2, 0,  0) ≈ -√(1/2)
        @test clebschgordan(3/2, -1/2, 2, 1, 7/2,  1/2) ≈ √(12/35)
        @test clebschgordan(3/2, -1/2, 2, 1, 5/2,  1/2) ≈ -√(5/14)
        @test clebschgordan(3/2, -1/2, 2, 1, 3/2,  1/2) ≈ 0
        @test clebschgordan(3/2, -1/2, 2, 1, 1/2,  1/2) ≈ √(3/10)
        @test clebschgordan(2,  2, 3/2, -3/2, 7/2,  1/2) ≈ √(1/35)
        @test clebschgordan(2,  2, 3/2, -3/2, 5/2,  1/2) ≈ √(6/35)
        @test clebschgordan(2,  2, 3/2, -3/2, 3/2,  1/2) ≈ √(2/5)
        @test clebschgordan(2,  2, 3/2, -3/2, 1/2,  1/2) ≈ √(2/5)
        @test clebschgordan(2,  1, 3/2, -1/2, 7/2,  1/2) ≈ √(12/35)
        @test clebschgordan(2,  1, 3/2, -1/2, 5/2,  1/2) ≈ √(5/14)
        @test clebschgordan(2,  1, 3/2, -1/2, 3/2,  1/2) ≈ 0
        @test clebschgordan(2,  1, 3/2, -1/2, 1/2,  1/2) ≈ -√(3/10)
        @test clebschgordan(2,  0, 3/2,  1/2, 7/2,  1/2) ≈ √(18/35)
        @test clebschgordan(2,  0, 3/2,  1/2, 5/2,  1/2) ≈ -√(3/35)
        @test clebschgordan(2,  0, 3/2,  1/2, 3/2,  1/2) ≈ -√(1/5)
        @test clebschgordan(2,  0, 3/2,  1/2, 1/2,  1/2) ≈ √(1/5)
        @test clebschgordan(2, -1, 3/2,  3/2, 7/2,  1/2) ≈ √(4/35)
        @test clebschgordan(2, -1, 3/2,  3/2, 5/2,  1/2) ≈ -√(27/70)
        @test clebschgordan(2, -1, 3/2,  3/2, 3/2,  1/2) ≈ √(2/5)
        @test clebschgordan(2, -1, 3/2,  3/2, 1/2,  1/2) ≈ -√(1/10)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 5,  0) ≈ √(25/252)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 4,  0) ≈ √(9/28)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 3,  0) ≈ √(49/180)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 2,  0) ≈ √(1/84)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 1,  0) ≈ -√(9/70)
        @test clebschgordan(5/2,  3/2, 5/2, -3/2, 0,  0) ≈ -√(1/6)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 5,  0) ≈ √(25/252)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 4,  0) ≈ -√(9/28)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 3,  0) ≈ √(49/180)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 2,  0) ≈ -√(1/84)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 1,  0) ≈ -√(9/70)
        @test clebschgordan(5/2, -3/2, 5/2,  3/2, 0,  0) ≈ √(1/6)
        # Negative numbers as arguments for J
        @info "The following 20 warnings (\"GSL Error 1\") are expected (testing error handling)"
        @test_throws DomainError clebschgordan(-5/2, 3/2, 0, 0, 5/2, 3/2)
        @test_throws DomainError clebschgordan(0, 0, -5/2, 3/2, 5/2, 3/2)
        # In the following case, GSL.jl does not print a warning since sqrt(-4.0) throws a
        # DomainError before wigner3j is called
        @test_throws DomainError clebschgordan(0, 0, 5/2, 3/2, -5/2, 3/2)
        # Arguments that are not half-integers
        @test_throws InexactError clebschgordan(5/3, 3/2, 0, 0, 5/2, 3/2)
        @test_throws InexactError clebschgordan(5/2, 4/3, 0, 0, 5/2, 3/2)
        @test_throws InexactError clebschgordan(0, 0, 5/3, 3/2, 5/2, 3/2)
        @test_throws InexactError clebschgordan(0, 0, 5/2, 4/3, 5/2, 3/2)
        @test_throws InexactError clebschgordan(5/3, 3/2, 0, 0, 5/3, 3/2)
        @test_throws InexactError clebschgordan(5/2, 4/3, 0, 0, 5/2, 4/3)
    end

    @testset "wigner3j" begin
        @test wigner3j(AngularJ64(2), AngularJ64(6), AngularJ64(4),
                       AngularM64(0), AngularM64(0), AngularM64(0)) ≈ sqrt(5/143)
        @test wigner3j(AngularJ64(2), AngularJ64(6), AngularJ64(4),
                       AngularM64(0), AngularM64(0), AngularM64(1)) == 0
        @test wigner3j(AngularJ64(2), AngularJ64(7), AngularJ64(4),
                       AngularM64(0), AngularM64(0), AngularM64(0)) == 0
        @test wigner3j(AngularJ64(3//2), AngularJ64(1), AngularJ64(5//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -sqrt(1/10)
        @test wigner3j(AngularJ64(5//2), AngularJ64(1), AngularJ64(5//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ sqrt(1/210)
        @test wigner3j(AngularJ64(3//2), AngularJ64(0), AngularJ64(3//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ 1/2
        @test wigner3j(AngularJ64(3//2), AngularJ64(2), AngularJ64(3//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -sqrt(1/20)
        @test wigner3j(AngularJ64(7//2), AngularJ64(2), AngularJ64(5//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -sqrt(1/210)
        @test wigner3j(AngularJ64(7//2), AngularJ64(4), AngularJ64(5//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ sqrt(5/462)
        @test wigner3j(AngularJ64(7//2), AngularJ64(6), AngularJ64(5//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -5*sqrt(1/858)
        @test wigner3j(AngularJ64(7//2), AngularJ64(0), AngularJ64(7//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ 1/2*sqrt(1/2)
        @test wigner3j(AngularJ64(7//2), AngularJ64(2), AngularJ64(7//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -1/2*sqrt(5/42)
        @test wigner3j(AngularJ64(7//2), AngularJ64(4), AngularJ64(7//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ 3/2*sqrt(1/154)
        @test wigner3j(AngularJ64(7//2), AngularJ64(6), AngularJ64(7//2),
                       AngularM64(1//2), AngularM64(0), AngularM64(-1//2)) ≈ -5/2*sqrt(1/858)
        @test wigner3j(2, 6, 4, 0, 0, 0) ≈ sqrt(5/143)
        @test wigner3j(HalfInt(3/2), HalfInt(1), HalfInt(5/2), 1//2, 0, -1/2) ≈ -sqrt(1/10)
        @test wigner3j(3/2, 1, 5/2, 1/2, 0, -1/2) ≈ -sqrt(1/10)
        # Negative numbers as arguments for J
        @test_throws DomainError wigner3j(-3/2, 1, 5/2, 1//2, 0, -1/2)
        @test_throws DomainError wigner3j(3/2, -1, 5/2, 1//2, 0, -1/2)
        @test_throws DomainError wigner3j(3/2, 1, -5/2, 1//2, 0, -1/2)
        # Arguments that are not half-integers
        @test_throws InexactError wigner3j(4/3, 1, 5/2, 1//2, 0, -1/2)
        @test_throws InexactError wigner3j(3/2, 1.1, 5/2, 1//2, 0, -1/2)
        @test_throws InexactError wigner3j(3/2, 1, 5/3, 1//2, 0, -1/2)
        @test_throws InexactError wigner3j(3/2, 1, 5/2, 1//3, 0, -1/2)
        @test_throws InexactError wigner3j(3/2, 1, 5/2, 1//2, 0.1, -1/2)
        @test_throws InexactError wigner3j(3/2, 1, 5/2, 1//2, 0, -1/5)
    end

    @testset "wigner6j" begin
        @test wigner6j(AngularJ64(3), AngularJ64(3), AngularJ64(3),
                       AngularJ64(3), AngularJ64(3), AngularJ64(3)) ≈ -1/14
        @test wigner6j(AngularJ64(5), AngularJ64(5), AngularJ64(5),
                       AngularJ64(5), AngularJ64(5), AngularJ64(5)) ≈ 1/52
        @test wigner6j(AngularJ64(1), AngularJ64(3//2), AngularJ64(5//2),
                       AngularJ64(0), AngularJ64(5//2), AngularJ64(3//2)) ≈ -sqrt(1/24)
        @test wigner6j(1, 3/2, 5/2, 0, 5/2, 3/2) ≈ -sqrt(1/24)
        @test wigner6j(HalfInt(1), HalfInt(3/2), HalfInt(5/2), 0, 5//2, 3/2) ≈ -sqrt(1/24)
        # Negative numbers as arguments
        @test_throws DomainError wigner6j(-1, 3/2, 5/2, 0, 5//2, 3/2)
        @test_throws DomainError wigner6j(1, -3/2, 5/2, 0, 5//2, 3/2)
        @test_throws DomainError wigner6j(1, 3/2, -5/2, 0, 5//2, 3/2)
        @test_throws DomainError wigner6j(3/2, 5/2, 1, -5//2, 3/2, 0)
        @test_throws DomainError wigner6j(1, 3/2, 5/2, 0, -5//2, 3/2)
        @test_throws DomainError wigner6j(1, 3/2, 5/2, 0, 5//2, -3/2)
        # Arguments that are not half-integers
        @test_throws InexactError wigner6j(1.1, 3/2, 5/2, 0, 5//2, 3/2)
        @test_throws InexactError wigner6j(1, 4/3, 5/2, 0, 5//2, 3/2)
        @test_throws InexactError wigner6j(1, 3/2, 5/3, 0, 5//2, 3/2)
        @test_throws InexactError wigner6j(1, 3/2, 5/2, 0.1, 5//2, 3/2)
        @test_throws InexactError wigner6j(1, 3/2, 5/2, 0, 5//3, 3/2)
        @test_throws InexactError wigner6j(1, 3/2, 5/2, 0, 5//2, 4/3)
    end

    @testset "wigner9j" begin
        @test wigner9j(AngularJ64(1), AngularJ64(1), AngularJ64(1),
                       AngularJ64(1), AngularJ64(1), AngularJ64(1),
                       AngularJ64(1), AngularJ64(1), AngularJ64(0)) ≈ 1/18
        @test wigner9j(AngularJ64(1),    AngularJ64(3//2), AngularJ64(5//2),
                       AngularJ64(5//2), AngularJ64(0),    AngularJ64(5//2),
                       AngularJ64(3//2), AngularJ64(3//2), AngularJ64(0)) ≈ -1/24
        @test wigner9j(AngularJ64(1//2), AngularJ64(1//2), AngularJ64(1),
                       AngularJ64(3),    AngularJ64(3),    AngularJ64(2),
                       AngularJ64(5//2), AngularJ64(5//2), AngularJ64(1)) ≈ (1/21)*sqrt(2/5)
        @test wigner9j(1, 1, 1, 1, 1, 1, 1, 1, 0) ≈ 1/18
        @test wigner9j(1, AngularJ64(1), HalfInt(1), 1//1, 1.0, 1, 1, 1, 0) ≈ 1/18
        # Negative numbers as arguments
        @test_throws DomainError wigner9j(-1, 1, HalfInt(1), 1//1, 1.0, 1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, -1, HalfInt(1), 1//1, 1.0, 1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(-1), 1//1, 1.0, 1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), -1//1, 1.0, 1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), 1//1, -1.0, 1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, -1, 1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, -1, 1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, 1, -1, 0)
        @test_throws DomainError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, 1, 1, -1)
        # Arguments that are not half-integers
        @test_throws InexactError wigner9j(1.1, 1, HalfInt(1), 1//1, 1.0, 1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1.1, HalfInt(1), 1//1, 1.0, 1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1, 1.1, 1//1, 1.0, 1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//3, 1.0, 1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//1, 1.6, 1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1.1, 1, 1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, 1.2, 1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, 1, 1.1, 0)
        @test_throws InexactError wigner9j(1, 1, HalfInt(1), 1//1, 1.0, 1, 1, 1.3, 0.01)
    end
end


text:
module LibCImGui

using CImGuiPack_jll
export CImGuiPack_jll

const IS_LIBC_MUSL = occursin("musl", Base.BUILD_TRIPLET)
if Sys.isapple() && Sys.ARCH === :aarch64
    include("../lib/aarch64-apple-darwin20.jl")
elseif Sys.islinux() && Sys.ARCH === :aarch64 && !IS_LIBC_MUSL
    include("../lib/aarch64-linux-gnu.jl")
elseif Sys.islinux() && Sys.ARCH === :aarch64 && IS_LIBC_MUSL
    include("../lib/aarch64-linux-musl.jl")
elseif Sys.islinux() && startswith(string(Sys.ARCH), "arm") && !IS_LIBC_MUSL
    include("../lib/armv7l-linux-gnueabihf.jl")
elseif Sys.islinux() && startswith(string(Sys.ARCH), "arm") && IS_LIBC_MUSL
    include("../lib/armv7l-linux-musleabihf.jl")
elseif Sys.islinux() && Sys.ARCH === :i686 && !IS_LIBC_MUSL
    include("../lib/i686-linux-gnu.jl")
elseif Sys.islinux() && Sys.ARCH === :i686 && IS_LIBC_MUSL
    include("../lib/i686-linux-musl.jl")
elseif Sys.iswindows() && Sys.ARCH === :i686
    include("../lib/i686-w64-mingw32.jl")
elseif Sys.islinux() && Sys.ARCH === :powerpc64le
    include("../lib/powerpc64le-linux-gnu.jl")
elseif Sys.isapple() && Sys.ARCH === :x86_64
    include("../lib/x86_64-apple-darwin14.jl")
elseif Sys.islinux() && Sys.ARCH === :x86_64 && !IS_LIBC_MUSL
    include("../lib/x86_64-linux-gnu.jl")
elseif Sys.islinux() && Sys.ARCH === :x86_64 && IS_LIBC_MUSL
    include("../lib/x86_64-linux-musl.jl")
elseif Sys.isbsd() && !Sys.isapple()
    include("../lib/x86_64-unknown-freebsd11.1.jl")
elseif Sys.iswindows() && Sys.ARCH === :x86_64
    include("../lib/x86_64-w64-mingw32.jl")
else
    error("Unknown platform: $(Base.BUILD_TRIPLET)")
end

# exports
const PREFIXES = ["ig", "Im", "IMGUI_", "imnodes_", "ImPlot_", "ImVector_"]
for name in names(@__MODULE__; all=true), prefix in PREFIXES
    if startswith(string(name), prefix)
        @eval export $name
    end
end

end


text:
using StringParserPEG

calc1 = Grammar("""
  start => (number & op & number) {"start"}

  op => (plus | minus) {"op"}
  number => (-(space) & r([0-9]+)r) {"number"}
  plus => (-(space) & '+') {"plus"}
  minus => (-(space) & '-') {"minus"}
  space => r([ \\t\\n\\r]*)r
""")
toresult(node,children,::MatchRule{:default}) = node.value
toresult(node,children,::MatchRule{:number}) = parse(Int,node.value)
toresult(node,children,::MatchRule{:plus}) = +
toresult(node,children,::MatchRule{:minus}) = -
toresult(node,children,::MatchRule{:start}) = children[2](children[1],children[3])

data = "4+5"

(ast, pos, err) = parse(calc1, data)
transformed = transform(toresult,ast)
transformed


text:
module UnitfulBuckinghamPi

using Unitful
using LinearAlgebra

export @setparameters, @addparameters, pi_groups

"""
    param_simbols = Vector{Symbol}()

Vector containing the list of symbols of the registered parameters.
"""
param_symbols = Vector{Symbol}()

"""
    param_values = Vector{Union{Unitful.Quantity, Unitful.FreeUnits, Unitful.Dimensions, Number}}()

Vector containing the list of values of the registered parameters.
"""
param_values = Vector{Union{Unitful.Quantity, Unitful.FreeUnits, Unitful.Dimensions, Number}}()

"""
    clearregister()

Clear the parameter register.
"""
function clearregister()
    intersect!(param_symbols, Vector{Symbol}())
    intersect!(param_values, Vector{Union{Unitful.Quantity, Unitful.FreeUnits, Unitful.Dimensions, Number}}())
end

"""
    addparameter(x, y)

Add parameter with symbol `x` and value `y` to the register.
"""
function addparameter(x,y)
    y isa Union{Unitful.Quantity, Unitful.FreeUnits, Unitful.Dimensions, Number} ||
        throw(ArgumentError(
            "Parameter should be either a Unitful.Quantity, Unitful.FreeUnits,"
            * "Unitful.Dimensions or Number"))

    if x ∉ UnitfulBuckinghamPi.param_symbols
        push!(param_symbols, x)
        push!(param_values, y)
    end
end

"""
    @setparameters args...

Register a list of parameters.

The parameters should be of any of following types:
    * Unitful.Quantity
    * Unitful.FreeUnits
    * Unitful.Dimensions
    * Number

# Examples

```jldoctest
julia> ℓ = u"m"; g = 9.8u"m/s^2"; m = u"g"; T = u"𝐓"; θ = u"NoDims";

julia> @setparameters ℓ g m τ θ
[ Info: Parameter(s) registered:
[ Info:  ℓ = m
[ Info:  g = 9.8 m s⁻²
[ Info:  m = g
[ Info:  τ = s
[ Info:  θ = NoDims
```
"""
macro setparameters(args...)
    quote
        $UnitfulBuckinghamPi.clearregister()
        $([:($UnitfulBuckinghamPi.addparameter($(Meta.quot(arg)), $(esc(arg))))
            for arg in args]...)
        $UnitfulBuckinghamPi.displayregister()
    end
end

"""
    @addparameters args...

Add a list of parameters to the register.

The parameters should be of any of following types:
    * Unitful.Quantity
    * Unitful.FreeUnits
    * Unitful.Dimensions
    * Number

# Examples

```jldoctest
julia> ℓ = u"m"; g = 9.8u"m/s^2"; m = u"g"; T = u"𝐓"; θ = u"NoDims";

julia> @setparameters ℓ g m
[ Info: Parameter(s) registered:
[ Info:  ℓ = m
[ Info:  g = 9.8 m s⁻²
[ Info:  m = g

julia> @addparameters T θ
[ Info: Parameter(s) registered:
[ Info:  ℓ = m
[ Info:  g = 9.8 m s⁻²
[ Info:  m = g
[ Info:  T = 𝐓
[ Info:  θ = NoDims
```
"""
macro addparameters(args...)
    quote
        $([:($UnitfulBuckinghamPi.addparameter($(Meta.quot(arg)), $(esc(arg)))) for arg in args]...)
        $UnitfulBuckinghamPi.displayregister()
    end
end

"""
    displayregister()

Display info with the list of registered parameters.
"""
function displayregister()
    @info "Parameter(s) registered:"
    for (n, v) in zip(param_symbols, param_values)
        @info " $n = $v"
    end
end

"""
    param_dimensions(x)

Return name, abbreviation and power of the dimensions of the given argument `x`.

The argument `x` can be a `Uniftul.Quantity`, a `Unitful.FreeUnits`,
a `Unitful.Dimensions` or a `Number`.
"""
function param_dimensions(::Unitful.Dimensions{D}) where {D}
    return [(Unitful.name(z), Unitful.abbr(z), Unitful.power(z)) for z in D]
end
param_dimensions(u::Unitful.FreeUnits) = param_dimensions(dimension(u))
param_dimensions(q::Unitful.Quantity) = param_dimensions(dimension(q))
param_dimensions(x::Number) = param_dimensions(dimension(x))

"""
    parameterdimensionmatrix()

Build and return the parameter-to-dimension matrix.
"""
function parameterdimensionmatrix()
    dims = Set(dims[2] for p in param_values for dims in param_dimensions(p))
    dims_dict = Dict(v => i for (i,v) in enumerate(dims))
    pdmat = fill(0//1, length(dims), length(param_values))
    for (j,p) in enumerate(param_values)
        for d in param_dimensions(p)
            pdmat[dims_dict[d[2]],j] = d[3]
        end
    end
    return pdmat
end

"""
    lu_pq(A::AbstractMatrix)

Compute the LU factorization of `A` with full pivoting.

Output is a `NamedTuple`, say `F=lu_pq(A)`, whose fields are
* `F.L`: `L` (lower triangular) part of the factorization
* `F.U`: `U` (upper triangular) part of the factorization
* `p`: row permutation `Vector`
* `q`: column permutation `Vector`

Factorization yields the identity `F.L * F.U == A[F.p, F.q]`.

More information about LU factorization with full pivoting,
see [^GolubVanLoan1996], [^TrefethenBauIII1997].

The choice of the tolerance, however, is beyond me, at the moment,
but see [^issue8859] and [^pinv]

# Examples

```jldoctest
julia> A = [4 3; 6 3]
2×2 Matrix{Int64}:
 4  3
 6  3

julia> F = lu_pq(A)
(L = [1.0 0.0; 0.6666666666666666 1.0], U = [6.0 3.0; 0.0 1.0], p = [2, 1], q = [1, 2])

julia> F.L * F.U == A[F.p, F.q]
true

julia> L, U, p, q = lu_pq(A)
(L = [1.0 0.0; 0.6666666666666666 1.0], U = [6.0 3.0; 0.0 1.0], p = [2, 1], q = [1, 2])

julia> L * U == A[p, q]
true

julia> A = reshape(collect(1:12),3,4)
3×4 Matrix{Int64}:
 1  4  7  10
 2  5  8  11
 3  6  9  12

julia> L, U, p, q = lu_pq(A)
(L = [1.0 0.0 0.0; 0.8333333333333334 1.0 0.0; 0.9166666666666666 0.5 1.0], U = [12.0 3.0 9.0 6.0; 0.0 -1.5 -0.5 -1.0; 0.0 0.0 0.0 0.0], p = [3, 1, 2], q = [4, 1, 3, 2])

julia> L * U == A[p, q]
true

julia> rank(A) == rank(U) == 2
true

julia> A = convert.(Rational, reshape(collect(1:12),3,4))
3×4 Matrix{Rational{Int64}}:
 1//1  4//1  7//1  10//1
 2//1  5//1  8//1  11//1
 3//1  6//1  9//1  12//1

julia> L, U, p, q = lu_pq(A);

julia> U
3×4 Matrix{Rational{Int64}}:
 12//1   3//1   9//1   6//1
  0//1  -3//2  -1//2  -1//1
  0//1   0//1   0//1   0//1

julia> A = complex(reshape(collect(1.0:12.0),3,4))
3×4 Matrix{ComplexF64}:
 1.0+0.0im  4.0+0.0im  7.0+0.0im  10.0+0.0im
 2.0+0.0im  5.0+0.0im  8.0+0.0im  11.0+0.0im
 3.0+0.0im  6.0+0.0im  9.0+0.0im  12.0+0.0im

julia> L, U, p, q = lu_pq(A);

julia> U
3×4 Matrix{ComplexF64}:
 12.0+0.0im   3.0+0.0im           9.0+0.0im   6.0+0.0im
  0.0+0.0im  -1.5+0.0im          -0.5+0.0im  -1.0+0.0im
  0.0+0.0im   0.0+0.0im  -4.44089e-16+0.0im   0.0+0.0im

julia> L * U == A[p, q]
true

julia> A = [1 1; typemax(Int64)//2 1]
2×2 Matrix{Rational{Int64}}:
                   1//1  1//1
 9223372036854775807//2  1//1

julia> L, U, p, q = lu_pq(A);

julia> U
2×2 Matrix{Rational{Int64}}:
 9223372036854775807//2                    1//1
                   0//1  9223372036854775805//9223372036854775807

julia> L * U == A[p, q]
true
```

# References:

[^GolubVanLoan1996]: Gene H. Golub, Charles F. Van Loan, "Matrix Computations", Johns Hopkins
Studies in Mathematical Sciences, 3rd Edition, 1996.

[^TrefethenBauIII1997]: Lloyd N. Trefethen, David Bau III, "Numerical Linear Algebra",
First Edition, SIAM, 1997.

[^issue8859]: Issue 8859, "Fix least squares", [https://github.com/JuliaLang/julia/pull/8859](https://github.com/JuliaLang/julia/pull/8859)

[^pinv]: [LinearAlgebra.pinv](https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/dense.jl#L1362)
"""
function lu_pq(A::AbstractMatrix{T}) where T <: Number
    tol = T <: Rational ? 0//1 : min(size(A)...)*eps(real(float(one(T))))
    U = copy(A)
    (n,m) = size(U)
    L = diagm(ones(eltype(A),n))
    p = collect(1:n)
    q = collect(1:m)
    for k =1:min(n,m)
        i, j = k-1 .+ Tuple(argmax(abs.(U[k:end,k:end])))
        abs(U[i,j]) > tol || break
        if i > k
            p[k], p[i] = p[i], p[k]
            U[k,:], U[i,:] = U[i,:], U[k,:]
            L[k,1:k-1], L[i,1:k-1] = L[i,1:k-1], L[k,1:k-1]
        end
        if j > k
            q[k], q[j] = q[j], q[k]
            U[:,k], U[:,j] = U[:,j], U[:,k]
        end
        τ = U[k+1:end,k] / U[k,k]
        U[k+1:end,k:end] -=  τ * U[k,k:end]'
        L[k+1:end,k] = τ
    end
    return (L=L, U=U, p=p, q=q)
end
lu_pq(A::AbstractMatrix{T}) where T <: Integer = lu_pq(float(A))
lu_pq(A::AbstractMatrix{Complex{T}}) where T <: Integer = lu_pq(convert.(float(Complex{Int}),A))

"""
    lu_nullspace(mat)

Return a matrix whose columns span the null space of the matrix `mat`.

If `mat` has full rank, the returned matrix has zero columns.

The algorithm uses the implementation [`lu_pq`](@ref) of the LU decomposition
with full pivoting. This decomposition not only retains the Rational
eltype of the matrix, but also handles singular matrix.
"""
function lu_nullspace(mat)
    function ivec(n,i)
        ohv = fill(zero(eltype(mat)), n)
        ohv[i] = one(eltype(mat))
        return ohv
    end
    mat_lu = lu_pq(mat)
    mat_nrows, mat_ncols = size(mat)
    mat_rank = rank(mat)
    mat_null = fill(zero(eltype(mat)), mat_ncols, mat_ncols - mat_rank)
    for j in 1:mat_ncols-mat_rank
        mat_null[1:mat_rank,j] = -(mat_lu.U[:,1:mat_rank] \ (mat_lu.U * ivec(mat_ncols, mat_rank+j)))
        mat_null[mat_rank+j,j] = one(eltype(mat))
    end
    return mat_null, mat_lu.q
end

"""
    pi_groups(type::Symbol = :Expr)

Return a vector with the Pi groups associated with the registered parameters.

The returned vector can be of one of the following eltypes depending
on the value of the argument `type`:
    * eltype `Expr`, if `type` is set to `Expr`
    * eltype `String`, if `type` is set to `:String`

# Examples

```jldoctest
julia> ℓ = u"m"; g = 9.8u"m/s^2"; m = u"g"; τ = u"s"; θ = u"NoDims";

julia> ℓ = u"m"; g = 9.8u"m/s^2"; m = u"g"; τ = u"s"; θ = u"NoDims";

julia> @setparameters ℓ g m τ θ
[ Info: Parameter(s) registered:
[ Info:  ℓ = m
[ Info:  g = 9.8 m s⁻²
[ Info:  m = g
[ Info:  τ = s
[ Info:  θ = NoDims

julia> pi_groups()
2-element Vector{Expr}:
 :(g ^ (1 // 2) * ℓ ^ (-1 // 2) * τ ^ (1 // 1))
 :(θ ^ (1 // 1))

julia> pi_groups(:Expr)
 2-element Vector{Expr}:
  :(g ^ (1 // 2) * ℓ ^ (-1 // 2) * τ ^ (1 // 1))
  :(θ ^ (1 // 1))

julia> pi_groups(:String)
2-element Vector{String}:
  "g^(1//2)*ℓ^(-1//2)*τ^(1//1)"
  "θ^(1//1)"
```
"""
function pi_groups(type::Symbol = :Expr)
    pdmat = parameterdimensionmatrix()
    pdmat_null, q = lu_nullspace(pdmat)
    groups = [join(["$p^($a)" for (p,a) in zip(param_symbols[q], col) if !iszero(a)], "*") for col in eachcol(pdmat_null)]
    type == :String && return groups
    type == :Expr && return [Meta.parse(group) for group in groups]
    throw(
        ArgumentError(
            "Type $type not implemented. Choose between `:Expr` and `:String`"
        )
    )
end

end # module

max_stars_repo_name: rmsrosa/UnitfulBuckinghamPi

max_issues_repo_name: rmsrosa/UnitfulBuckinghamPi

max_forks_repo_name: rmsrosa/UnitfulBuckinghamPi


text:
using Cribbage

xs = all_hands(score)

maximum(xs)

count(x->x==29, xs)
count(x->x==28, xs)
count(x->x==27, xs)
count(x->x==26, xs)
count(x->x==25, xs)
count(x->x==24, xs)

using Plots

histogram(xs,
    )


text:
using Test
using LogicCircuits
using ProbabilisticCircuits

function test_equal(c1::LogicCircuit, c2::LogicCircuit)
    result = true
    for (n1, n2) in zip(linearize(c1), linearize(c2))
        if is⋁gate(n1)
            @test is⋁gate(n2)
            @test all(params(n1) ≈ params(n2))
        elseif is⋀gate(n1)
            result = result
            @test is⋀gate(n2)
        else
            @test isliteralgate(n1)
            @test isliteralgate(n2)
            @test literal(n1) == literal(n2)
        end
    end
    result
end

@testset "Circuit saver test" begin
    mktempdir() do tmp

        circuit, vtree = load_struct_prob_circuit(
                            zoo_psdd_file("little_4var.psdd"), zoo_vtree_file("little_4var.vtree"))

        # load, save, and load as .psdd
        @test_nowarn save_circuit("$tmp/temp.psdd", circuit, vtree)
        @test_nowarn save_vtree("$tmp/temp.vtree", vtree);

        circuit2, vtree2 = load_struct_prob_circuit("$tmp/temp.psdd", "$tmp/temp.vtree")
        test_equal(circuit, circuit2)

        f_c, f_v = open("$tmp/temp.psdd", "r"), open("$tmp/temp.vtree", "r")
        circuit2, _ = load_struct_prob_circuit(f_c, f_v)
        test_equal(circuit, circuit2)
        close(f_c); close(f_v)

        f = open("$tmp/temp.psdd", "w")
        @test_nowarn save_as_psdd(f, circuit, vtree)
        close(f)
        circuit2, _ = load_struct_prob_circuit("$tmp/temp.psdd", "$tmp/temp.vtree")
        test_equal(circuit, circuit2)

        # save and load as .sdd
        @test_nowarn save_circuit("$tmp/temp.sdd", PlainStructLogicCircuit(circuit), vtree)
        @test_nowarn save_vtree("$tmp/temp.vtree", vtree)

        @test_nowarn save_as_tex("$tmp/temp.tex", circuit)
        @test_nowarn save_as_dot("$tmp/temp.tex", circuit)
        @test_nowarn plot(circuit)
        @test_nowarn plot(vtree)

        # psdd2
        v = Vtree(5, :balanced)
        c = fully_factorized_circuit(ProbCircuit, v).children[1]
        @test_nowarn save_circuit("$tmp/temp.psdd", c, v)
        @test_nowarn save_vtree("$tmp/temp.vtree", v);
        c2, v2 = load_struct_prob_circuit("$tmp/temp.psdd", "$tmp/temp.vtree")
        test_equal(c, c2)
    end

    mktempdir() do tmp
        classes = 2
        lc1 = zoo_lc("little_4var.circuit", classes)
        @test_nowarn save_circuit("$tmp/temp.circuit", lc1, nothing)

        lc2 = load_logistic_circuit("$tmp/temp.circuit", classes)
        test_equal(lc1, lc2)
    end
end