text:
export
    dafac,
    dafbbs,
    dafbfs,
    dafcls,
    dafcs,
    dafdc,
    dafec,
    daffna,
    daffpa,
    dafgda,
    dafgh,
    dafgn,
    dafgs,
    dafgsr,
    dafopr,
    dafopw,
    dafps,
    dafrda,
    dafrfr,
    dafrs,
    dafus,
    dasac,
    dascls,
    dasdc,
    dasec,
    dashfn,
    dasopr,
    dasopw,
    dasrfr,
    dcyldr,
    deltet,
    dgeodr,
    diags2,
    diff,
    dlabbs,
    dlabfs,
    dlafns,
    dlafps,
    dlatdr,
    dp2hx,
    dpgrdr,
    dpmax,
    dpmin,
    dpr,
    drdcyl,
    drdgeo,
    drdlat,
    drdpgr,
    drdsph,
    dskb02,
    dskcls,
    dskd02,
    dskgd,
    dskgtl,
    dski02,
    dskmi2,
    dskn02,
    dskobj,
    dskobj!,
    dskopn,
    dskp02,
    dskrb2,
    dsksrf,
    dsksrf!,
    dskstl,
    dskv02,
    dskw02,
    dskx02,
    dskxsi,
    dskxv,
    dskz02,
    dsphdr,
    dtpool,
    ducrss,
    dvcrss,
    dvdot,
    dvhat,
    dvnorm,
    dvpool,
    dvsep

"""
    dafac(handle, buffer)

Add comments from a buffer of character strings to the comment area of a binary DAF file, appending
them to any comments which are already present in the file's comment area.

### Arguments ###

- `handle`: Handle of a DAF opened with write access
- `buffer`: Buffer of comments to put into the comment area

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafac_c.html)
"""
function dafac(handle, buffer)
    buffer_, n, lenvals = chararray(buffer)
    ccall((:dafac_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceChar}),
          handle, n, lenvals, buffer_)
    handleerror()
end

"""
    dafbbs(handle)

Begin a backward search for arrays in a DAF.

### Arguments ###

- `handle`: Handle of DAF to be searched

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafbbs_c.html)
"""
function dafbbs(handle)
    ccall((:dafbbs_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
end

"""
    dafbfs(handle)

Begin a forward search for arrays in a DAF.

### Arguments ###

- `handle`: Handle of DAF to be searched

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafbfs_c.html)
"""
function dafbfs(handle)
    ccall((:dafbfs_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
end

"""
    dafcls(handle)

Close the DAF associated with a given handle.

### Arguments ###

- `handle`: Handle of DAF to be closed

### Output ###

Returns the handle of the closed file.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafcls_c.html)
"""
function dafcls(handle)
    ccall((:dafcls_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
    handle
end

"""
    dafcs(handle)

Select a DAF that already has a search in progress as the one to continue searching.

### Arguments ###

- `handle`: Handle of DAF to continue searching

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafcs_c.html)
"""
function dafcs(handle)
    ccall((:dafcs_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
end

"""
    dafdc(handle)

Delete the entire comment area of a specified DAF file.

### Arguments ###

- `handle`: The handle of a binary DAF opened for writing

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafdc_c.html)
"""
function dafdc(handle)
    ccall((:dafdc_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
end

"""
    dafec(handle; bufsiz=256, lenout=1024)

Extract comments from the comment area of a binary DAF.

### Arguments ###

- `handle`: Handle of binary DAF opened with read access
- `bufsiz`: Maximum size, in lines, of buffer (default: 256)
- `lenout`: Length of strings in output buffer (default: 1024)

### Output ###

Returns a buffer where extracted comment lines are placed.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafec_c.html)
"""
function dafec(handle; bufsiz=256, lenout=1024)
    n = Ref{SpiceInt}()
    buffer = Array{SpiceChar}(undef, lenout, bufsiz)
    done = Ref{SpiceBoolean}()
    ccall((:dafec_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceInt}, Ref{SpiceChar}, Ref{SpiceBoolean}),
          handle, bufsiz, lenout, n, buffer, done)
    handleerror()
    output = chararray_to_string(buffer, n[])
    while !Bool(done[])
        buffer = Array{SpiceChar}(undef, lenout, bufsiz)
        ccall((:dafec_c, libcspice), Cvoid,
              (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceInt}, Ref{SpiceChar}, Ref{SpiceBoolean}),
              handle, bufsiz, lenout, n, buffer, done)
        handleerror()
        append!(output, chararray_to_string(buffer, n[]))
    end
    output
end

"""
    daffna()

Find the next (forward) array in the current DAF.

### Output ###

Returns `true` if an array was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/daffna_c.html)
"""
function daffna()
    found = Ref{SpiceBoolean}()
    ccall((:daffna_c, libcspice), Cvoid, (Ref{SpiceBoolean},), found)
    handleerror()
    Bool(found[])
end

"""
    daffpa()

Find the previous (backward) array in the current DAF.

### Output ###

Returns `true` if an array was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/daffpa_c.html)
"""
function daffpa()
    found = Ref{SpiceBoolean}()
    ccall((:daffpa_c, libcspice), Cvoid, (Ref{SpiceBoolean},), found)
    handleerror()
    Bool(found[])
end

"""
    dafgda(handle, start, stop)

Read the double precision data bounded by two addresses within a DAF.

### Arguments ###

- `handle`: Handle of a DAF
- `start, stop`: Initial, final address within file

### Output ###

Returns the data contained between `start` and `stop`.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafgda_c.html)
"""
function dafgda(handle, start, stop)
    data = Array{SpiceDouble}(undef, abs(stop - start) + 1)
    ccall((:dafgda_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceDouble}),
          handle, start, stop, data)
    handleerror()
    data
end

"""
    dafgh()

Return (get) the handle of the DAF currently being searched.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafgh_c.html)
"""
function dafgh()
    handle = Ref{SpiceInt}()
    ccall((:dafgh_c, libcspice), Cvoid, (Ref{SpiceInt},), handle)
    handleerror()
    handle[]
end

"""
    dafgn(lenout=128)

Return (get) the name for the current array in the current DAF.

### Arguments ###

- `lenout`: Length of array name string (default: 128)

### Output ###

Returns the name of the current array.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafgn_c.html)
"""
function dafgn(lenout=128)
    name = Array{SpiceChar}(undef, lenout)
    ccall((:dafgn_c, libcspice), Cvoid,
          (SpiceInt, Ref{SpiceChar}),
          lenout, name)
    handleerror()
    chararray_to_string(name)
end

"""
    dafgs(lenout=128)

Return (get) the summary for the current array in the current DAF.

### Arguments ###

- `lenout`: The maximum length of the summary array

### Output ###

Returns the summary for the current array.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafgs_c.html)
"""
function dafgs(lenout=128)
    lenout = clamp(lenout, lenout, 128)
    array = zeros(128)
    ccall((:dafgs_c, libcspice), Cvoid, (Ref{SpiceDouble},), array)
    handleerror()
    array[1:lenout]
end

"""

Read a portion of the contents of a summary record in a DAF file.

### Arguments ###

- `handle`: Handle of DAF
- `recno`: Record number
- `start`: First word to read from record
- `stop`: Last word to read from record

### Output ###

Returns the contents of the record or `nothing` if none was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafgsr_c.html)
"""
function dafgsr(handle, recno, start, stop)
    data = Array{SpiceDouble}(undef, (stop - start) + 1)
    found = Ref{SpiceBoolean}()
    ccall((:dafgsr_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, SpiceInt, Ref{SpiceDouble}, Ref{SpiceBoolean}),
          handle, recno, start, stop, data, found)
    handleerror()
    Bool(found[]) || return nothing
    data
end

"""
    dafopr(fname)

Open a DAF for subsequent read requests.

### Arguments ###

- `fname`: Name of DAF to be opened

### Output ###

Returns the handle assigned to DAF.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafopr_c.html)
"""
function dafopr(fname)
    handle = Ref{SpiceInt}()
    ccall((:dafopr_c, libcspice), Cvoid, (Cstring, Ref{SpiceInt}), fname, handle)
    handleerror()
    handle[]
end

"""
    dafopw(fname)

Open a DAF for subsequent write requests.

### Arguments ###

- `fname`: Name of DAF to be opened

### Output ###

Returns the handle assigned to DAF.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafopw_c.html)
"""
function dafopw(fname)
    handle = Ref{SpiceInt}()
    ccall((:dafopw_c, libcspice), Cvoid, (Cstring, Ref{SpiceInt}), fname, handle)
    handleerror()
    handle[]
end

"""
    dafps(dc, ic)

Pack (assemble) an array summary from its double precision and integer components.

### Arguments ###

- `dc`: Double precision components
- `ic`: Integer components

### Output ###

Returns the array summary.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafps_c.html)
"""
function dafps(dc, ic)
    nd = length(dc)
    ni = length(ic)
    len = nd + (ni - 1) ÷ 2 + 1
    ic_ = SpiceInt.(ic)
    sum = Array{SpiceDouble}(undef, len)
    ccall((:dafps_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, Ref{SpiceDouble}, Ref{SpiceInt}, Ref{SpiceDouble}),
          nd, ni, dc, ic_, sum)
    sum
end

@deprecate dafrda dafgda

"""
    dafrfr(handle, lenout=128)

Read the contents of the file record of a DAF.

### Arguments ###

- `handle`: Handle of an open DAF file
- `lenout`: Available room in the output string `ifname' (default: 128)

### Output ###

- `nd`: Number of double precision components in summaries
- `ni`: Number of integer components in summaries
- `ifname`: Internal file name
- `fward`: Forward list pointer
- `bward`: Backward list pointer
- `free`: Free address pointer

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafrfr_c.html)
"""
function dafrfr(handle, lenout=128)
    nd = Ref{SpiceInt}()
    ni = Ref{SpiceInt}()
    ifname = Array{SpiceChar}(undef, lenout)
    fward = Ref{SpiceInt}()
    bward = Ref{SpiceInt}()
    free = Ref{SpiceInt}()
    ccall((:dafrfr_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, Ref{SpiceInt}, Ref{SpiceInt}, Ref{SpiceChar},
           Ref{SpiceInt}, Ref{SpiceInt}, Ref{SpiceInt}),
          handle, lenout, nd, ni, ifname, fward, bward, free)
    handleerror()
    Int(nd[]), Int(ni[]), chararray_to_string(ifname), Int(fward[]), Int(bward[]), Int(free[])
end

"""
    dafrs(sum)

Change the summary for the current array in the current DAF.

### Arguments ###

- `sum`: New summary for current array

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafrs_c.html)
"""
function dafrs(sum)
    ccall((:dafrs_c, libcspice), Cvoid, (Ref{SpiceDouble},), sum)
    handleerror()
end

"""
    dafus(sum, nd, ni)

Unpack an array summary into its double precision and integer components.

### Arguments ###

- `sum`: Array summary
- `nd`: Number of double precision components
- `ni`: Number of integer components

### Output ###

- `dc`: Double precision components
- `ic`: Integer components

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dafus_c.html)
"""
function dafus(sum, nd, ni)
    dc = Array{SpiceDouble}(undef, nd)
    ic = Array{SpiceInt}(undef, ni)
    ccall((:dafus_c, libcspice), Cvoid,
         (Ref{SpiceDouble}, SpiceInt, SpiceInt, Ref{SpiceDouble}, Ref{SpiceInt}),
         sum, nd, ni, dc, ic)
    dc, Int.(ic)
end

"""
    dasac(handle, buffer)

Add comments from a buffer of character strings to the comment area of a binary DAS file, appending
them to any comments which are already present in the file's comment area.

### Arguments ###

- `handle`: Handle of a DAS opened with write access
- `buffer`: Buffer of comments to put into the comment area

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasac_c.html)
"""
function dasac(handle, buffer)
    buffer_, n, lenvals = chararray(buffer)
    ccall((:dasac_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceChar}),
          handle, n, lenvals, buffer_)
    handleerror()
end

"""
    dascls(handle)

Close the DAS associated with a given handle.

### Arguments ###

- `handle`: Handle of DAS to be closed

### Output ###

Returns the handle of the closed file.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dascls_c.html)
"""
function dascls(handle)
    ccall((:dascls_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
    handle
end

"""
    dasdc(handle)

Delete the entire comment area of a specified DAS file.

### Arguments ###

- `handle`: The handle of a binary DAS opened for writing

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasdc_c.html)
"""
function dasdc(handle)
    ccall((:dasdc_c, libcspice), Cvoid, (SpiceInt,), handle)
    handleerror()
end

"""
    dasec(handle; bufsiz=256, lenout=1024)

Extract comments from the comment area of a binary DAS.

### Arguments ###

- `handle`: Handle of binary DAS opened with read access
- `bufsiz`: Maximum size, in lines, of buffer (default: 256)
- `lenout`: Length of strings in output buffer (default: 1024)

### Output ###

Returns a buffer where extracted comment lines are placed.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasec_c.html)
"""
function dasec(handle; bufsiz=256, lenout=1024)
    n = Ref{SpiceInt}()
    buffer = Array{SpiceChar}(undef, lenout, bufsiz)
    done = Ref{SpiceBoolean}()
    ccall((:dasec_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceInt}, Ref{SpiceChar}, Ref{SpiceBoolean}),
          handle, bufsiz, lenout, n, buffer, done)
    handleerror()
    output = chararray_to_string(buffer, n[])
    while !Bool(done[])
        buffer = Array{SpiceChar}(undef, lenout, bufsiz)
        ccall((:dasec_c, libcspice), Cvoid,
              (SpiceInt, SpiceInt, SpiceInt, Ref{SpiceInt}, Ref{SpiceChar}, Ref{SpiceBoolean}),
              handle, bufsiz, lenout, n, buffer, done)
        handleerror()
        append!(output, chararray_to_string(buffer, n[]))
    end
    output
end

"""
    dashfn(handle, namelen=256)

Return the name of the DAS file associated with a handle.

### Arguments ###

- `handle`: Handle of a DAS file
- `namlen`: Length of output file name string (default: 256)

### Output ###

Returns the corresponding file name.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dashfn_c.html)
"""
function dashfn(handle, namelen=256)
    name = Array{SpiceChar}(undef, namelen)
    ccall((:dashfn_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, Ref{SpiceChar}),
          handle, namelen, name)
    handleerror()
    chararray_to_string(name)
end

"""
    dasopr(fname)

Open a DAS for subsequent read requests.

### Arguments ###

- `fname`: Name of DAS to be opened

### Output ###

Returns the handle assigned to DAS.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasopr_c.html)
"""
function dasopr(fname)
    handle = Ref{SpiceInt}()
    ccall((:dasopr_c, libcspice), Cvoid, (Cstring, Ref{SpiceInt}), fname, handle)
    handleerror()
    handle[]
end

"""
    dasopw(fname)

Open a DAS for subsequent write requests.

### Arguments ###

- `fname`: Name of DAS to be opened

### Output ###

Returns the handle assigned to DAS.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasopw_c.html)
"""
function dasopw(fname)
    handle = Ref{SpiceInt}()
    ccall((:dasopw_c, libcspice), Cvoid, (Cstring, Ref{SpiceInt}), fname, handle)
    handleerror()
    handle[]
end

"""
    dasrfr(handle, idwlen=128, ifnlen=256)

Read the contents of the file record of a DAS.

### Arguments ###

- `handle`: DAS file handle
- `idwlen`: Length of ID word string (default: 128)
- `ifnlen`: Length of internal file name string (default: 256)

### Output ###

- `idword`: ID word
- `ifname`: DAS internal file name
- `nresvr`: Number of reserved records in file
- `nresvc`: Number of characters in use in reserved records area
- `ncomr`: Number of comment records in file
- `ncomc`: Number of characters in use in comment area

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dasrfr_c.html)
"""
function dasrfr(handle, idwlen=128, ifnlen=256)
    idword = Array{SpiceChar}(undef, idwlen)
    ifname = Array{SpiceChar}(undef, ifnlen)
    nresvr = Ref{SpiceInt}()
    nresvc = Ref{SpiceInt}()
    ncomr = Ref{SpiceInt}()
    ncomc = Ref{SpiceInt}()
    ccall((:dasrfr_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt,
           Ref{SpiceChar}, Ref{SpiceChar}, Ref{SpiceInt}, Ref{SpiceInt},
           Ref{SpiceInt}, Ref{SpiceInt}),
          handle, idwlen, ifnlen, idword, ifname, nresvr, nresvc, ncomr, ncomc)
    handleerror()
    chararray_to_string(idword), chararray_to_string(ifname),
    Int(nresvr[]), Int(nresvc[]), Int(ncomr[]), Int(ncomc[])
end

"""
    dcyldr(x, y, z)

Compute the Jacobian of the transformation from rectangular to cylindrical coordinates.

### Arguments ###

- `x`: X-coordinate of point
- `y`: Y-coordinate of point
- `z`: Z-coordinate of point

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dcyldr_c.html)
"""
function dcyldr(x, y, z)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:dcyldr_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          x, y, z, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    deltet(epoch, eptype)

Return the value of ΔET (ET-UTC) for an input epoch.

### Arguments ###

- `epoch`: Input epoch (seconds past J2000)
- `eptype`: Type of input epoch ("UTC" or "ET")

### Output ###

Returns ΔET (ET-UTC) at input epoch.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/deltet_c.html)
"""
function deltet(epoch, eptype)
    delta = Ref{SpiceDouble}()
    ccall((:deltet_c, libcspice), Cvoid,
          (SpiceDouble, Cstring, Ref{SpiceDouble}),
          epoch, eptype, delta)
    handleerror()
    delta[]
end

"""
    dgeodr(x, y, z, re, f)

Compute the Jacobian of the transformation from rectangular to geodetic coordinates.

### Arguments ###

- `x`: X-coordinate of point
- `y`: Y-coordinate of point
- `z`: Z-coordinate of point
- `re`: Equatorial radius of the reference spheroid
- `f`: Flattening coefficient

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dgeodr_c.html)
"""
function dgeodr(x, y, z, re, f)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:dgeodr_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          x, y, z, re, f, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    diags2(symmat)

Diagonalize a symmetric 2x2 matrix.

### Arguments ###

- `symmat`: A symmetric 2x2 matrix

### Output ###

- `diag`: A diagonal matrix similar to `symmat`
- `rotate`: A rotation used as the similarity transformation

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/diags2_c.html)
"""
function diags2(symmat)
    @checkdims 2 2 symmat
    diag = Array{SpiceDouble}(undef, 2, 2)
    rotate = Array{SpiceDouble}(undef, 2, 2)
    ccall((:diags2_c, libcspice), Cvoid,
          (Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceDouble}),
          symmat, diag, rotate)
    permutedims(diag), permutedims(rotate)
end

"""
    diff(a::T, b::T) where T <: SpiceCell

Compute the difference of two sets of any data type to form a third set.

### Arguments ###

- `a`: First input set
- `b`: Second input set

### Output ###

Returns a cell containing the difference of `a` and `b`.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/diff_c.html)
"""
function Base.diff(a::SpiceCell{T}, b::SpiceCell{T}) where T
    size = max(a.cell.size, b.cell.size)
    if T <: SpiceChar
        length = max(a.cell.length, b.cell.length)
        out = SpiceCell{T}(size, length)
    else
        out = SpiceCell{T}(size)
    end
    a_data = a.data
    b_data = b.data
    out_data = out.data
    GC.@preserve a_data b_data out_data begin
        ccall((:diff_c, libcspice), Cvoid, (Ref{Cell{T}}, Ref{Cell{T}}, Ref{Cell{T}}),
              a.cell, b.cell, out.cell)
    end
    handleerror()
    out
end

"""
    dlabbs(handle)

Begin a backward segment search in a DLA file.

### Arguments ###

- `handle`: Handle of open DLA file

### Output ###

Returns the descriptor of the last segment in the DLA file or `nothing` if none was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dlabbs_c.html)
"""
function dlabbs(handle)
    descr = Ref{DLADescr}()
    found = Ref{SpiceBoolean}()
    ccall((:dlabbs_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{SpiceBoolean}),
          handle, descr, found)
    handleerror()
    Bool(found[]) || return nothing
    descr[]
end

"""
    dlabfs(handle)

Begin a forward segment search in a DLA file.

### Arguments ###

- `handle`: Handle of open DLA file

### Output ###

Returns the descriptor of the first segment in the DLA file or `nothing` if none was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dlabfs_c.html)
"""
function dlabfs(handle)
    descr = Ref{DLADescr}()
    found = Ref{SpiceBoolean}()
    ccall((:dlabfs_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{SpiceBoolean}),
          handle, descr, found)
    handleerror()
    Bool(found[]) || return nothing
    descr[]
end

"""
    dlafns(handle, descr)

Find the segment following a specified segment in a DLA file.

### Arguments ###

- `handle`: Handle of open DLA file
- `descr`: Descriptor of a DLA segment

### Output ###

Returns the descriptor of the next segment in the DLA file or `nothing` if none was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dlafns_c.html)
"""
function dlafns(handle, descr)
    nxtdsc = Ref{DLADescr}()
    found = Ref{SpiceBoolean}()
    ccall((:dlafns_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{DLADescr}, Ref{SpiceBoolean}),
          handle, descr, nxtdsc, found)
    handleerror()
    Bool(found[]) || return nothing
    nxtdsc[]
end

"""
    dlafps(handle, descr)

Find the segment preceding a specified segment in a DLA file.

### Arguments ###

- `handle`: Handle of open DLA file
- `descr`: Descriptor of a DLA segment

### Output ###

Returns the descriptor of the previous segment in the DLA file or `nothing` if none was found.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dlafps_c.html)
"""
function dlafps(handle, descr)
    nxtdsc = Ref{DLADescr}()
    found = Ref{SpiceBoolean}()
    ccall((:dlafps_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{DLADescr}, Ref{SpiceBoolean}),
          handle, descr, nxtdsc, found)
    handleerror()
    Bool(found[]) || return nothing
    nxtdsc[]
end

"""
    dlatdr(x, y, z)

Compute the Jacobian of the transformation from rectangular to latitudinal coordinates.

### Arguments ###

- `x`: X-coordinate of point
- `y`: Y-coordinate of point
- `z`: Z-coordinate of point

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dlatdr_c.html)
"""
function dlatdr(x, y, z)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:dlatdr_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          x, y, z, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    dp2hx(number, lenout=128)

Convert a double precision number to an equivalent character string using base 16 "scientific notation."

### Arguments ###

- `number`: Number to be converted
- `lenout`: Available space for output string

### Output ###

Returns the equivalent character string, left justified.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dp2hx_c.html)
"""
function dp2hx(number, lenout=128)
    string = Array{SpiceChar}(undef, lenout)
    n = Ref{SpiceInt}()
    ccall((:dp2hx_c, libcspice), Cvoid,
          (SpiceDouble, SpiceInt, Ref{SpiceChar}, Ref{SpiceInt}),
          number, lenout, string, n)
    chararray_to_string(string)
end

"""
    dpgrdr(x, y, z, re, f)

Compute the Jacobian of the transformation from rectangular to planetographic coordinates.

### Arguments ###

- `body`: Body with which coordinate system is associated
- `x`: X-coordinate of point
- `y`: Y-coordinate of point
- `z`: Z-coordinate of point
- `re`: Equatorial radius of the reference spheroid
- `f`: Flattening coefficient

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dpgrdr_c.html)
"""
function dpgrdr(body, x, y, z, re, f)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:dpgrdr_c, libcspice), Cvoid,
          (Cstring, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          body, x, y, z, re, f, jacobi)
    handleerror()
    permutedims(jacobi)
end

function _dpmax()
    ccall((:dpmax_c, libcspice), SpiceDouble, ())
end

@deprecate dpmax() prevfloat(typemax(Float64))

"""
    dpmax()

!!! warning "Deprecated"
    Use `prevfloat(typemax(Float64))` instead.
"""
dpmax

function _dpmin()
    ccall((:dpmin_c, libcspice), SpiceDouble, ())
end

@deprecate dpmin() nextfloat(typemin(Float64))

"""
    dpmin()

!!! warning "Deprecated"
    Use `nextfloat(typemin(Float64))` instead.
"""
dpmin

function _dpr()
    ccall((:dpr_c, libcspice), SpiceDouble, ())
end

@deprecate dpr() rad2deg(1.0)

"""
    dpr()

!!! warning "Deprecated"
    Use `rad2deg(1.0)` instead.
"""
dpr

"""
    drdcyl(r, lon, z)

Compute the Jacobian of the transformation from cylindrical to rectangular coordinates.

### Arguments ###

- `r`: Distance of a point from the origin
- `lon`: Angle of the point from the xz plane in radians
- `z`: Height of the point above the xy plane

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/drdcyl_c.html)
"""
function drdcyl(r, lon, z)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:drdcyl_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          r, lon, z, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    drdgeo(lon, lat, alt, re, f)

Compute the Jacobian of the transformation from geodetic to rectangular coordinates.

### Arguments ###

- `lon`: Geodetic longitude of point (radians)
- `lat`: Geodetic latitude of point (radians)
- `alt`: Altitude of point above the reference spheroid
- `re`: Equatorial radius of the reference spheroid
- `f`: Flattening coefficient

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/drdgeo_c.html)
"""
function drdgeo(lon, lat, alt, re, f)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:drdgeo_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          lon, lat, alt, re, f, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    drdlat(radius, lon, lat)

Compute the Jacobian of the transformation from latitudinal to rectangular coordinates.

### Arguments ###

- `radius`: Distance of a point from the origin
- `lon`: Angle of the point from the XZ plane in radians
- `lat`: Angle of the point from the XY plane in radians

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/drdlat_c.html)
"""
function drdlat(radius, lon, lat)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:drdlat_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          radius, lon, lat, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    drdpgr(body, lon, lat, alt, re, f)

Compute the Jacobian matrix of the transformation from planetographic to rectangular coordinates.

### Arguments ###

- `body`: Name of body with which coordinates are associated
- `lon`: Planetographic longitude of a point (radians)
- `lat`: Planetographic latitude of a point (radians)
- `alt`: Altitude of a point above reference spheroid
- `re`: Equatorial radius of the reference spheroid
- `f`: Flattening coefficient

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/drdpgr_c.html)
"""
function drdpgr(body, lon, lat, alt, re, f)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:drdpgr_c, libcspice), Cvoid,
          (Cstring, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble,
           Ref{SpiceDouble}),
          body, lon, lat, alt, re, f, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    drdsph(r, colat, lon)

Compute the Jacobian of the transformation from latitudinal to rectangular coordinates.

### Arguments ###

- `r`: Distance of a point from the origin
- `colat`: Angle of the point from the positive z-axis
- `lon`: Angle of the point from the xy plane

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/drdsph_c.html)
"""
function drdsph(r, colat, lon)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:drdsph_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          r, colat, lon, jacobi)
    handleerror()
    permutedims(jacobi)
end

"""
    dskb02(handle, dladsc)

Return bookkeeping data from a DSK type 2 segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor

### Output ###

- `nv`: Number of vertices in model
- `np`: Number of plates in model
- `nvxtot`: Number of voxels in fine grid
- `vtxbds`: Vertex bounds
- `voxsiz`: Fine voxel edge length
- `voxori`: Fine voxel grid origin
- `vgrext`: Fine voxel grid exent
- `cgscal`: Coarse voxel grid scale
- `vtxnpl`: Size of vertex-plate correspondence list
- `voxnpt`: Size of voxel-plate pointer list
- `voxnpl`: Size of voxel-plate correspondence list

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskb02_c.html)
"""
function dskb02(handle, dladsc)
    nv = Ref{SpiceInt}()
    np = Ref{SpiceInt}()
    nvxtot = Ref{SpiceInt}()
    vtxbds = Array{SpiceDouble}(undef, 2, 3)
    voxsiz = Ref{SpiceDouble}()
    voxori = Array{SpiceDouble}(undef, 3)
    vgrext = Array{SpiceDouble}(undef, 3)
    cgscal = Ref{SpiceInt}()
    vtxnpl = Ref{SpiceInt}()
    voxnpt = Ref{SpiceInt}()
    voxnpl = Ref{SpiceInt}()
    ccall((:dskb02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{SpiceInt}, Ref{SpiceInt}, Ref{SpiceInt}, Ref{SpiceDouble},
           Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceInt}, Ref{SpiceInt},
           Ref{SpiceInt}, Ref{SpiceInt}),
          handle, dladsc, nv, np, nvxtot, vtxbds, voxsiz, voxori, vgrext, cgscal, vtxnpl,
          voxnpt, voxnpl)
    handleerror()
    Int(nv[]), Int(np[]), Int(nvxtot[]), vtxbds, voxsiz[], voxori, vgrext, Int(cgscal[]),
    Int(vtxnpl[]), Int(voxnpt[]), Int(voxnpl[])
end

"""
    dskcls(handle, optmiz=true)

Close a DSK file.

### Arguments ###

- `handle`: Handle assigned to the opened DSK file
- `optmiz`: Flag indicating whether to segregate the DSK (default: `true`)

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskcls_c.html)
"""
function dskcls(handle, optmiz=true)
    ccall((:dskcls_c, libcspice), Cvoid, (SpiceInt, SpiceBoolean), handle, optmiz)
    handleerror()
end

"""
    dskd02(handle, dladsc, item, start, room)

Fetch double precision data from a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor
- `item`: Keyword identifying item to fetch
- `start`: Start index
- `room`: Amount of room in output array

### Output ###

Returns an array containing the requested item.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskd02_c.html)
"""
function dskd02(handle, dladsc, item, start, room)
    n = Ref{SpiceInt}()
    values = Array{SpiceDouble}(undef, room)
    ccall((:dskd02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, SpiceInt, SpiceInt, SpiceInt,
           Ref{SpiceInt}, Ref{SpiceDouble}),
          handle, dladsc, item, start - 1, room, n, values)
    handleerror()
    values[1:n[]]
end

"""
    dskgd(handle, dladsc)

Return the DSK descriptor from a DSK segment identified by a DAS handle and DLA descriptor.

### Arguments ###

- `handle`: Handle of a DSK file
- `dladsc`: DLA segment descriptor

### Output ###

Returns the DSK segment descriptor.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskgd_c.html)
"""
function dskgd(handle, dladsc)
    dskdsc = Ref{DSKDescr}()
    ccall((:dskgd_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{DSKDescr}),
          handle, dladsc, dskdsc)
    handleerror()
    dskdsc[]
end

"""
    dskgtl(keywrd)

Retrieve the value of a specified DSK tolerance or margin parameter.

### Arguments ###

- `keywrd`: Code specifying parameter to retrieve

### Output ###

Returns the value of the parameter.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskgtl_c.html)
"""
function dskgtl(keywrd)
    dpval = Ref{SpiceDouble}()
    ccall((:dskgtl_c, libcspice), Cvoid,
          (SpiceInt, Ref{SpiceDouble}),
          keywrd, dpval)
    handleerror()
    dpval[]
end

"""
    dski02(handle, dladsc, item, start, room)

Fetch integer data from a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor
- `item`: Keyword identifying item to fetch
- `start`: Start index
- `room`: Amount of room in output array

### Output ###

Returns an array containing the requested item.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dski02_c.html)
"""
function dski02(handle, dladsc, item, start, room)
    n = Ref{SpiceInt}()
    values = Array{SpiceInt}(undef, room)
    ccall((:dski02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, SpiceInt, SpiceInt, SpiceInt,
           Ref{SpiceInt}, Ref{SpiceInt}),
          handle, dladsc, item, start - 1, room, n, values)
    handleerror()
    values[1:n[]]
end

"""
    dskmi2(vrtces, plates, finscl, corscl, worksz, voxpsz, voxlsz, makvtl, spaisz)

Make spatial index for a DSK type 2 segment.

### Arguments ###

- `vrtces`: Vertices
- `plates`: Plates
- `finscl`: Fine voxel scale
- `corscl`: Coarse voxel scale
- `worksz`: Workspace size
- `voxpsz`: Voxel-plate pointer array size
- `voxlsz`: Voxel-plate list array size
- `makvtl`: Vertex-plate list flag
- `spxisz`: Spatial index integer component size

### Output ###

- `spaixd`: Double precision component of spatial index.
- `spaixi`: Integer component of spatial index.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskmi2_c.html)
"""
function dskmi2(vrtces, plates, finscl, corscl, worksz, voxpsz, voxlsz, makvtl, spxisz)
    vrtces_ = array_to_cmatrix(vrtces, n=3)
    plates_ = array_to_cmatrix(plates, n=3)
    nv = length(vrtces)
    np = length(plates)
    work = Array{SpiceInt}(undef, worksz, 2)
    spaixd = Array{SpiceDouble}(undef, 10)
    spaixi = Array{SpiceInt}(undef, spxisz)
    ccall((:dskmi2_c, libcspice), Cvoid,
          (SpiceInt, Ref{SpiceDouble}, SpiceInt, Ref{SpiceInt}, SpiceDouble,
           SpiceInt, SpiceInt, SpiceInt, SpiceInt, SpiceBoolean, SpiceInt,
           Ref{SpiceInt}, Ref{SpiceDouble}, Ref{SpiceInt}),
          nv, vrtces_, np, plates_, finscl, corscl, worksz, voxpsz, voxlsz, makvtl, spxisz,
          work, spaixd, spaixi)
    handleerror()
    spaixd, Int.(spaixi)
end

"""
    dskn02(handle, dladsc, plid)

Compute the unit normal vector for a specified plate from a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor
- `plid`: Plate ID

### Output ###

Return the plate's unit normal vector.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskn02_c.html)
"""
function dskn02(handle, dladsc, plid)
    normal = Array{SpiceDouble}(undef, 3)
    ccall((:dskn02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, SpiceInt, Ref{SpiceDouble}),
          handle, dladsc, plid, normal)
    handleerror()
    normal
end

"""
    dskobj!(set, dsk)

Find the set of body ID codes of all objects for which topographic data are provided in a specified
DSK file.

### Arguments ###

- `dsk`: Name of DSK file
- `set` or `len`: Either a preallocated `SpiceIntCell` or the `size` of the output set.

### Output ###

Returns the set of ID codes of objects in the DSK file.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskobj_c.html)
"""
function dskobj!(set, dsk)
    data = set.data
    GC.@preserve data begin
        ccall((:dskobj_c, libcspice), Cvoid,
              (Cstring, Ref{Cell{SpiceInt}}),
              dsk, set.cell)
    end
    handleerror()
    set
end

@deprecate dskobj dskobj!

"""
    dskopn(fname, ifname, ncomch)

Open a new DSK file for subsequent write operations.

### Arguments ###

- `fname`: Name of a DSK file to be opened
- `ifname`: Internal file name
- `ncomch`: Number of comment characters to allocate

### Output ###

Returns the handle assigned to the opened DSK file.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskopn_c.html)
"""
function dskopn(fname, ifname, ncomch)
    handle = Ref{SpiceInt}()
    ccall((:dskopn_c, libcspice), Cvoid,
          (Cstring, Cstring, SpiceInt, Ref{SpiceInt}),
          fname, ifname, ncomch, handle)
    handleerror()
    handle[]
end

"""
    dskp02(handle, dladsc, start, room)

Fetch triangular plates from a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor
- `start`: Start index
- `room`: Amount of room in output array

### Output ###

Returns an array of plates.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskp02_c.html)
"""
function dskp02(handle, dladsc, start, room)
    n = Ref{SpiceInt}()
    plates = Array{SpiceInt}(undef, 3, room)
    ccall((:dskp02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, SpiceInt, SpiceInt,
           Ref{SpiceInt}, Ref{SpiceInt}),
          handle, dladsc, start - 1, room, n, plates)
    handleerror()
    cmatrix_to_array(plates)
end

"""
    dskrb2(vrtces, plates, corsys, corpar)

Determine range bounds for a set of triangular plates to be stored in a type 2 DSK segment.

### Arguments ###

- `vrtces`: Vertices
- `plates`: Plates
- `corsys`: DSK coordinate system code
- `corpar`: DSK coordinate system parameters

### Output ###

- `mncor3`: Lower bound on range of third coordinate
- `mxcor3`: Upper bound on range of third coordinate

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskrb2_c.html)
"""
function dskrb2(vrtces, plates, corsys, corpar)
    vrtces_ = array_to_cmatrix(vrtces, n=3)
    plates_ = array_to_cmatrix(plates, n=3)
    nv = length(vrtces)
    np = length(plates)
    mncor3 = Ref{SpiceDouble}()
    mxcor3 = Ref{SpiceDouble}()
    ccall((:dskrb2_c, libcspice), Cvoid,
          (SpiceInt, Ref{SpiceDouble}, SpiceInt, Ref{SpiceInt}, SpiceInt, Ref{SpiceDouble},
           Ref{SpiceDouble}, Ref{SpiceDouble}),
          nv, vrtces_, np, plates_, corsys, corpar, mncor3, mxcor3)
    handleerror()
    mncor3[], mxcor3[]
end

"""
    dsksrf!(set, dsk)

Find the set of surface ID codes of all objects for which topographic data are provided in a
specified DSK file.

### Arguments ###

- `dsk`: Name of DSK file
- `set` or `len`: Either a preallocated `SpiceIntCell` or the `size` of the output set.

### Output ###

Returns the set of ID codes of surfaces in the DSK file.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dsksrf_c.html)
"""
function dsksrf!(set, dsk, bodyid)
    data = set.data
    GC.@preserve data begin
        ccall((:dsksrf_c, libcspice), Cvoid,
              (Cstring, SpiceInt, Ref{Cell{SpiceInt}}),
              dsk, bodyid, set.cell)
    end
    handleerror()
    set
end

@deprecate dsksrf dsksrf!

"""
    dskstl(keywrd)

Set the value of a specified DSK tolerance or margin parameter.

### Arguments ###

- `keywrd`: Code specifying parameter to retrieve
- `dpval`: Value of parameter

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskstl_c.html)
"""
function dskstl(keywrd, dpval)
    ccall((:dskstl_c, libcspice), Cvoid,
          (SpiceInt, SpiceDouble),
          keywrd, dpval)
    handleerror()
end

"""
    dskv02(handle, dladsc, start, room)

Fetch vertices from a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor
- `start`: Start index
- `room`: Amount of room in output array

### Output ###

Returns an array of vertices.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskv02_c.html)
"""
function dskv02(handle, dladsc, start, room)
    n = Ref{SpiceInt}()
    vrtces = Array{SpiceDouble}(undef, 3, room)
    ccall((:dskv02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, SpiceInt, SpiceInt,
           Ref{SpiceInt}, Ref{SpiceDouble}),
          handle, dladsc, start - 1, room, n, vrtces)
    handleerror()
    cmatrix_to_array(vrtces)
end

"""
    dskw02(handle, center, surfid, dclass, frame, corsys, corpar, mncor1, mxcor1,
           mncor2, mxcor2, mncor3, mxcor3, first, last, vrtces, plates, spaixd, spaixi)

Write a type 2 segment to a DSK file.

### Arguments ###

- `handle`: Handle assigned to the opened DSK file
- `center`: Central body ID code
- `surfid`: Surface ID code
- `dclass`: Data class
- `frame `: Reference frame
- `corsys`: Coordinate system code
- `corpar`: Coordinate system parameters
- `mncor1`: Minimum value of first coordinate
- `mxcor1`: Maximum value of first coordinate
- `mncor2`: Minimum value of second coordinate
- `mxcor2`: Maximum value of second coordinate
- `mncor3`: Minimum value of third coordinate
- `mxcor3`: Maximum value of third coordinate
- `first`: Coverage start time
- `last`: Coverage stop time
- `nv`: Number of vertices
- `vrtces`: Vertices
- `np`: Number of plates
- `plates`: Plates
- `spaixd`: Double precision component of spatial index
- `spaixi`: Integer component of spatial index

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskw02_c.html)
"""
function dskw02(handle, center, surfid, dclass, frame, corsys, corpar, mncor1, mxcor1,
                mncor2, mxcor2, mncor3, mxcor3, first, last, vrtces, plates, spaixd, spaixi)
    vrtces_ = array_to_cmatrix(vrtces, n=3)
    plates_ = array_to_cmatrix(plates, n=3)
    spaixi_ = SpiceInt.(spaixi)
    nv = length(vrtces)
    np = length(plates)
    ccall((:dskw02_c, libcspice), Cvoid,
          (SpiceInt, SpiceInt, SpiceInt, SpiceInt, Cstring, SpiceInt, Ref{SpiceDouble},
           SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble, SpiceDouble,
           SpiceDouble, SpiceDouble, SpiceInt, Ref{SpiceDouble}, SpiceInt, Ref{SpiceInt},
           Ref{SpiceDouble}, Ref{SpiceInt}),
          handle, center, surfid, dclass, frame, corsys, corpar, mncor1, mxcor1, mncor2,
          mxcor2, mncor3, mxcor3, first, last, nv, vrtces_, np, plates_, spaixd, spaixi_)
    handleerror()
end

"""
    dskx02(handle, dladsc, vertex, raydir)

Determine the plate ID and body-fixed coordinates of the intersection of a specified ray with the
surface defined by a type 2 DSK plate model.

### Arguments ###

- `handle`: Handle of DSK kernel containing plate model
- `dladsc`: DLA descriptor of plate model segment
- `vertex`: Ray vertex in the body fixed frame
- `raydir`: Ray direction in the body fixed frame

### Output ###

Returns `nothing` if no intercept exists or

- `plid`: ID code of the plate intersected by the ray
- `xpt`: Intercept

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskx02_c.html)
"""
function dskx02(handle, dladsc, vertex, raydir)
    @checkdims 3 vertex raydir
    plid = Ref{SpiceInt}()
    xpt = Array{SpiceDouble}(undef, 3)
    found = Ref{SpiceBoolean}()
    ccall((:dskx02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{SpiceDouble}, Ref{SpiceDouble},
           Ref{SpiceInt}, Ref{SpiceDouble}, Ref{SpiceBoolean}),
          handle, dladsc, vertex, raydir, plid, xpt, found)
    handleerror()
    Bool(found[]) || return nothing
    Int(plid[]), xpt
end

"""
    dskxsi(pri, target, nsurf, srflst, et, fixref, vertex, raydir, maxd=1, maxi=1)

Compute a ray-surface intercept using data provided by multiple loaded DSK segments.
Return information about the source of the data defining the surface on which the intercept
was found: DSK handle, DLA and DSK descriptors, and DSK data type-dependent parameters.

### Arguments ###

- `pri`: Data prioritization flag
- `target`: Target body name
- `srflst`: Surface ID list
- `et`: Epoch, expressed as seconds past J2000 TDB
- `fixref`: Name of target body-fixed reference frame
- `vertex`: Vertex of ray
- `raydir`: Direction vector of ray
- `maxd`: Size of DC array (default: 1)
- `maxi`: Size of IC array (default: 1)

### Output ###

Returns `nothing` if no intercept exists or

- `xpt`: Intercept point
- `handle`: Handle of segment contributing surface data
- `dladsc`: DLA descriptor of segment
- `dskdsc`: DSK descriptor of segment
- `dc`: Double precision component of source info
- `ic`: Integer component of source info

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskxsi_c.html)
"""
function dskxsi(pri, target, srflst, et, fixref, vertex, raydir, maxd=1, maxi=1)
    @checkdims 3 vertex raydir
    nsurf = length(srflst)
    srflst_ = SpiceInt.(srflst)
    xpt = Array{SpiceDouble}(undef, 3)
    handle = Ref{SpiceInt}()
    dladsc = Ref{DLADescr}()
    dskdsc = Ref{DSKDescr}()
    dc = zeros(maxd)
    ic = Array{SpiceInt}(undef, maxi)
    found = Ref{SpiceBoolean}()
    ccall((:dskxsi_c, libcspice), Cvoid,
          (SpiceBoolean, Cstring, SpiceInt, Ref{SpiceInt}, SpiceDouble, Cstring, Ref{SpiceDouble},
           Ref{SpiceDouble}, SpiceInt, SpiceInt, Ref{SpiceDouble}, Ref{SpiceInt},
           Ref{DLADescr}, Ref{DSKDescr}, Ref{SpiceDouble}, Ref{SpiceInt}, Ref{SpiceBoolean}),
          pri, target, nsurf, srflst_, et, fixref, vertex, raydir, maxd, maxi,
          xpt, handle, dladsc, dskdsc, dc, ic, found)
    handleerror()
    Bool(found[]) || return nothing
    xpt, handle[], dladsc[], dskdsc[], dc, Int.(ic)
end

"""
    dskxv(pri, target, srflst, et, fixref, nrays, vtxarr, dirarr)

Compute ray-surface intercepts for a set of rays, using data provided by multiple loaded DSK
segments.

### Arguments ###

- `pri`: Data prioritization flag
- `target`: Target body name
- `srflst`: Surface ID list
- `et`: Epoch, expressed as seconds past J2000 TDB
- `fixref`: Name of target body-fixed reference frame
- `nrays `: Number of rays
- `vtxarr`: Array of vertices of rays
- `dirarr`: Array of direction vectors of rays

### Output ###

- `xptarr`: Intercept point array
- `fndarr`: Found flag array

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskxv_c.html)
"""
function dskxv(pri, target, srflst, et, fixref, vtxarr, dirarr)
    srflst_ = SpiceInt.(srflst)
    nrays = length(vtxarr)
    nsurf = length(srflst)
    @checkdims nrays dirarr
    vtxarr_ = array_to_cmatrix(vtxarr, n=3)
    dirarr_ = array_to_cmatrix(dirarr, n=3)
    xptarr = Array{SpiceDouble}(undef, 3, nrays)
    fndarr = Array{SpiceBoolean}(undef, nrays)
    ccall((:dskxv_c, libcspice), Cvoid,
          (SpiceBoolean, Cstring, SpiceInt, Ref{SpiceInt}, SpiceDouble, Cstring, SpiceInt,
           Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceBoolean}),
          pri, target, nsurf, srflst_, et, fixref, nrays, vtxarr_, dirarr_, xptarr, fndarr)
    handleerror()
    cmatrix_to_array(xptarr), Bool.(fndarr)
end

"""
    dskz02(handle, dladsc)

Return plate model size parameters - plate count and vertex count - for a type 2 DSK segment.

### Arguments ###

- `handle`: DSK file handle
- `dladsc`: DLA descriptor

### Output ###

- `nv`: Number of vertices
- `np`: Number of plates

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskz02_c.html)
"""
function dskz02(handle, dladsc)
    nv = Ref{SpiceInt}()
    np = Ref{SpiceInt}()
    ccall((:dskz02_c, libcspice), Cvoid,
          (SpiceInt, Ref{DLADescr}, Ref{SpiceInt}, Ref{SpiceInt}),
          handle, dladsc, nv, np)
    handleerror()
    Int(nv[]), Int(np[])
end

"""
    dsphdr(x, y, z)

Compute the Jacobian of the transformation from rectangular to spherical coordinates.

### Arguments ###

- `x`: X-coordinate of point
- `y`: Y-coordinate of point
- `z`: Z-coordinate of point

### Output ###

Returns the matrix of partial derivatives.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dsphdr_c.html)
"""
function dsphdr(x, y, z)
    jacobi = Array{SpiceDouble}(undef, 3, 3)
    ccall((:dsphdr_c, libcspice), Cvoid,
          (SpiceDouble, SpiceDouble, SpiceDouble, Ref{SpiceDouble}),
          x, y, z, jacobi)
    jacobi
end

"""
    dtpool(name)

Return the data about a kernel pool variable.

### Arguments ###

- `name`: Name of the variable whose value is to be returned

### Output ###

Returns the tuple `(n ,vartype)`.

- `n`: Number of values returned for name
- `vartype`: Type of the variable
    - `:C` if the data is character data
    - `:N` if the data is numeric
    - `:X` if there is no variable name in the pool

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dtpool_c.html)
"""
function dtpool(name)
    found = Ref{SpiceBoolean}()
    n = Ref{SpiceInt}()
    vartype = Ref{Cchar}()
    ccall((:dtpool_c, libcspice), Cvoid, (Cstring, Ref{SpiceBoolean}, Ref{SpiceInt}, Ref{Cchar}),
          name, found, n, vartype)
    handleerror()
    Int(n[]), Symbol(Char(vartype[]))
end

"""
    ducrss(s1, s2)

Compute the unit vector parallel to the cross product of two 3-dimensional vectors and the
derivative of this unit vector.

### Arguments ###

- `s1`: Left hand state for cross product and derivative
- `s2`: Right hand state for cross product and derivative

### Output ###

Returns the unit vector and derivative of the cross product.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ducrss_c.html)
"""
function ducrss(s1, s2)
    @checkdims 6 s1 s2
    sout = Array{SpiceDouble}(undef, 6)
    ccall((:ducrss_c, libcspice), Cvoid,
          (Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceDouble}),
          s1, s2, sout)
    sout
end

"""
    dvcrss(s1, s2)

Compute the cross product of two 3-dimensional vectors and the derivative of this cross product.

### Arguments ###

- `s1`: Left hand state for cross product and derivative
- `s2`: Right hand state for cross product and derivative

### Output ###

Returns the cross product and its derivative.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvcrss_c.html)
"""
function dvcrss(s1, s2)
    @checkdims 6 s1 s2
    sout = Array{SpiceDouble}(undef, 6)
    ccall((:dvcrss_c, libcspice), Cvoid,
          (Ref{SpiceDouble}, Ref{SpiceDouble}, Ref{SpiceDouble}),
          s1, s2, sout)
    sout
end

"""
    dvdot(s1, s2)

Compute the derivative of the dot product of two double precision position vectors.

### Arguments ###

- `s1`: First state vector in the dot product
- `s2`: Second state vector in the dot product

### Output ###

Returns the derivative of the dot product `s1 ⋅ s2`.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvdot_c.html)
"""
function dvdot(s1, s2)
    @checkdims 6 s1 s2
    ccall((:dvdot_c, libcspice), SpiceDouble, (Ref{SpiceDouble}, Ref{SpiceDouble}), s1, s2)
end

"""
    dvhat(s1)

Find the unit vector corresponding to a state vector and the derivative of the unit vector.

### Arguments ###

- `s1`: State to be normalized

### Output ###

Returns the unit vector `s1 / |s1|`, and its time derivative.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvhat_c.html)
"""
function dvhat(s1)
    @checkdims 6 s1
    sout = Array{SpiceDouble}(undef, 6)
    ccall((:dvhat_c, libcspice), Cvoid,
          (Ref{SpiceDouble}, Ref{SpiceDouble}),
          s1, sout)
    sout
end

"""
    dvnorm(state)

Function to calculate the derivative of the norm of a 3-vector.

### Arguments ###

- `state`: A 6-vector composed of three coordinates and their derivatives.

### Output ###

Returns the derivative of the norm of `state`.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvnorm_c.html)
"""
function dvnorm(state)
    @checkdims 6 state
    ccall((:dvnorm_c, libcspice), SpiceDouble, (Ref{SpiceDouble},), state)
end

"""
    dvpool(name)

Delete a variable from the kernel pool.

### Arguments ###

- `name`: Name of the kernel variable to be deleted

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvpool_c.html)
"""
function dvpool(name)
    ccall((:dvpool_c, libcspice), Cvoid, (Cstring,), name)
    handleerror()
end

"""
    dvsep(s1, s2)

Calculate the time derivative of the separation angle between two input states, `s1` and `s2`.

### Arguments ###

- `s1`: State vector of the first body
- `s2`: State vector of the second  body

### Output ###

Returns the value of the time derivative of the angular separation between `s1` and `s2`.

### References ###

- [NAIF Documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dvsep_c.html)
"""
function dvsep(s1, s2)
    @checkdims 6 s1 s2
    res = ccall((:dvsep_c, libcspice), SpiceDouble, (Ref{SpiceDouble}, Ref{SpiceDouble}), s1, s2)
    handleerror()
    res
end


text:
using MetabolicFluxAnalysis
# test parser:

fluxi_1_f = open("testdata/test_01.fluxi")
fluxi_1_s = readstring(fluxi_1_f)

MetabolicFluxAnalysis.parseFluxi(fluxi_1_s)
s1 = MetabolicFluxAnalysis.parseFluxi( fluxi_1_s )

@test length( s1.net.species ) == 6
@test length( s1.net.fluxes )  == 9

ext: jl


text:
import Base: *, +, -, /, \

##################
# Multiplication #
##################

# The below needs to be defined more generically;
# the below only defines multiplication on orthonormal,
# N<3 objects

typealias OrthonormalBasis{S<:Orthonormal} AbstractBasis{S}

# bra * ket -> scalar
function *{B<:OrthonormalBasis}(bra::DualVector{B}, ket::AbstractQuVector{B})
    return dot(rawcoeffs(bra), rawcoeffs(ket))
end

# bra * operator -> bra
function *{B<:OrthonormalBasis}(bra::DualVector{B}, op::AbstractQuMatrix{B})
    return QuArray(Ac_mul_B(rawcoeffs(op), rawcoeffs(bra)), bases(op,2))'
end

function *{B<:OrthonormalBasis}(bra::DualVector{B}, op::DualMatrix{B})
    return QuArray(rawcoeffs(op)*rawcoeffs(bra), bases(op,2))'
end

# operator * ket -> ket
function *{B<:OrthonormalBasis}(op::AbstractQuMatrix{B}, ket::AbstractQuVector{B})
    vc = rawcoeffs(op)*rawcoeffs(ket)
    QAT = similar_type(ket)
    return QAT(vc, bases(op,1))
end

function *{B<:OrthonormalBasis}(op::DualMatrix{B}, ket::AbstractQuVector{B})
    vc = Ac_mul_B(rawcoeffs(op), rawcoeffs(ket))
    QAT = similar_type(ket)
    return QAT(vc, bases(op,1))
end

# ket * bra -> operator
function *{B<:OrthonormalBasis}(ket::QuVector{B}, bra::DualVector{B})
    return QuArray(A_mul_Bc(rawcoeffs(ket), rawcoeffs(bra)),
                   bases(ket,1),
                   bases(bra,1))
end

# operator * operator -> operator
*(dm1::DualMatrix, dm2::DualMatrix) = (dm2.qarr*dm1.qarr)'
*{B<:OrthonormalBasis}(dm1::DualMatrix{B}, dm2::DualMatrix{B}) = (dm2.qarr*dm1.qarr)'

function *{B<:OrthonormalBasis}(dm::DualMatrix{B}, qm::AbstractQuMatrix{B})
    mc = Ac_mul_B(rawcoeffs(dm), rawcoeffs(qm))
    QAT = similar_type(qm)
    return QAT(mc, bases(dm,1), bases(qm,2))
end

function *{B<:OrthonormalBasis}(qm::AbstractQuMatrix{B}, dm::DualMatrix{B})
    mc = A_mul_Bc(rawcoeffs(qm), rawcoeffs(dm))
    QAT = similar_type(qm)
    return QAT(mc, bases(qm,1), bases(dm,2))
end

function *{B<:OrthonormalBasis}(qm1::AbstractQuMatrix{B}, qm2::AbstractQuMatrix{B})
    mc = rawcoeffs(qm1)*rawcoeffs(qm2)
    QAT = similar_type(qm1, qm2)
    return QAT(mc, bases(qm1,1), bases(qm2,2))
end

# addition and subtraction
function +{B<:AbstractBasis}(qarr1::AbstractQuArray{B}, qarr2::AbstractQuArray{B})
    if bases(qarr1) == bases(qarr2)
        sc = coeffs(qarr1) + coeffs(qarr2)
        QAT = similar_type(qarr1, qarr2)
        return QAT(sc, bases(qarr1))
    else
        error("Bases not compatible")
    end
end

function -{B<:AbstractBasis}(qarr1::AbstractQuArray{B}, qarr2::AbstractQuArray{B})
    if bases(qarr1) == bases(qarr2)
        sc = coeffs(qarr1) - coeffs(qarr2)
        QAT = similar_type(qarr1, qarr2)
        return QAT(sc, bases(qarr1))
    else
        error("Bases not compatible")
    end
end

+(ct1::CTranspose, ct2::CTranspose) = (ct1.qarr+ct2.qarr)'
-(ct1::CTranspose, ct2::CTranspose) = (ct1.qarr-ct2.qarr)'

# scaling
Base.scale!(num::Number, qarr::AbstractQuArray) = (scale!(num, rawcoeffs(qarr)); return qarr)
Base.scale!(num::Number, ct::CTranspose) = CTranspose(scale!(num', ct.qarr))
Base.scale!(qarr::AbstractQuArray, num::Number) = scale!(num, qarr)

function Base.scale(num::Number, qarr::AbstractQuArray)
    fc = scale(num, rawcoeffs(qarr))
    QAT = similar_type(qarr)
    return QAT(fc, bases(qarr))
end
Base.scale(num::Number, ct::CTranspose) = CTranspose(scale(num', ct.qarr))
Base.scale(qarr::AbstractQuArray, num::Number) = scale(num, qarr)

*(num::Number, qarr::AbstractQuArray) = scale(num, qarr)
*(qarr::AbstractQuArray, num::Number) = scale(qarr, num)
/(qarr::AbstractQuArray, num::Number) = scale(1/num, qarr)

# Matrix Division, A*X=B, X = \(A,B), where A and B are of type AbstractQuMatrix
function \{B<:OrthonormalBasis}(qm1::AbstractQuMatrix{B}, qm2::AbstractQuMatrix{B})
    div = \(coeffs(qm1),coeffs(qm2))
    QAT = similar_type(qm1, qm2)
    return QAT(div, bases(qm1,1), bases(qm2,2))
end

# Matrix Division, A*X=B; X = \(A,B), where A is AbstractQuMatrix and B is AbstractQuVector
function \{B<:OrthonormalBasis}(op::AbstractQuMatrix{B}, vec::AbstractQuVector{B})
    div = \(coeffs(op), coeffs(vec))
    QAT = similar_type(vec)
    return QAT(div, bases(op,1))
end

#  Vectorize QuArray
Base.vec{B<:OrthonormalBasis}(vec1::AbstractQuArray{B}) = QuArray(vec(coeffs(vec1)))

# Trace of AbstractQuMatrix
Base.trace{B<:OrthonormalBasis}(qm1::AbstractQuMatrix{B}) = trace(coeffs(qm1))

# dot product of QuArray's
Base.dot{B<:OrthonormalBasis}(vec1::AbstractQuVector{B}, vec2::AbstractQuVector{B}) = dot(coeffs(vec1), coeffs(vec2))
Base.dot{B<:OrthonormalBasis}(vec1::DualVector{B}, vec2::DualVector{B}) = dot(vec(coeffs(vec1)), vec(coeffs(vec2)))
Base.dot{B<:OrthonormalBasis}(vec1::AbstractQuVector{B}, vec2::DualVector{B}) = error("Inner product of a dual vector and a vector is not supported.")
Base.dot{B<:OrthonormalBasis}(vec1::DualVector{B}, vec2::AbstractQuVector{B}) = error("Inner product of a dual vector and a vector is not supported.")

# Reference : http://en.wikipedia.org/wiki/Dot_product#Dyadics_and_matrices
Base.dot{B<:OrthonormalBasis}(qm1::AbstractQuMatrix{B}, qm2::AbstractQuMatrix{B}) = trace(qm1'*qm2)
Base.dot{B<:OrthonormalBasis}(qm1::DualMatrix{B}, qm2::AbstractQuMatrix{B}) = trace(qm1*qm2)
Base.dot{B<:OrthonormalBasis}(qm1::DualMatrix{B}, qm2::DualMatrix{B}) = trace(qm1*qm2')
Base.dot{B<:OrthonormalBasis}(qm1::AbstractQuMatrix{B}, qm2::DualMatrix{B}) = trace(qm1'*qm2')

# matrix operations returning a scalar
# normalization
Base.norm(qarr::AbstractQuArray) = vecnorm(rawcoeffs(qarr))

function Compat.normalize!(qarr::AbstractQuArray)
    scale!(1/norm(qarr), rawcoeffs(qarr))
    return qarr
end

Compat.normalize(qarr::AbstractQuArray) = normalize!(copy(qarr))

# matrix operations returning an array
# sparse to dense
function Base.full(qarr::AbstractQuMatrix)
    fc = full(rawcoeffs(qarr))
    QAT = similar_type(qarr)
    return QAT(fc, bases(qarr))
end
#Base.full(ct::CTranspose) = full(ct.qarr)'

# exponential of dense matrix
function Base.expm(qarr::AbstractQuMatrix)
    fc = expm(full(rawcoeffs(qarr)))
    QAT = similar_type(qarr)
    return QAT(fc, bases(qarr))
end
#Base.expm(ct::CTranspose) = expm(ct.qarr)'

##################
# Tensor Product #
##################

# General tensor product definitions
function tensor{B1,B2,T1,T2,N}(qarr1::AbstractQuArray{B1,T1,N}, qarr2::AbstractQuArray{B2,T2,N})
    tc = kron(coeffs(qarr1), coeffs(qarr2))
    QAT = similar_type(qarr1, qarr2)
    return QAT(tc, map(tensor, bases(qarr1), bases(qarr2)))
end

# defined to resolve ambiguity warnings
tensor(ct1::CTranspose, ct2::CTranspose) = tensor(ct1.qarr, ct2.qarr)'
tensor(ct1::DualVector, ct2::DualVector) = tensor(ct1.qarr, ct2.qarr)'

function tensor(ket::AbstractQuVector, bra::DualVector)
    tc = kron(coeffs(ket), coeffs(bra))
    QAT = similar_type(ket)
    return QAT(tc, bases(ket,1), bases(bra,1))
end

tensor(bra::DualVector, ket::AbstractQuVector) = tensor(ket, bra)

###############
# Commutators #
###############

# (anti)commute two QuMatrices and return result
commute(a::AbstractQuMatrix, b::AbstractQuMatrix) = (a*b) - (b*a)
anticommute(a::AbstractQuMatrix, b::AbstractQuMatrix) = (a*b) + (b*a)

################
#  Expectation #
################
expectationvalue(qarr::AbstractQuVector, op::AbstractQuMatrix) = qarr'*op*qarr
expectationvalue(qarr::AbstractQuMatrix, op::AbstractQuMatrix) = trace(qarr*op)

export tensor,
    commute,
    anticommute,
    expectationvalue


text:
using JuMP, EAGO

                     m = Model()

                     EAGO.register_eago_operators!(m)

                     @variable(m, -1 <= x[i=1:5] <= 1)

                     @variable(m, -31.730360167469108 <= q <= 25.84895899492546)

                     add_NL_constraint(m, :(gelu(0.0048766473277672695 + 0.6370542772950833*gelu(0.25009028296342795 + -0.2547820908673408*$(x[1]) + -0.7856561704813507*$(x[2]) + -0.058708649178761174*$(x[3]) + -0.7608390940355938*$(x[4]) + -0.05318346349824532*$(x[5])) + 0.7379502189935647*gelu(-0.9382943152388461 + 0.5207156183879813*$(x[1]) + -0.2471020507819235*$(x[2]) + -0.7557614646986384*$(x[3]) + -0.33572241425474436*$(x[4]) + -0.6239060401766734*$(x[5])) + -0.017781498731094914*gelu(-0.885143874020959 + 0.9842140185190744*$(x[1]) + 0.788813814030803*$(x[2]) + -0.15763218219342123*$(x[3]) + -0.7069686241723065*$(x[4]) + -0.5626424821908671*$(x[5])) + -0.30964053180650675*gelu(0.6131135785432997 + 0.10922488949962084*$(x[1]) + -0.12917190851327387*$(x[2]) + -0.1680916348200565*$(x[3]) + -0.8331067755239463*$(x[4]) + 0.6030847772122314*$(x[5])) + -0.19693223852539354*gelu(-0.16753936699968897 + -0.5793989304507368*$(x[1]) + 0.5784575652786188*$(x[2]) + 0.7312888898953878*$(x[3]) + 0.9375360522038214*$(x[4]) + -0.8845975912485904*$(x[5]))) + gelu(0.6750746912592471 + -0.6689814871888631*gelu(0.25009028296342795 + -0.2547820908673408*$(x[1]) + -0.7856561704813507*$(x[2]) + -0.058708649178761174*$(x[3]) + -0.7608390940355938*$(x[4]) + -0.05318346349824532*$(x[5])) + 0.08174772592079638*gelu(-0.9382943152388461 + 0.5207156183879813*$(x[1]) + -0.2471020507819235*$(x[2]) + -0.7557614646986384*$(x[3]) + -0.33572241425474436*$(x[4]) + -0.6239060401766734*$(x[5])) + 0.43040165086652493*gelu(-0.885143874020959 + 0.9842140185190744*$(x[1]) + 0.788813814030803*$(x[2]) + -0.15763218219342123*$(x[3]) + -0.7069686241723065*$(x[4]) + -0.5626424821908671*$(x[5])) + 0.6360324545158482*gelu(0.6131135785432997 + 0.10922488949962084*$(x[1]) + -0.12917190851327387*$(x[2]) + -0.1680916348200565*$(x[3]) + -0.8331067755239463*$(x[4]) + 0.6030847772122314*$(x[5])) + 0.2590621611090005*gelu(-0.16753936699968897 + -0.5793989304507368*$(x[1]) + 0.5784575652786188*$(x[2]) + 0.7312888898953878*$(x[3]) + 0.9375360522038214*$(x[4]) + -0.8845975912485904*$(x[5]))) + gelu(-0.5603004507305789 + -0.6080760485894823*gelu(0.25009028296342795 + -0.2547820908673408*$(x[1]) + -0.7856561704813507*$(x[2]) + -0.058708649178761174*$(x[3]) + -0.7608390940355938*$(x[4]) + -0.05318346349824532*$(x[5])) + -0.17827205367530619*gelu(-0.9382943152388461 + 0.5207156183879813*$(x[1]) + -0.2471020507819235*$(x[2]) + -0.7557614646986384*$(x[3]) + -0.33572241425474436*$(x[4]) + -0.6239060401766734*$(x[5])) + -0.3024929990799108*gelu(-0.885143874020959 + 0.9842140185190744*$(x[1]) + 0.788813814030803*$(x[2]) + -0.15763218219342123*$(x[3]) + -0.7069686241723065*$(x[4]) + -0.5626424821908671*$(x[5])) + 0.2876553916986979*gelu(0.6131135785432997 + 0.10922488949962084*$(x[1]) + -0.12917190851327387*$(x[2]) + -0.1680916348200565*$(x[3]) + -0.8331067755239463*$(x[4]) + 0.6030847772122314*$(x[5])) + 0.1394466763243627*gelu(-0.16753936699968897 + -0.5793989304507368*$(x[1]) + 0.5784575652786188*$(x[2]) + 0.7312888898953878*$(x[3]) + 0.9375360522038214*$(x[4]) + -0.8845975912485904*$(x[5]))) + gelu(-0.3104079613918116 + -0.8967757209559282*gelu(0.25009028296342795 + -0.2547820908673408*$(x[1]) + -0.7856561704813507*$(x[2]) + -0.058708649178761174*$(x[3]) + -0.7608390940355938*$(x[4]) + -0.05318346349824532*$(x[5])) + 0.9554659562201504*gelu(-0.9382943152388461 + 0.5207156183879813*$(x[1]) + -0.2471020507819235*$(x[2]) + -0.7557614646986384*$(x[3]) + -0.33572241425474436*$(x[4]) + -0.6239060401766734*$(x[5])) + 0.4284452595185697*gelu(-0.885143874020959 + 0.9842140185190744*$(x[1]) + 0.788813814030803*$(x[2]) + -0.15763218219342123*$(x[3]) + -0.7069686241723065*$(x[4]) + -0.5626424821908671*$(x[5])) + -0.8546417933790886*gelu(0.6131135785432997 + 0.10922488949962084*$(x[1]) + -0.12917190851327387*$(x[2]) + -0.1680916348200565*$(x[3]) + -0.8331067755239463*$(x[4]) + 0.6030847772122314*$(x[5])) + -0.9550224035691546*gelu(-0.16753936699968897 + -0.5793989304507368*$(x[1]) + 0.5784575652786188*$(x[2]) + 0.7312888898953878*$(x[3]) + 0.9375360522038214*$(x[4]) + -0.8845975912485904*$(x[5]))) + gelu(0.11524778075403264 + -0.08842997013200282*gelu(0.25009028296342795 + -0.2547820908673408*$(x[1]) + -0.7856561704813507*$(x[2]) + -0.058708649178761174*$(x[3]) + -0.7608390940355938*$(x[4]) + -0.05318346349824532*$(x[5])) + -0.2446780712327863*gelu(-0.9382943152388461 + 0.5207156183879813*$(x[1]) + -0.2471020507819235*$(x[2]) + -0.7557614646986384*$(x[3]) + -0.33572241425474436*$(x[4]) + -0.6239060401766734*$(x[5])) + 0.5457935761049009*gelu(-0.885143874020959 + 0.9842140185190744*$(x[1]) + 0.788813814030803*$(x[2]) + -0.15763218219342123*$(x[3]) + -0.7069686241723065*$(x[4]) + -0.5626424821908671*$(x[5])) + -0.1673283141057702*gelu(0.6131135785432997 + 0.10922488949962084*$(x[1]) + -0.12917190851327387*$(x[2]) + -0.1680916348200565*$(x[3]) + -0.8331067755239463*$(x[4]) + 0.6030847772122314*$(x[5])) + 0.6343389483483679*gelu(-0.16753936699968897 + -0.5793989304507368*$(x[1]) + 0.5784575652786188*$(x[2]) + 0.7312888898953878*$(x[3]) + 0.9375360522038214*$(x[4]) + -0.8845975912485904*$(x[5]))) - $q <= 0.0))

                     @objective(m, Min, q)

                     return m

max_stars_repo_name: PSORLab/RSActivationFunctions

max_issues_repo_name: PSORLab/RSActivationFunctions

max_forks_repo_name: PSORLab/RSActivationFunctions


text:
abstract Link             # Link types define linkfun!, linkinv!, and mueta!

import Base.@math_const

@math_const sqrt2   1.4142135623730950488 sqrt(big(2.))
@math_const sqrt2pi 2.5066282746310005024 sqrt(big(2.)*π)

type CauchitLink <: Link end
type CloglogLink  <: Link end
type IdentityLink <: Link end
type InverseLink  <: Link end
type LogitLink <: Link end
type LogLink <: Link end
type ProbitLink <: Link end

type CauchLink <: UnaryFunctor end
evaluate{T<:FP}(::CauchLink,x::T) = tan(pi*(x - convert(T,0.5)))
type CauchInv <: UnaryFunctor end
evaluate{T<:FP}(::CauchInv,x::T) = convert(T,0.5) + atan(x)/pi
type CauchME <: UnaryFunctor end
evaluate{T<:FP}(::CauchME,x::T) = one(T)/(pi*(one(T) + abs2(x)))
type CLgLgLink <: UnaryFunctor end
evaluate{T<:FP}(::CLgLgLink,x::T) = log(-log(one(T) - x))
type CLgLgInv <: UnaryFunctor end
evaluate{T<:FP}(::CLgLgInv,x::T) = -expm1(-exp(x))
type CLgLgME <: UnaryFunctor end
evaluate{T<:FP}(::CLgLgME,x::T) = exp(x)*exp(-exp(x))
type InvME <: UnaryFunctor end
evaluate{T<:FP}(::InvME,x::T) = -one(T)/abs2(x)
type LogitME <: UnaryFunctor end
evaluate{T<:FP}(::LogitME,x::T) = (e = exp(-abs(x)); f = one(T) + e; e / (f * f))
type ProbLink <: UnaryFunctor end
evaluate{T<:FP}(::ProbLink,x::T) = sqrt2*erfinv(convert(T,2.0)*x-one(T))
type ProbInv <: UnaryFunctor end
evaluate{T<:FP}(::ProbInv,x::T) = (one(T) + erf(x/sqrt2))/convert(T,2.0)
type ProbME <: UnaryFunctor end
evaluate{T<:FP}(::ProbME,x::T) = exp(-x*x/convert(T,2.0))/sqrt2pi

                                        # IdentityLink is a special case - nothing to map
linkfun!{T<:FP}(::IdentityLink, eta::Vector{T}, mu::Vector{T}) = copy!(eta,mu)
linkinv!{T<:FP}(::IdentityLink, mu::Vector{T}, eta::Vector{T}) = copy!(mu,eta)
mueta!{T<:FP}(::IdentityLink, me::Vector{T}, eta::Vector{T}) = fill!(me,one(T))

for (l, lf, li, mueta) in
    ((:CauchitLink, :CauchLink, :CauchInv, :CauchME),
     (:CloglogLink, :CLgLgLink, :CLgLgInv, :CLgLgME),
     (:InverseLink, :Recip, :Recip, :InvME),
     (:LogitLink, :LogitFun, :LogisticFun, :LogitME),
     (:LogLink, :LogFun, :ExpFun, :ExpFun),
     (:ProbitLink, :ProbLink, :ProbInv, :ProbME))
    @eval begin
        linkfun!{T<:FP}(::$l,eta::Vector{T},mu::Vector{T}) = map!($lf(),eta,mu)
        linkinv!{T<:FP}(::$l,mu::Vector{T},eta::Vector{T}) = map!($li(),mu,eta)
        mueta!{T<:FP}(::$l,me::Vector{T},eta::Vector{T}) = map!($mueta(),me,eta)
    end
end

canonicallink(::Gamma) = InverseLink()
canonicallink(::Normal) = IdentityLink()
canonicallink(::Binomial) = LogitLink()
canonicallink(::Poisson) = LogLink()

type BernoulliVar <: UnaryFunctor end
evaluate{T<:FP}(::BernoulliVar,x::T) = x * (one(T) - x)

var!{T<:FP}(::Binomial,v::Vector{T},mu::Vector{T}) = map!(BernoulliVar(),v,mu)
var!{T<:FP}(::Gamma,v::Vector{T},mu::Vector{T}) = map!(Abs2Fun(),v,mu)
var!{T<:FP}(::Normal,v::Vector{T},mu::Vector{T}) = fill!(v,one(T))
var!{T<:FP}(::Poisson,v::Vector{T},mu::Vector{T}) = copy!(v,mu)

type BinomialMuStart <: BinaryFunctor end
evaluate{T<:FP}(::BinomialMuStart,y::T,w::T) = (w*y + convert(T,0.5))/(w + one(T))
result_type{T<:FP}(::BinomialMuStart,::Type{T},::Type{T}) = T

mustart{T<:FP}(::Binomial,y::Vector{T},wt::Vector{T}) = map(BinomialMuStart(),y,wt)
mustart{T<:FP}(::Gamma,y::Vector{T},::Vector{T}) = copy(y)
mustart{T<:FP}(::Normal,y::Vector{T},::Vector{T}) = copy(y)
mustart{T<:FP}(::Poisson,y::Vector{T},::Vector{T}) = y + convert(T,0.1)

for Op in [:BernoulliVar,
           :CauchLink, :CauchInv, :CauchME,
           :CLgLgLink, :CLgLgInv, :CLgLgME,
           :InvME,
           :LogitME,
           :ProbLink, :ProbInv, :ProbME]
    @eval result_type{T<:FP}(::$(Op), ::Type{T}) = T
end

type BinomialDevResid <: TernaryFunctor end
function evaluate{T<:FP}(::BinomialDevResid,y::T,mu::T,wt::T)
    omy = one(T)-y
    2.wt*(xlogy(y,y/mu) + xlogy(omy,omy/(one(T)-mu)))
end
result_type{T<:FP}(::BinomialDevResid,::Type{T},::Type{T},::Type{T}) = T

type PoissonDevResid <: TernaryFunctor end
evaluate{T<:FP}(::PoissonDevResid,y::T,mu::T,wt::T) = 2.wt * (xlogy(y,y/mu) - (y - mu))
result_type{T<:FP}(::PoissonDevResid,::Type{T},::Type{T},::Type{T}) = T

function devresid!{T<:FP}(::Binomial,dr::Vector{T},y::Vector{T},
                                     mu::Vector{T},wt::Vector{T})
    map!(BinomialDevResid(), dr, y, mu, wt)
end
function devresid!{T<:FP}(::Poisson,dr::Vector{T},y::Vector{T},
                                     mu::Vector{T},wt::Vector{T})
    map!(PoissonDevResid(), dr, y, mu, wt)
end


text:
function run_Zilindroa(;

    #Time variables
    tspan::Array{Float64 , 1}   =   [0. , 0.]   ,
    dt::Float64                 =   0.05        ,
    out_every::Float64          =   1.0         ,
    max_run_time::String        =   "24:00:00"  ,

    #Spatial variables
    Nodes::Array{Int64 , 1}   =   [128 , 128]   ,
    Rcylinder::Float64        =   1.       ,
    Rcavity::Float64          =   30.       ,

    #Cylinder parameters
    Z::Float64              =   1.0     ,
    Omega::Float64          =   0.5     ,
    epsilon::Float64        =   0.0    ,

    #Initial configuration
    Gaussian_pulse:: Array{Float64, 1} = [ 3.5 , 3.7 , 20.  , 0.1 , 2 ],

    output_folder              = ""

    )

if(tspan[2] - tspan[1] < 0)
   println("ERROR: t_final must be larger than t_initial")
    return
end

#filename
folder_name = output_folder

if(output_folder == "")
    folder_name = string("/", Dates.today() , "/")
end

filename = string(
            "Zilindroa"             ,
            "_R1_"      , Rcylinder ,
            "_R2_"      , Rcavity   ,
            "_Z_"       , Z         ,
            "_eps_"     , epsilon   ,
            "_Omega_"   , Omega     ,
            "_Nr_"      , Nodes[1]  ,
            "_Nt_"      , Nodes[2]  ,
            "_ti_"      , tspan[1]  ,
             "_tf_"     , tspan[2] )

#Setup simulation
p0 = Param(

#Temporal variables
t_sim_init      = tspan[1]      ,
t_sim_final     = tspan[2]      ,
out_every_t     = out_every     ,
deltat          = dt            ,

max_runtime     = max_run_time  ,
#Spacial variables
rmin           =    Rcylinder   ,
rmax           =    Rcavity     ,
rnodes         =    Nodes[1]   ,

#Spacial variables
thnodes         =    Nodes[2]      ,

#Initial Conditions
A0              =   Gaussian_pulse[1] , #3.5         ,
σ               =   Gaussian_pulse[2] , #4.5         ,
r0              =   Gaussian_pulse[3] , #40.0        ,
ω               =   Gaussian_pulse[4] , #0.5         ,
m               =   Gaussian_pulse[5] , #2           ,

Z0              = Z         ,
ϵ               = epsilon   ,
Ω               = Omega     ,

#Data variables
folder          = folder_name   ,
fname           = filename

 )

solve_zilindroa_system(p0)

return 1
end


text:
# ## This is markdown title
# This is also markdown
## This is a normal comment
#
a = 1
b = a + 1
prinln(b)


text:
# Biryani -- A conversion and validation toolbox
# By: Emmanuel Raviart <emmanuel@raviart.com>
#
# Copyright (C) 2015 Emmanuel Raviart
# https://github.com/eraviart/Biryani.jl
#
# This file is part of Biryani.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module Biryani

export _, call, condition, Convertible, default, embed_error, empty_to_nothing, extract_when_singleton, fail,
  first_match, from_value, guess_bool, input_to_bool, input_to_email, input_to_float, input_to_int, input_to_ipv4,
  input_to_url_name, is_valid, item_or_sequence, item_to_singleton, log_info, log_warning, N_, noop, pipe, require,
  string_to_email, string_to_ipv4, strip, struct, test, test_between, test_equal, test_greater_or_equal, test_in,
  test_isa, test_nothing, to_bool, to_float, to_int, to_string, to_value, to_value_error, uniform_mapping,
  uniform_sequence

import Base: strip

import Compat: pipe
import DataStructures: OrderedDict

include("base.jl")

module DatesConverters

  export date_to_iso8601_string, iso8601_input_to_date, iso8601_string_to_date, to_date

  import ..Biryani: call, Context, Convertible, N_, pipe, strip, test

  include("dates.jl")

end  # module DatesConverters

module JsonConverters

  export input_to_json

  import JSON

  import ..Biryani: Convertible, N_

  include("json.jl")

end  # module JsonConverters

module SlugifyConverters

  export input_to_slug

  import Slugify: slugify

  import ..Biryani: Convertible

  include("slugify.jl")

end  # module SlugifyConverters

end  # module Biryani


text:
using DataArrays,DataFrames
using PyCall

@pyimport matplotlib.pyplot as plt
@pyimport matplotlib.figure as pyfigure

function main()

  path = "../ml-100k/u.data"
  df = readrel(path,'\t')

  num_ratings = aggregate(df,:rating,length)[:item_id_length]
  ratings = 1:5

  plt.bar(ratings,num_ratings)
  plt.xlabel("RATING_GIVEN")
  plt.ylabel("NUMBER_OF_RATINGS_GIVEN")
  plt.xticks([1,2,3,4,5])
#   plt.tick_params(axis="x")

#   plt.figure(figsize=(40,10))

  plt.show()

end

function readrel(relpath,delimiter=',')

  base = dirname(@__FILE__)

  if relpath[1] == '/'
    relpathwslash = relpath
  else
    relpathwslash = string("/",relpath)
  end

  path = string(base,relpathwslash)

  df = readtable(path,separator = delimiter)

  names!(df,[:user_id,:item_id,:rating,:timestamp])

  df

end

main()


text:
using Base.Test
using LibGit2

context(f::Function, s::String) = (println(s); f())

has_ssh() = begin
    keys = ["URL", "USER", "KEY", "PUBKEY", "PASSPHRASE"]
    for key in keys
        if !(haskey(ENV, "GITTEST_REMOTE_SSH_$key"))
            return false
        end
    end
    return true
end

has_git() = haskey(ENV, "GITTEST_REMOTE_GIT_URL")

ssh_key_credential() = CredSSHKey(ENV["GITTEST_REMOTE_SSH_USER"],
                                  ENV["GITTEST_REMOTE_SSH_PUBKEY"],
                                  ENV["GITTEST_REMOTE_SSH_KEY"],
                                  ENV["GITTEST_REMOTE_SSH_PASSPHRASE"])

if !has_git()
    warn("Skipping remote clone => test clone over git")
else
    dir = mktempdir()
    try
        repo = repo_clone(ENV["GITTEST_REMOTE_GIT_URL"], dir)
        @test isa(repo, GitRepo)
    finally
        rm(dir, recursive=true)
    end
end

if !has_ssh()
    warn("Skipping remote clone => test clone over ssh with credentials")
else
    dir = mktempdir()
    try
        repo = repo_clone(ENV["GITTEST_REMOTE_SSH_URL"], dir,
                          {:credentials => ssh_key_credential()})
        @test isa(repo, GitRepo)
    finally
        rm(dir, recursive=true)
    end
end

if !has_ssh()
    warn("Skipping remote clone => test clone over ssh with credentials callback")
else
    dir = mktempdir()
    try
        repo = repo_clone(ENV["GITTEST_REMOTE_SSH_URL"], dir,
                          {:credentials => (url, username, allowed_types) -> ssh_key_credential()})
        @test isa(repo, GitRepo)
    finally
        rm(dir, recursive=true)
    end
end

context("test clone callback args without username") do
    dir = mktempdir()
    gurl, gusername, gallowed_types = nothing, nothing, nothing
    #TODO: better error
    @test_throws ErrorException repo_clone("github.com:libgit2/TestGitRepository", dir, {
          :credentials => (args...) -> begin
            gurl, gusername, gallowed_types = args
            return nothing
          end
    })
    @test gurl == "github.com:libgit2/TestGitRepository"
    @test gusername == nothing
    for t in [:plaintext, :sshkey]
        @test in(t, gallowed_types)
    end
end

context("test clone callback args with username") do
    dir = mktempdir()
    gurl, gusername, gallowed_types = nothing, nothing, nothing
    #TODO: better error
    @test_throws ErrorException repo_clone("git@github.com:libgit2/TestGitRepository", dir, {
          :credentials => (args...) -> begin
            gurl, gusername, gallowed_types = args
            return nothing
          end
    })
    @test gurl == "git@github.com:libgit2/TestGitRepository"
    @test gusername == "git"
    for t in [:plaintext, :sshkey]
        @test in(t, gallowed_types)
    end
end

println(" \033[32;1mSUCCESS\033[0m")