text:
###############################################################################
#
#   acb.jl : Arb complex numbers
#
#   Copyright (C) 2015 Tommy Hofmann
#   Copyright (C) 2015 Fredrik Johansson
#
###############################################################################

import Base: real, imag, abs, conj, angle, sqrt, log, log1p, sin, cos,
             tan, cot, sinpi, cospi, sinh, cosh, tanh, coth, atan, gamma,
             lgamma, gamma

export one, onei, real, imag, conj, abs, inv, angle, isreal

export sqrt, rsqrt, log, log1p, exppii, sin, cos, tan, cot,
       sinpi, cospi, tanpi, cotpi, sincos, sincospi, sinh, cosh, tanh, coth,
       sinhcosh, atan, logsinpi, gamma, rgamma, lgamma, digamma, risingfac,
       risingfac2, polygamma, polylog, zeta, barnesg, logbarnesg, agm,
       erf, erfi, erfc, ei, si, ci, shi, chi, li, lioffset, expint, gamma,
       besselj, bessely, besseli, besselk, hyp1f1, hyp1f1r, hyperu, hyp2f1,
       jtheta, modeta, modj, modlambda, moddelta, ellipwp, ellipk, ellipe

###############################################################################
#
#   Basic manipulation
#
###############################################################################

elem_type(::Type{AcbField}) = acb

parent_type(::Type{acb}) = AcbField

doc"""
    base_ring(R::AcbField)
> Returns `Union{}` since an Arb complex field does not depend on any other
> ring.
"""
base_ring(R::AcbField) = Union{}

doc"""
    base_ring(a::acb)
> Returns `Union{}` since an Arb complex field does not depend on any other
> ring.
"""
base_ring(a::acb) = Union{}

doc"""
    parent(x::acb)
> Return the parent of the given Arb complex field element.
"""
parent(x::acb) = x.parent

isdomain_type(::Type{acb}) = true

isexact_type(::Type{acb}) = false

doc"""
    zero(R::AcbField)
> Return exact zero in the given Arb complex field.
"""
function zero(r::AcbField)
  z = acb()
  z.parent = r
  return z
end

doc"""
    one(R::AcbField)
> Return exact one in the given Arb complex field.
"""
function one(r::AcbField)
  z = acb()
  ccall((:acb_one, :libarb), Void, (Ref{acb}, ), z)
  z.parent = r
  return z
end

doc"""
    onei(R::AcbField)
> Return exact one times $i$ in the given Arb complex field.
"""
function onei(r::AcbField)
  z = acb()
  ccall((:acb_onei, :libarb), Void, (Ref{acb}, ), z)
  z.parent = r
  return z
end

doc"""
    accuracy_bits(x::acb)
> Return the relative accuracy of $x$ measured in bits, capped between
> `typemax(Int)` and `-typemax(Int)`.
"""
function accuracy_bits(x::acb)
  # bug in acb.h: rel_accuracy_bits is not in the library
  return -ccall((:acb_rel_error_bits, :libarb), Int, (Ref{acb},), x)
end

function deepcopy_internal(a::acb, dict::ObjectIdDict)
  b = parent(a)()
  ccall((:acb_set, :libarb), Void, (Ref{acb}, Ref{acb}), b, a)
  return b
end

# TODO: implement hash

################################################################################
#
#  Conversions
#
################################################################################

function convert(::Type{Complex128}, x::acb)
    re = ccall((:acb_real_ptr, :libarb), Ref{arb_struct}, (Ref{acb}, ), x)
    im = ccall((:acb_imag_ptr, :libarb), Ref{arb_struct}, (Ref{acb}, ), x)
    t = ccall((:arb_mid_ptr, :libarb), Ref{arf_struct}, (Ref{arb}, ), re)
    u = ccall((:arb_mid_ptr, :libarb), Ref{arf_struct}, (Ref{arb}, ), im)
    # 4 == round to nearest
    v = ccall((:arf_get_d, :libarb), Float64, (Ref{arf_struct}, Int), t, 4)
    w = ccall((:arf_get_d, :libarb), Float64, (Ref{arf_struct}, Int), u, 4)
    return complex(v, w)
end

################################################################################
#
#  Real and imaginary part
#
################################################################################

doc"""
    real(x::acb)
> Return the real part of $x$ as an `arb`.
"""
function real(x::acb)
  z = arb()
  ccall((:acb_get_real, :libarb), Void, (Ref{arb}, Ref{acb}), z, x)
  z.parent = ArbField(parent(x).prec)
  return z
end

doc"""
    imag(x::acb)
> Return the imaginary part of $x$ as an `arb`.
"""
function imag(x::acb)
  z = arb()
  ccall((:acb_get_imag, :libarb), Void, (Ref{arb}, Ref{acb}), z, x)
  z.parent = ArbField(parent(x).prec)
  return z
end

################################################################################
#
#  String I/O
#
################################################################################

function show(io::IO, x::acb)
  show(io, real(x))
  print(io, " + i*")
  show(io, imag(x))
end

function show(io::IO, x::AcbField)
  print(io, "Complex Field with ")
  print(io, prec(x))
  print(io, " bits of precision and error bounds")
end

needs_parentheses(x::acb) = true

################################################################################
#
#  Unary operations
#
################################################################################

function -(x::acb)
  z = parent(x)()
  ccall((:acb_neg, :libarb), Void, (Ref{acb}, Ref{acb}), z, x)
  return z
end

################################################################################
#
#  Binary operations
#
################################################################################

# acb - acb

for (s,f) in ((:+,"acb_add"), (:*,"acb_mul"), (://, "acb_div"), (:-,"acb_sub"), (:^,"acb_pow"))
  @eval begin
    function ($s)(x::acb, y::acb)
      z = parent(x)()
      ccall(($f, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
                           z, x, y, parent(x).prec)
      return z
    end
  end
end

for (f,s) in ((:+, "add"), (:-, "sub"), (:*, "mul"), (://, "div"), (:^, "pow"))
  @eval begin

    function ($f)(x::acb, y::UInt)
      z = parent(x)()
      ccall(($("acb_"*s*"_ui"), :libarb), Void,
                  (Ref{acb}, Ref{acb}, UInt, Int),
                  z, x, y, parent(x).prec)
      return z
    end

    function ($f)(x::acb, y::Int)
      z = parent(x)()
      ccall(($("acb_"*s*"_si"), :libarb), Void,
      (Ref{acb}, Ref{acb}, Int, Int), z, x, y, parent(x).prec)
      return z
    end

    function ($f)(x::acb, y::fmpz)
      z = parent(x)()
      ccall(($("acb_"*s*"_fmpz"), :libarb), Void,
                  (Ref{acb}, Ref{acb}, Ref{fmpz}, Int),
                  z, x, y, parent(x).prec)
      return z
    end

    function ($f)(x::acb, y::arb)
      z = parent(x)()
      ccall(($("acb_"*s*"_arb"), :libarb), Void,
                  (Ref{acb}, Ref{acb}, Ref{arb}, Int),
                  z, x, y, parent(x).prec)
      return z
    end
  end
end

+(x::UInt,y::acb) = +(y,x)
+(x::Int,y::acb) = +(y,x)
+(x::fmpz,y::acb) = +(y,x)
+(x::arb,y::acb) = +(y,x)

*(x::UInt,y::acb) = *(y,x)
*(x::Int,y::acb) = *(y,x)
*(x::fmpz,y::acb) = *(y,x)
*(x::arb,y::acb) = *(y,x)

//(x::UInt,y::acb) = (x == 1) ? inv(y) : parent(y)(x) // y
//(x::Int,y::acb) = (x == 1) ? inv(y) : parent(y)(x) // y
//(x::fmpz,y::acb) = isone(x) ? inv(y) : parent(y)(x) // y
//(x::arb,y::acb) = isone(x) ? inv(y) : parent(y)(x) // y

^(x::UInt,y::acb) = parent(y)(x) ^ y
^(x::Int,y::acb) = parent(y)(x) ^ y
^(x::fmpz,y::acb) = parent(y)(x) ^ y
^(x::arb,y::acb) = parent(y)(x) ^ y
^(x::Integer, y::acb) = fmpz(x)^y

function -(x::UInt, y::acb)
  z = parent(y)()
  ccall((:acb_sub_ui, :libarb), Void, (Ref{acb}, Ref{acb}, UInt, Int), z, y, x, parent(y).prec)
  ccall((:acb_neg, :libarb), Void, (Ref{acb}, Ref{acb}), z, z)
  return z
end

function -(x::Int, y::acb)
  z = parent(y)()
  ccall((:acb_sub_si, :libarb), Void, (Ref{acb}, Ref{acb}, Int, Int), z, y, x, parent(y).prec)
  ccall((:acb_neg, :libarb), Void, (Ref{acb}, Ref{acb}), z, z)
  return z
end

function -(x::fmpz, y::acb)
  z = parent(y)()
  ccall((:acb_sub_fmpz, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{fmpz}, Int), z, y, x, parent(y).prec)
  ccall((:acb_neg, :libarb), Void, (Ref{acb}, Ref{acb}), z, z)
  return z
end

function -(x::arb, y::acb)
  z = parent(y)()
  ccall((:acb_sub_arb, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{arb}, Int), z, y, x, parent(y).prec)
  ccall((:acb_neg, :libarb), Void, (Ref{acb}, Ref{acb}), z, z)
  return z
end

+(x::acb, y::Integer) = x + fmpz(y)

-(x::acb, y::Integer) = x - fmpz(y)

*(x::acb, y::Integer) = x*fmpz(y)

//(x::acb, y::Integer) = x//fmpz(y)

+(x::Integer, y::acb) = fmpz(x) + y

-(x::Integer, y::acb) = fmpz(x) - y

*(x::Integer, y::acb) = fmpz(x)*y

//(x::Integer, y::acb) = fmpz(x)//y

+(x::acb, y::fmpq) = x + parent(x)(y)
-(x::acb, y::fmpq) = x - parent(x)(y)
*(x::acb, y::fmpq) = x * parent(x)(y)
//(x::acb, y::fmpq) = x // parent(x)(y)
^(x::acb, y::fmpq) = x ^ parent(x)(y)

+(x::fmpq, y::acb) = parent(y)(x) + y
-(x::fmpq, y::acb) = parent(y)(x) - y
*(x::fmpq, y::acb) = parent(y)(x) * y
//(x::fmpq, y::acb) = parent(y)(x) // y
^(x::fmpq, y::acb) = parent(y)(x) ^ y

divexact(x::acb, y::acb) = x // y
divexact(x::fmpz, y::acb) = x // y
divexact(x::acb, y::fmpz) = x // y
divexact(x::Int, y::acb) = x // y
divexact(x::acb, y::Int) = x // y
divexact(x::UInt, y::acb) = x // y
divexact(x::acb, y::UInt) = x // y
divexact(x::fmpq, y::acb) = x // y
divexact(x::acb, y::fmpq) = x // y
divexact(x::arb, y::acb) = x // y
divexact(x::acb, y::arb) = x // y
divexact(x::Float64, y::acb) = x // y
divexact(x::acb, y::Float64) = x // y
divexact(x::BigFloat, y::acb) = x // y
divexact(x::acb, y::BigFloat) = x // y
divexact(x::Integer, y::acb) = x // y
divexact(x::acb, y::Integer) = x // y
divexact(x::Rational{T}, y::acb) where {T <: Integer} = x // y
divexact(x::acb, y::Rational{T}) where {T <: Integer} = x // y

/(x::acb, y::acb) = x // y
/(x::fmpz, y::acb) = x // y
/(x::acb, y::fmpz) = x // y
/(x::Int, y::acb) = x // y
/(x::acb, y::Int) = x // y
/(x::UInt, y::acb) = x // y
/(x::acb, y::UInt) = x // y
/(x::fmpq, y::acb) = x // y
/(x::acb, y::fmpq) = x // y
/(x::arb, y::acb) = x // y
/(x::acb, y::arb) = x // y

+(x::Rational{T}, y::acb) where {T <: Integer} = fmpq(x) + y
+(x::acb, y::Rational{T}) where {T <: Integer} = x + fmpq(y)
-(x::Rational{T}, y::acb) where {T <: Integer} = fmpq(x) - y
-(x::acb, y::Rational{T}) where {T <: Integer} = x - fmpq(y)
*(x::Rational{T}, y::acb) where {T <: Integer} = fmpq(x) * y
*(x::acb, y::Rational{T}) where {T <: Integer} = x * fmpq(y)
//(x::Rational{T}, y::acb) where {T <: Integer} = fmpq(x) // y
//(x::acb, y::Rational{T}) where {T <: Integer} = x // fmpq(y)
^(x::Rational{T}, y::acb) where {T <: Integer} = fmpq(x)^y
^(x::acb, y::Rational{T}) where {T <: Integer} = x ^ fmpq(y)

+(x::Float64, y::acb) = parent(y)(x) + y
+(x::acb, y::Float64) = x + parent(x)(y)
-(x::Float64, y::acb) = parent(y)(x) - y
-(x::acb, y::Float64) = x - parent(x)(y)
*(x::Float64, y::acb) = parent(y)(x) * y
*(x::acb, y::Float64) = x * parent(x)(y)
//(x::Float64, y::acb) = parent(y)(x) // y
//(x::acb, y::Float64) = x // parent(x)(y)
^(x::Float64, y::acb) = parent(y)(x)^y
^(x::acb, y::Float64) = x ^ parent(x)(y)

+(x::BigFloat, y::acb) = parent(y)(x) + y
+(x::acb, y::BigFloat) = x + parent(x)(y)
-(x::BigFloat, y::acb) = parent(y)(x) - y
-(x::acb, y::BigFloat) = x - parent(x)(y)
*(x::BigFloat, y::acb) = parent(y)(x) * y
*(x::acb, y::BigFloat) = x * parent(x)(y)
//(x::BigFloat, y::acb) = parent(y)(x) // y
//(x::acb, y::BigFloat) = x // parent(x)(y)
^(x::BigFloat, y::acb) = parent(y)(x)^y
^(x::acb, y::BigFloat) = x ^ parent(x)(y)

################################################################################
#
#  Comparison
#
################################################################################

doc"""
    isequal(x::acb, y::acb)
> Return `true` if the boxes $x$ and $y$ are precisely equal, i.e. their real
> and imaginary parts have the same midpoints and radii.
"""
function isequal(x::acb, y::acb)
  r = ccall((:acb_equal, :libarb), Cint, (Ref{acb}, Ref{acb}), x, y)
  return Bool(r)
end

function ==(x::acb, y::acb)
  r = ccall((:acb_eq, :libarb), Cint, (Ref{acb}, Ref{acb}), x, y)
  return Bool(r)
end

function !=(x::acb, y::acb)
  r = ccall((:acb_ne, :libarb), Cint, (Ref{acb}, Ref{acb}), x, y)
  return Bool(r)
end

==(x::acb,y::Int) = (x == parent(x)(y))
==(x::Int,y::acb) = (y == parent(y)(x))

==(x::acb,y::arb) = (x == parent(x)(y))
==(x::arb,y::acb) = (y == parent(y)(x))

==(x::acb,y::fmpz) = (x == parent(x)(y))
==(x::fmpz,y::acb) = (y == parent(y)(x))

==(x::acb,y::Integer) = x == fmpz(y)
==(x::Integer,y::acb) = fmpz(x) == y

==(x::acb,y::Float64) = (x == parent(x)(y))
==(x::Float64,y::acb) = (y == parent(y)(x))

!=(x::acb,y::Int) = (x != parent(x)(y))
!=(x::Int,y::acb) = (y != parent(y)(x))

!=(x::acb,y::arb) = (x != parent(x)(y))
!=(x::arb,y::acb) = (y != parent(y)(x))

!=(x::acb,y::fmpz) = (x != parent(x)(y))
!=(x::fmpz,y::acb) = (y != parent(y)(x))

!=(x::acb,y::Float64) = (x != parent(x)(y))
!=(x::Float64,y::acb) = (y != parent(y)(x))

################################################################################
#
#  Containment
#
################################################################################

doc"""
    overlaps(x::acb, y::acb)
> Returns `true` if any part of the box $x$ overlaps any part of the box $y$,
> otherwise return `false`.
"""
function overlaps(x::acb, y::acb)
  r = ccall((:acb_overlaps, :libarb), Cint, (Ref{acb}, Ref{acb}), x, y)
  return Bool(r)
end

doc"""
    contains(x::acb, y::acb)
> Returns `true` if the box $x$ contains the box $y$, otherwise return
> `false`.
"""
function contains(x::acb, y::acb)
  r = ccall((:acb_contains, :libarb), Cint, (Ref{acb}, Ref{acb}), x, y)
  return Bool(r)
end

doc"""
    contains(x::acb, y::fmpq)
> Returns `true` if the box $x$ contains the given rational value, otherwise
> return `false`.
"""
function contains(x::acb, y::fmpq)
  r = ccall((:acb_contains_fmpq, :libarb), Cint, (Ref{acb}, Ref{fmpq}), x, y)
  return Bool(r)
end

doc"""
    contains(x::acb, y::fmpz)
> Returns `true` if the box $x$ contains the given integer value, otherwise
> return `false`.
"""
function contains(x::acb, y::fmpz)
  r = ccall((:acb_contains_fmpz, :libarb), Cint, (Ref{acb}, Ref{fmpz}), x, y)
  return Bool(r)
end

function contains(x::acb, y::Int)
  v = fmpz(y)
  r = ccall((:acb_contains_fmpz, :libarb), Cint, (Ref{acb}, Ref{fmpz}), x, v)
  return Bool(r)
end

doc"""
    contains(x::acb, y::Integer)
> Returns `true` if the box $x$ contains the given integer value, otherwise
> return `false`.
"""
contains(x::acb, y::Integer) = contains(x, fmpz(y))

doc"""
    contains(x::acb, y::Rational{Integer})
> Returns `true` if the box $x$ contains the given rational value, otherwise
> return `false`.
"""
contains(x::acb, y::Rational{T}) where {T <: Integer} = contains(x, fmpz(y))

doc"""
    contains_zero(x::acb)
> Returns `true` if the box $x$ contains zero, otherwise return `false`.
"""
function contains_zero(x::acb)
   return Bool(ccall((:acb_contains_zero, :libarb), Cint, (Ref{acb},), x))
end

################################################################################
#
#  Predicates
#
################################################################################

function isunit(x::acb)
   !iszero(x)
end

doc"""
    iszero(x::acb)
> Return `true` if $x$ is certainly zero, otherwise return `false`.
"""
function iszero(x::acb)
   return Bool(ccall((:acb_is_zero, :libarb), Cint, (Ref{acb},), x))
end

doc"""
    isone(x::acb)
> Return `true` if $x$ is certainly zero, otherwise return `false`.
"""
function isone(x::acb)
   return Bool(ccall((:acb_is_one, :libarb), Cint, (Ref{acb},), x))
end

doc"""
    isfinite(x::acb)
> Return `true` if $x$ is finite, i.e. its real and imaginary parts have finite
> midpoint and radius, otherwise return `false`.
"""
function isfinite(x::acb)
   return Bool(ccall((:acb_is_finite, :libarb), Cint, (Ref{acb},), x))
end

doc"""
    isexact(x::acb)
> Return `true` if $x$ is exact, i.e. has its real and imaginary parts have
> zero radius, otherwise return `false`.
"""
function isexact(x::acb)
   return Bool(ccall((:acb_is_exact, :libarb), Cint, (Ref{acb},), x))
end

doc"""
    isint(x::acb)
> Return `true` if $x$ is an exact integer, otherwise return `false`.
"""
function isint(x::acb)
   return Bool(ccall((:acb_is_int, :libarb), Cint, (Ref{acb},), x))
end

doc"""
    isint(x::acb)
> Return `true` if $x$ is purely real, i.e. having zero imaginary part,
> otherwise return `false`.
"""
function isreal(x::acb)
   return Bool(ccall((:acb_is_real, :libarb), Cint, (Ref{acb},), x))
end

isnegative(x::acb) = isreal(x) && isnegative(real(x))

################################################################################
#
#  Absolute value
#
################################################################################

doc"""
    abs(x::acb)
> Return the complex absolute value of $x$.
"""
function abs(x::acb)
  z = arb()
  ccall((:acb_abs, :libarb), Void,
                (Ref{arb}, Ref{acb}, Int), z, x, parent(x).prec)
  z.parent = ArbField(parent(x).prec)
  return z
end

################################################################################
#
#  Inversion
#
################################################################################

doc"""
    inv(x::acb)
> Return the multiplicative inverse of $x$, i.e. $1/x$.
"""
function inv(x::acb)
  z = parent(x)()
  ccall((:acb_inv, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
  return z
end

################################################################################
#
#  Shifting
#
################################################################################

doc"""
    ldexp(x::acb, y::Int)
> Return $2^yx$. Note that $y$ can be positive, zero or negative.
"""
function ldexp(x::acb, y::Int)
  z = parent(x)()
  ccall((:acb_mul_2exp_si, :libarb), Void,
              (Ref{acb}, Ref{acb}, Int), z, x, y)
  return z
end

doc"""
    ldexp(x::acb, y::fmpz)
> Return $2^yx$. Note that $y$ can be positive, zero or negative.
"""
function ldexp(x::acb, y::fmpz)
  z = parent(x)()
  ccall((:acb_mul_2exp_fmpz, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{fmpz}), z, x, y)
  return z
end

################################################################################
#
#  Miscellaneous
#
################################################################################

doc"""
    trim(x::acb)
> Return an `acb` box containing $x$ but which may be more economical,
> by rounding off insignificant bits from midpoints.
"""
function trim(x::acb)
  z = parent(x)()
  ccall((:acb_trim, :libarb), Void, (Ref{acb}, Ref{acb}), z, x)
  return z
end

doc"""
    unique_integer(x::acb)
> Return a pair where the first value is a boolean and the second is an `fmpz`
> integer. The boolean indicates whether the box $x$ contains a unique
> integer. If this is the case, the second return value is set to this unique
> integer.
"""
function unique_integer(x::acb)
  z = fmpz()
  unique = ccall((:acb_get_unique_fmpz, :libarb), Int,
    (Ref{fmpz}, Ref{acb}), z, x)
  return (unique != 0, z)
end

doc"""
    conj(x::acb)
> Return the complex conjugate of $x$.
"""
function conj(x::acb)
  z = parent(x)()
  ccall((:acb_conj, :libarb), Void, (Ref{acb}, Ref{acb}), z, x)
  return z
end

doc"""
    angle(x::acb)
> Return the angle in radians that the complex vector $x$ makes with the
> positive real axis in a counterclockwise direction.
"""
function angle(x::acb)
  z = arb()
  ccall((:acb_arg, :libarb), Void,
                (Ref{arb}, Ref{acb}, Int), z, x, parent(x).prec)
  z.parent = ArbField(parent(x).prec)
  return z
end

################################################################################
#
#  Constants
#
################################################################################

function const_pi(r::AcbField)
  z = r()
  ccall((:acb_const_pi, :libarb), Void, (Ref{acb}, Int), z, prec(r))
  return z
end

################################################################################
#
#  Complex valued functions
#
################################################################################

# complex - complex functions

doc"""
    sqrt(x::acb)
> Return the square root of $x$.
"""
function sqrt(x::acb)
   z = parent(x)()
   ccall((:acb_sqrt, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    rsqrt(x::acb)
> Return the reciprocal of the square root of $x$, i.e. $1/\sqrt{x}$.
"""
function rsqrt(x::acb)
   z = parent(x)()
   ccall((:acb_rsqrt, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    log(x::acb)
> Return the principal branch of the logarithm of $x$.

"""
function log(x::acb)
   z = parent(x)()
   ccall((:acb_log, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    log1p(x::acb)
> Return $\log(1+x)$, evaluated accurately for small $x$.
"""
function log1p(x::acb)
   z = parent(x)()
   ccall((:acb_log1p, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    exp(x::acb)
> Return the exponential of $x$.
"""
function Base.exp(x::acb)
   z = parent(x)()
   ccall((:acb_exp, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    exppii(x::acb)
> Return the exponential of $\pi i x$.
"""
function exppii(x::acb)
   z = parent(x)()
   ccall((:acb_exp_pi_i, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    sin(x::acb)
> Return the sine of $x$.
"""
function sin(x::acb)
   z = parent(x)()
   ccall((:acb_sin, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    cos(x::acb)
> Return the cosine of $x$.
"""
function cos(x::acb)
   z = parent(x)()
   ccall((:acb_cos, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    tan(x::acb)
> Return the tangent of $x$.
"""
function tan(x::acb)
   z = parent(x)()
   ccall((:acb_tan, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    cot(x::acb)
> Return the cotangent of $x$.
"""
function cot(x::acb)
   z = parent(x)()
   ccall((:acb_cot, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    sinpi(x::acb)
> Return the sine of $\pi x$.
"""
function sinpi(x::acb)
   z = parent(x)()
   ccall((:acb_sin_pi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    cospi(x::acb)
> Return the cosine of $\pi x$.
"""
function cospi(x::acb)
   z = parent(x)()
   ccall((:acb_cos_pi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    tanpi(x::acb)
> Return the tangent of $\pi x$.
"""
function tanpi(x::acb)
   z = parent(x)()
   ccall((:acb_tan_pi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    cotpi(x::acb)
> Return the cotangent of $\pi x$.
"""
function cotpi(x::acb)
   z = parent(x)()
   ccall((:acb_cot_pi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    sinh(x::acb)
> Return the hyperbolic sine of $x$.
"""
function sinh(x::acb)
   z = parent(x)()
   ccall((:acb_sinh, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    cosh(x::acb)
> Return the hyperbolic cosine of $x$.
"""
function cosh(x::acb)
   z = parent(x)()
   ccall((:acb_cosh, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    tanh(x::acb)
> Return the hyperbolic tangent of $x$.
"""
function tanh(x::acb)
   z = parent(x)()
   ccall((:acb_tanh, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    coth(x::acb)
> Return the hyperbolic cotangent of $x$.
"""
function coth(x::acb)
   z = parent(x)()
   ccall((:acb_coth, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    atan(x::acb)
> Return the arctangent of $x$.
"""
function atan(x::acb)
   z = parent(x)()
   ccall((:acb_atan, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    logsinpi(x::acb)
> Return $\log\sin(\pi x)$, constructed without branch cuts off the real line.
"""
function logsinpi(x::acb)
   z = parent(x)()
   ccall((:acb_log_sin_pi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    gamma(x::acb)
> Return the Gamma function evaluated at $x$.
"""
function gamma(x::acb)
   z = parent(x)()
   ccall((:acb_gamma, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    rgamma(x::acb)
> Return the reciprocal of the Gamma function evaluated at $x$.
"""
function rgamma(x::acb)
   z = parent(x)()
   ccall((:acb_rgamma, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    lgamma(x::acb)
> Return the logarithm of the Gamma function evaluated at $x$.
"""
function lgamma(x::acb)
   z = parent(x)()
   ccall((:acb_lgamma, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    digamma(x::acb)
> Return the  logarithmic derivative of the gamma function evaluated at $x$,
> i.e. $\psi(x)$.
"""
function digamma(x::acb)
   z = parent(x)()
   ccall((:acb_digamma, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    zeta(x::acb)
> Return the Riemann zeta function evaluated at $x$.
"""
function zeta(x::acb)
   z = parent(x)()
   ccall((:acb_zeta, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    barnesg(x::acb)
> Return the Barnes $G$-function, evaluated at $x$.
"""
function barnesg(x::acb)
   z = parent(x)()
   ccall((:acb_barnes_g, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    logbarnesg(x::acb)
> Return the logarithm of the Barnes $G$-function, evaluated at $x$.
"""
function logbarnesg(x::acb)
   z = parent(x)()
   ccall((:acb_log_barnes_g, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    agm(x::acb)
> Return the arithmetic-geometric mean of $1$ and $x$.
"""
function agm(x::acb)
   z = parent(x)()
   ccall((:acb_agm1, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    erf(x::acb)
> Return the error function evaluated at $x$.
"""
function erf(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_erf, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    erfi(x::acb)
> Return the imaginary error function evaluated at $x$.
"""
function erfi(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_erfi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    erfc(x::acb)
> Return the complex error function evaluated at $x$.
"""
function erfc(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_erfc, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    ei(x::acb)
> Return the exponential integral evaluated at $x$.
"""
function ei(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_ei, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    si(x::acb)
> Return the sine integral evaluated at $x$.
"""
function si(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_si, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    ci(x::acb)
> Return the exponential cosine integral evaluated at $x$.
"""
function ci(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_ci, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    shi(x::acb)
> Return the hyperbolic sine integral evaluated at $x$.
"""
function shi(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_shi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    chi(x::acb)
> Return the hyperbolic cosine integral evaluated at $x$.
"""
function chi(x::acb)
   z = parent(x)()
   ccall((:acb_hypgeom_chi, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    modeta(x::acb)
> Return the Dedekind eta function $\eta(\tau)$ at $\tau = x$.
"""
function modeta(x::acb)
   z = parent(x)()
   ccall((:acb_modular_eta, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    modj(x::acb)
> Return the $j$-invariant $j(\tau)$ at $\tau = x$.
"""
function modj(x::acb)
   z = parent(x)()
   ccall((:acb_modular_j, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    modlambda(x::acb)
> Return the modular lambda function $\lambda(\tau)$ at $\tau = x$.
"""
function modlambda(x::acb)
   z = parent(x)()
   ccall((:acb_modular_lambda, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    moddelta(x::acb)
> Return the modular delta function $\Delta(\tau)$ at $\tau = x$.
"""
function moddelta(x::acb)
   z = parent(x)()
   ccall((:acb_modular_delta, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    ellipk(x::acb)
> Return the complete elliptic integral $K(x)$.
"""
function ellipk(x::acb)
   z = parent(x)()
   ccall((:acb_modular_elliptic_k, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    ellipe(x::acb)
> Return the complete elliptic integral $E(x)$.
"""
function ellipe(x::acb)
   z = parent(x)()
   ccall((:acb_modular_elliptic_e, :libarb), Void, (Ref{acb}, Ref{acb}, Int), z, x, parent(x).prec)
   return z
end

doc"""
    sincos(x::acb)
> Return a tuple $s, c$ consisting of the sine $s$ and cosine $c$ of $x$.
"""
function sincos(x::acb)
  s = parent(x)()
  c = parent(x)()
  ccall((:acb_sin_cos, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), s, c, x, parent(x).prec)
  return (s, c)
end

doc"""
    sincospi(x::acb)
> Return a tuple $s, c$ consisting of the sine $s$ and cosine $c$ of $\pi x$.
"""
function sincospi(x::acb)
  s = parent(x)()
  c = parent(x)()
  ccall((:acb_sin_cos_pi, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), s, c, x, parent(x).prec)
  return (s, c)
end

doc"""
    sinhcosh(x::acb)
> Return a tuple $s, c$ consisting of the hyperbolic sine and cosine of $x$.
"""
function sinhcosh(x::acb)
  s = parent(x)()
  c = parent(x)()
  ccall((:acb_sinh_cosh, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), s, c, x, parent(x).prec)
  return (s, c)
end

doc"""
    zeta(s::acb, a::acb)
> Return the Hurwitz zeta function $\zeta(s,a)$.
"""
function zeta(s::acb, a::acb)
  z = parent(s)()
  ccall((:acb_hurwitz_zeta, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, s, a, parent(s).prec)
  return z
end

doc"""
    polygamma(s::acb, a::acb)
> Return the generalised polygamma function $\psi(s,z)$.
"""
function polygamma(s::acb, a::acb)
  z = parent(s)()
  ccall((:acb_polygamma, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, s, a, parent(s).prec)
  return z
end

function risingfac(x::acb, n::UInt)
  z = parent(x)()
  ccall((:acb_rising_ui, :libarb), Void,
              (Ref{acb}, Ref{acb}, UInt, Int), z, x, n, parent(x).prec)
  return z
end

doc"""
    risingfac(x::acb, n::Int)
> Return the rising factorial $x(x + 1)\ldots (x + n - 1)$ as an Acb.
"""
risingfac(x::acb, n::Int) = n < 0 ? throw(DomainError()) : risingfac(x, UInt(n))

function risingfac2(x::acb, n::UInt)
  z = parent(x)()
  w = parent(x)()
  ccall((:acb_rising2_ui, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, UInt, Int), z, w, x, n, parent(x).prec)
  return (z, w)
end

doc"""
    risingfac2(x::acb, n::Int)
> Return a tuple containing the rising factorial $x(x + 1)\ldots (x + n - 1)$
> and its derivative.
"""
risingfac2(x::acb, n::Int) = n < 0 ? throw(DomainError()) : risingfac2(x, UInt(n))

doc"""
    polylog(s::acb, a::acb)
>
"""
function polylog(s::acb, a::acb)
  z = parent(s)()
  ccall((:acb_polylog, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, s, a, parent(s).prec)
  return z
end

doc"""
    polylog(s::Int, a::acb)
> Return the polylogarithm Li$_s(a)$.
"""
function polylog(s::Int, a::acb)
  z = parent(a)()
  ccall((:acb_polylog_si, :libarb), Void,
              (Ref{acb}, Int, Ref{acb}, Int), z, s, a, parent(a).prec)
  return z
end

doc"""
    li(x::acb)
> Return the logarithmic integral, evaluated at $x$.
"""
function li(x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_li, :libarb), Void,
              (Ref{acb}, Ref{acb}, Int, Int), z, x, 0, parent(x).prec)
  return z
end

doc"""
    lioffset(x::acb)
> Return the offset logarithmic integral, evaluated at $x$.
"""
function lioffset(x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_li, :libarb), Void,
              (Ref{acb}, Ref{acb}, Int, Int), z, x, 1, parent(x).prec)
  return z
end

doc"""
    expint(s::acb, x::acb)
> Return the generalised exponential integral $E_s(x)$.
"""
function expint(s::acb, x::acb)
  z = parent(s)()
  ccall((:acb_hypgeom_expint, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, s, x, parent(s).prec)
  return z
end

doc"""
    gamma(s::acb, x::acb)
> Return the upper incomplete gamma function $\Gamma(s,x)$.
"""
function gamma(s::acb, x::acb)
  z = parent(s)()
  ccall((:acb_hypgeom_gamma_upper, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int, Int), z, s, x, 0, parent(s).prec)
  return z
end

doc"""
    besselj(nu::acb, x::acb)
> Return the Bessel function $J_{\nu}(x)$.
"""
function besselj(nu::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_bessel_j, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, nu, x, parent(x).prec)
  return z
end

doc"""
    bessely(nu::acb, x::acb)
> Return the Bessel function $Y_{\nu}(x)$.
"""
function bessely(nu::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_bessel_y, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, nu, x, parent(x).prec)
  return z
end

doc"""
    besseli(nu::acb, x::acb)
> Return the Bessel function $I_{\nu}(x)$.
"""
function besseli(nu::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_bessel_i, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, nu, x, parent(x).prec)
  return z
end

doc"""
    besselk(nu::acb, x::acb)
> Return the Bessel function $K_{\nu}(x)$.
"""
function besselk(nu::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_bessel_k, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), z, nu, x, parent(x).prec)
  return z
end

doc"""
    hyp1f1(a::acb, b::acb, x::acb)
> Return the confluent hypergeometric function ${}_1F1(a,b,x)$.
"""
function hyp1f1(a::acb, b::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_m, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Int, Int), z, a, b, x, 0, parent(x).prec)
  return z
end

doc"""
    hyp1f1r(a::acb, b::acb, x::acb)
> Return the regularized confluent hypergeometric function
> ${}_1F1(a,b,x) / \Gamma(b)$.
"""
function hyp1f1r(a::acb, b::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_m, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Int, Int), z, a, b, x, 1, parent(x).prec)
  return z
end

doc"""
    hyperu(a::acb, b::acb, x::acb)
> Return the confluent hypergeometric function $U(a,b,x)$.
"""
function hyperu(a::acb, b::acb, x::acb)
  z = parent(x)()
  ccall((:acb_hypgeom_u, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Int), z, a, b, x, parent(x).prec)
  return z
end

doc"""
    hyp2f1(a::acb, b::acb, c::acb, x::acb)
> Return the Gauss hypergeometric function ${}_2F_1(a,b,c,x)$.
"""
function hyp2f1(a::acb, b::acb, c::acb, x::acb; flags=0)
  z = parent(x)()
  ccall((:acb_hypgeom_2f1, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Int, Int), z, a, b, c, x, flags, parent(x).prec)
  return z
end

doc"""
    jtheta(z::acb, tau::acb)
> Return a tuple of four elements containing the Jacobi theta function values
> $\theta_1, \theta_2, \theta_3, \theta_4$ evaluated at $z, \tau$.
"""
function jtheta(z::acb, tau::acb)
  t1 = parent(z)()
  t2 = parent(z)()
  t3 = parent(z)()
  t4 = parent(z)()
  ccall((:acb_modular_theta, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Ref{acb}, Int),
                t1, t2, t3, t4, z, tau, parent(z).prec)
  return (t1, t2, t3, t4)
end

doc"""
    ellipwp(z::acb, tau::acb)
> Return the Weierstrass elliptic function $\wp(z,\tau)$.
"""
function ellipwp(z::acb, tau::acb)
  r = parent(z)()
  ccall((:acb_modular_elliptic_p, :libarb), Void,
              (Ref{acb}, Ref{acb}, Ref{acb}, Int), r, z, tau, parent(z).prec)
  return r
end

doc"""
    agm(x::acb, y::acb)
> Return the arithmetic-geometric mean of $x$ and $y$.
"""
function agm(x::acb, y::acb)
  v = inv(y)
  if isfinite(v)
    return agm(x * v) * y
  else
    v = inv(x)
    return agm(y * v) * x
  end
end

################################################################################
#
#  Unsafe arithmetic
#
################################################################################

function zero!(z::acb)
   ccall((:acb_zero, :libarb), Void, (Ref{acb},), z)
   return z
end

function add!(z::acb, x::acb, y::acb)
  ccall((:acb_add, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
         z, x, y, parent(z).prec)
  return z
end

function addeq!(z::acb, y::acb)
  ccall((:acb_add, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
         z, z, y, parent(z).prec)
  return z
end

function sub!(z::acb, x::acb, y::acb)
  ccall((:acb_sub, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
        z, x, y, parent(z).prec)
  return z
end

function mul!(z::acb, x::acb, y::acb)
  ccall((:acb_mul, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
        z, x, y, parent(z).prec)
  return z
end

function div!(z::acb, x::acb, y::acb)
  ccall((:acb_div, :libarb), Void, (Ref{acb}, Ref{acb}, Ref{acb}, Int),
        z, x, y, parent(z).prec)
  return z
end

################################################################################
#
#  Unsafe setting
#
################################################################################

for (typeofx, passtoc) in ((acb, Ref{acb}), (Ref{acb}, Ref{acb}))
  for (f,t) in (("acb_set_si", Int), ("acb_set_ui", UInt),
                ("acb_set_d", Float64))
    @eval begin
      function _acb_set(x::($typeofx), y::($t))
        ccall(($f, :libarb), Void, (($passtoc), ($t)), x, y)
      end

      function _acb_set(x::($typeofx), y::($t), p::Int)
        _acb_set(x, y)
        ccall((:acb_set_round, :libarb), Void,
                    (($passtoc), ($passtoc), Int), x, x, p)
      end
    end
  end

  @eval begin
    function _acb_set(x::($typeofx), y::fmpz)
      ccall((:acb_set_fmpz, :libarb), Void, (($passtoc), Ref{fmpz}), x, y)
    end

    function _acb_set(x::($typeofx), y::fmpz, p::Int)
      ccall((:acb_set_round_fmpz, :libarb), Void,
                  (($passtoc), Ref{fmpz}, Int), x, y, p)
    end

    function _acb_set(x::($typeofx), y::fmpq, p::Int)
      ccall((:acb_set_fmpq, :libarb), Void,
                  (($passtoc), Ref{fmpq}, Int), x, y, p)
    end

    function _acb_set(x::($typeofx), y::arb)
      ccall((:acb_set_arb, :libarb), Void, (($passtoc), Ref{arb}), x, y)
    end

    function _acb_set(x::($typeofx), y::arb, p::Int)
      _acb_set(x, y)
      ccall((:acb_set_round, :libarb), Void,
                  (($passtoc), ($passtoc), Int), x, x, p)
    end

    function _acb_set(x::($typeofx), y::acb)
      ccall((:acb_set, :libarb), Void, (($passtoc), Ref{acb}), x, y)
    end

    function _acb_set(x::($typeofx), y::acb, p::Int)
      ccall((:acb_set_round, :libarb), Void,
                  (($passtoc), Ref{acb}, Int), x, y, p)
    end

    function _acb_set(x::($typeofx), y::AbstractString, p::Int)
      r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(r, y, p)
      i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      ccall((:arb_zero, :libarb), Void, (Ref{arb}, ), i)
    end

    function _acb_set(x::($typeofx), y::BigFloat)
      r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(r, y)
      i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      ccall((:arb_zero, :libarb), Void, (Ref{arb}, ), i)
    end

    function _acb_set(x::($typeofx), y::BigFloat, p::Int)
      r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(r, y, p)
      i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      ccall((:arb_zero, :libarb), Void, (Ref{arb}, ), i)
    end

    function _acb_set(x::($typeofx), y::Int, z::Int, p::Int)
      ccall((:acb_set_si_si, :libarb), Void,
                  (($passtoc), Int, Int), x, y, z)
      ccall((:acb_set_round, :libarb), Void,
                  (($passtoc), ($passtoc), Int), x, x, p)
    end

    function _acb_set(x::($typeofx), y::arb, z::arb)
      ccall((:acb_set_arb_arb, :libarb), Void,
                  (($passtoc), Ref{arb}, Ref{arb}), x, y, z)
    end

    function _acb_set(x::($typeofx), y::arb, z::arb, p::Int)
      _acb_set(x, y, z)
      ccall((:acb_set_round, :libarb), Void,
                  (($passtoc), ($passtoc), Int), x, x, p)
    end

    function _acb_set(x::($typeofx), y::fmpq, z::fmpq, p::Int)
      r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(r, y, p)
      i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(i, z, p)
    end

    function _acb_set(x::($typeofx), y::T, z::T, p::Int) where {T <: AbstractString}
      r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(r, y, p)
      i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
      _arb_set(i, z, p)
    end

  end

  for T in (Float64, BigFloat, UInt, fmpz)
    @eval begin
      function _acb_set(x::($typeofx), y::($T), z::($T))
        r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
        _arb_set(r, y)
        i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
        _arb_set(i, z)
      end

      function _acb_set(x::($typeofx), y::($T), z::($T), p::Int)
        r = ccall((:acb_real_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
        _arb_set(r, y, p)
        i = ccall((:acb_imag_ptr, :libarb), Ref{arb}, (($passtoc), ), x)
        _arb_set(i, z, p)
      end
    end
  end
end

################################################################################
#
#  Parent object overload
#
################################################################################

function (r::AcbField)()
  z = acb()
  z.parent = r
  return z
end

function (r::AcbField)(x::Union{Int, UInt, fmpz, fmpq, arb, acb, Float64,
                                BigFloat, AbstractString})
  z = acb(x, r.prec)
  z.parent = r
  return z
end

(r::AcbField)(x::Integer) = r(fmpz(x))

(r::AcbField)(x::Rational{T}) where {T <: Integer} = r(fmpq(x))

function (r::AcbField)(x::T, y::T) where {T <: Union{Int, UInt,fmpz, fmpq, arb, Float64, BigFloat, AbstractString}}
  z = acb(x, y, r.prec)
  z.parent = r
  return z
end

(r::AcbField)(x::BigInt, y::BigInt) = r(fmpz(x), fmpz(y))

(r::AcbField)(x::Rational{S}, y::Rational{T}) where {S <: Integer, T <: Integer} =
      r(fmpq(x), fmpq(y))

################################################################################
#
#  AcbField constructor
#
################################################################################

# see internal constructor


text:
using Timestamps, FinancialAssets, Reactive

module Grist

using Timestamps, FinancialAssets, Reactive

import Base: convert, show, getindex, start, next, done, isempty

export Blotter,
       transact, # helper method to update asset A
       res, vals, # from dev/tenblotters.jl
       txn, cash, A, mark_price, Pval, Aval # from dev/updates.jl

include("blotter.jl")
include("operators.jl")
include("../dev/tenblotters.jl")
include("../dev/updates.jl")
#include("../dev/run.jl")

end

ext: jl


text:
@testset "J" begin
    @test j1900() == 2415020.0
    @test j1950() == 2433282.5
    @test j2000() == 2451545.0
    @test j2100() == 2488070.0
    @test jyear() == 31557600.0
end


text:
module EDA

using CImGui
using CImGui.CSyntax
using CImGui.CSyntax.CStatic
using CImGui.GLFWBackend
using CImGui.OpenGLBackend
using CImGui.GLFWBackend.GLFW
using CImGui.OpenGLBackend.ModernGL
using CImGui: ImVec2, ImVec4, IM_COL32, ImS32, ImU32, ImS64, ImU64
using Printf
using DataFrames
#using Gadfly
using CSV
#using Images
#using Plots
#using Makie
using Dates

include("new_GUI.jl")

export
    parse_file,
    launch

end # module


text:
######Single qubit gates ###########

function U!(C::Circuit, U::AbstractArray{ComplexF64,2}, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    a = length(C.qreg)
    if (bitpos>a) || (bitpos<=0)
        error("The bit specified must be within the register of the circuit!")
    end
    Uf = sparse(U)
    M = similar(Uf)
    I2 = sparse(I*(1.0+0.0*im),2,2)
    for  i ∈ 1:a
        if (i == 1) && (i !== bitpos)
            copy!(M,I2)
        elseif (i == 1) && (i == bitpos)
            copy!(M,Uf)
        else
            if (i == bitpos)
                M = kron(Uf,M)
            else
                M = kron(I2,M)
            end
        end
    end
   return push!(C.gates, M)
end

function U!(C::Circuit, U::AbstractSparseArray{ComplexF64,Int}, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    a = length(C.qreg)
    if (bitpos>a) || (bitpos<=0)
        error("The bit specified must be within the register of the circuit!")
    end
    M = similar(U)
    I2 = sparse(I*(1.0+0.0*im),2,2)
    for  i ∈ 1:a
        if (i == 1) && (i !== bitpos)
            copy!(M,I2)
        elseif (i == 1) && (i == bitpos)
            copy!(M,U)
        else
            if (i == bitpos)
                M = kron(U,M)
            else
                M = kron(I2,M)
            end
        end
    end
   return push!(C.gates, M)
end

function U!(C::Circuit, λ::Float64, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#

    U = sparse([1.0  0.0
                0.0  exp(im*λ)])
    a = length(C.qreg)
    if (bitpos>a) || (bitpos<=0)
        error("The bit specified must be within the register of the circuit!")
    end
    M = similar(U)
    I2 = sparse(I*(1.0+0.0*im),2,2)
    for  i ∈ 1:a
        if (i == 1) && (i !== bitpos)
            copy!(M,I2)
        elseif (i == 1) && (i == bitpos)
            copy!(M,U)
        else
            if (i == bitpos)
                M = kron(U,M)
            else
                M = kron(I2,M)
            end
        end
    end
   return push!(C.gates, M)
end

##Specialized methods for doing multiple gates sequentially
function U!(C::Circuit, U::AbstractArray{ComplexF64,2}, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    for i in set
        U!(C,U,i)
    end
end

function U!(C::Circuit, U::AbstractSparseArray{ComplexF64,Int}, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    for i in set
        U!(C,U,i)
    end
end

##Specialized methods for doing multiple gates sequentially
function U!(C::Circuit, λ::Float64, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    for i in set
        U!(C,λ,i)
    end
end

function Udagger!(C::Circuit, λ::Float64, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#

    U = sparse([1.0  0.0
                0.0  conj(exp(im*λ))])
    a = length(C.qreg)
    if (bitpos>a) || (bitpos<=0)
        error("The bit specified must be within the register of the circuit!")
    end
    M = similar(U)
    I2 = sparse(I*(1.0+0.0*im),2,2)
    for  i ∈ 1:a
        if (i == 1) && (i !== bitpos)
            copy!(M,I2)
        elseif (i == 1) && (i == bitpos)
            copy!(M,U)
        else
            if (i == bitpos)
                M = kron(U,M)
            else
                M = kron(I2,M)
            end
        end
    end
   return push!(C.gates, M)
end

##Specialized methods for doing multiple gates sequentially
function Udagger!(C::Circuit, λ::Float64, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    for i in set
        Udagger!(C,λ,i)
    end
end
function H!(C::Circuit, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    H = sparse([1.0/sqrt(2)+0.0*im  1.0/sqrt(2)+0.0*im
                1.0/sqrt(2)+0.0*im -1.0/sqrt(2)+0.0*im])
    U!(C,H,bitpos)
end

function H!(C::Circuit, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    H = sparse([1.0/sqrt(2)+0.0*im  1.0/sqrt(2)+0.0*im
                1.0/sqrt(2)+0.0*im -1.0/sqrt(2)+0.0*im])
    U!(C,H,set)
end

function T!(C::Circuit, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    T = sparse([1.0+0.0*im  0.0+0.0*im
                0.0+0.0*im  exp(im*π/4)])
    U!(C,T,bitpos)
end

function T!(C::Circuit, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    T = sparse([1.0+0.0*im  0.0+0.0*im
                0.0+0.0*im  exp(im*π/4)])
    U!(C,T,set)
end

######## Pauli Gates ##########
function X!(C::Circuit, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    X = sparse([0.0+0.0*im  1.0+0.0*im
                1.0+0.0*im  0.0+0.0*im])
    U!(C,X,bitpos)
end

function X!(C::Circuit, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    X = sparse([0.0+0.0*im  1.0+0.0*im
                1.0+0.0*im  0.0+0.0*im])
    U!(C,X,set)
end

function Y!(C::Circuit, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    Y = sparse([0.0+0.0*im  0.0-1.0*im
                0.0+1.0*im  0.0+0.0*im])
    U!(C,Y,bitpos)
end

function Y!(C::Circuit, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    Y = sparse([0.0+0.0*im  0.0-1.0*im
                0.0+1.0*im  0.0+0.0*im])
    U!(C,Y,set)
end

function Z!(C::Circuit, bitpos::Int)
    #=Implementation that adds the new matrix into the gates field
    of the circuit=#
    Z = sparse([1.0+0.0*im  0.0+0.0*im
                0.0+0.0*im -1.0+0.0*im])
    U!(C,Z,bitpos)
end

function Z!(C::Circuit, set::AbstractVector{Int})
    #=Implementation that gives user ability to define
    a range of qubits to affect with the specified gate=#
    Z = sparse([1.0+0.0*im  0.0+0.0*im
                0.0+0.0*im -1.0+0.0*im])
    U!(C,Z,set)
end


text:
# ------------------------------------------------------------------
# Licensed under the ISC License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    AbstractPath

A path on a spatial object.
"""
abstract type AbstractPath end

"""
    traverse(object, path)

Traverse spatial `object` with `path`.
"""
function traverse end

# ----------------
# IMPLEMENTATIONS
# ----------------
include("paths/linear.jl")
include("paths/random.jl")
include("paths/source.jl")
include("paths/shifted.jl")


text:
precompile(Tuple{Base.var"#@show", LineNumberNode, Module, Vararg{Any}})
precompile(Tuple{typeof(Base.sprint), Function, Symbol})
precompile(Tuple{typeof(Base.show_unquoted), Base.GenericIOBuffer{Array{UInt8, 1}}, Symbol})
precompile(Tuple{Base.var"#@raw_str", LineNumberNode, Module, Any})
precompile(Tuple{Base.var"#@r_str", LineNumberNode, Module, Any, Vararg{Any}})
precompile(Tuple{Core.var"#@cmd", LineNumberNode, Module, Any})
precompile(Tuple{typeof(Base.deepcopy_internal), Any, Base.IdDict{Any, Any}})
precompile(Tuple{typeof(Base.:(==)), Base.UUID, Base.UUID})
precompile(Tuple{Base.var"##sprint#416", Nothing, Int64, typeof(Base.sprint), Function, UInt64})
precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, UInt64})
precompile(Tuple{Base.var"##sprint#416", Nothing, Int64, typeof(Base.sprint), Function, Type})
precompile(Tuple{typeof(Base.julia_cmd)})
precompile(Tuple{Type{NamedTuple{(:stderr, :stdout), T} where T<:Tuple}, Tuple{Base.TTY, Base.TTY}})
precompile(Tuple{Base.var"#pipeline##kw", NamedTuple{(:stderr, :stdout), Tuple{Base.TTY, Base.TTY}}, typeof(Base.pipeline), Base.Cmd})
precompile(Tuple{typeof(Base.open), Base.CmdRedirect, String, Base.TTY})
precompile(Tuple{typeof(Base.convert), Type{IO}, Base.PipeEndpoint})
precompile(Tuple{typeof(Base.getproperty), Base.Process, Symbol})
precompile(Tuple{typeof(Base.show), Base.GenericIOBuffer{Array{UInt8, 1}}, Array{String, 1}})
precompile(Tuple{Base.var"##sprint#416", Nothing, Int64, typeof(Base.sprint), Function, Core.TypeName})
precompile(Tuple{typeof(Base.write), Base.PipeEndpoint, String})
precompile(Tuple{typeof(Base.success), Base.Process})
precompile(Tuple{Base.var"##open#345", Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), Base.var"#843#845", String, Vararg{String}})
precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, UInt16})
precompile(Tuple{Base.Cartesian.var"#@ncall", LineNumberNode, Module, Int64, Any, Vararg{Any}})
precompile(Tuple{typeof(HeatEqCalc.calc_sol)})
precompile(Tuple{StaticArrays.var"##s26#2", Any, Any, Any, Any, Any})
precompile(Tuple{typeof(Base.ntuple), StaticArrays.var"#3#4", Base.Val{1}})
precompile(Tuple{Base.var"#@_inline_meta", LineNumberNode, Module})
precompile(Tuple{typeof(Base.copy), Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, HeatEqCalc.var"#f#1"{Int64, Array{Float64, 1}, Array{Float64, 1}}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}}})
precompile(Tuple{typeof(Base.Broadcast.combine_eltypes), Function, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}})
precompile(Tuple{typeof(Core.Compiler.return_type), Any, Any})
precompile(Tuple{typeof(Core.Compiler.return_type), Any, Any, UInt64})
precompile(Tuple{typeof(Core.Compiler.return_type), Core.Compiler.NativeInterpreter, Any, Any})
precompile(Tuple{typeof(Core.Compiler.typeinf_type), Core.Compiler.NativeInterpreter, Method, Any, Core.SimpleVector})
precompile(Tuple{typeof(Core.Compiler.contains_is), Core.SimpleVector, Any})
precompile(Tuple{Type{StaticArrays.Size{S} where S}, Type{Tuple{200}}})
precompile(Tuple{typeof(StaticArrays._Length), Int64})
precompile(Tuple{StaticArrays.var"##s46#188", Any, Any, Any, Any})
precompile(Tuple{Type{Base.Generator{I, F} where F where I}, StaticArrays.var"#189#190", Base.UnitRange{Int64}})
precompile(Tuple{typeof(Base.collect), Base.Generator{Base.UnitRange{Int64}, StaticArrays.var"#189#190"}})
precompile(Tuple{StaticArrays.var"##s26#6", Any, Any, Any, Any, Any, Type, Type, Type, Any})
precompile(Tuple{typeof(Base.all), Function, Core.SimpleVector})
precompile(Tuple{typeof(Base._all), StaticArrays.var"#7#8", Core.SimpleVector, Base.Colon})
precompile(Tuple{typeof(StaticArrays.tuple_prod), Type{Tuple{200}}})
precompile(Tuple{typeof(Base.length), Core.SimpleVector})
precompile(Tuple{typeof(Base.:(*)), Int64})
precompile(Tuple{typeof(StaticArrays.tuple_minimum), Type{Tuple{200}}})
precompile(Tuple{typeof(Base.minimum), Tuple{Int64}})
precompile(Tuple{typeof(StaticArrays.tuple_length), Type{Tuple{200}}})
precompile(Tuple{Type{StaticArrays.SArray{Tuple{200}, T, 1, 200} where T}, Array{Float64, 1}})
precompile(Tuple{typeof(Base.similar), Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, HeatEqCalc.var"#f#1"{Int64, Array{Float64, 1}, Array{Float64, 1}}, Tuple{Base.Broadcast.Extruded{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Tuple{Bool}, Tuple{Int64}}}}, Type{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}}})
precompile(Tuple{typeof(Base.setindex!), Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 1}, StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, Int64})
precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!), Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 1}, Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Tuple{Base.OneTo{Int64}}, HeatEqCalc.var"#f#1"{Int64, Array{Float64, 1}, Array{Float64, 1}}, Tuple{Base.Broadcast.Extruded{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Tuple{Bool}, Tuple{Int64}}}}, Base.OneTo{Int64}, Int64, Int64})
precompile(Tuple{StaticArrays.var"##s46#274", Any, Any, Any})
precompile(Tuple{typeof(Base.findfirst), StaticArrays.var"#275#278", Tuple{DataType, DataType}})
precompile(Tuple{Type{Array{Expr, 1}}, UndefInitializer, Int64})
precompile(Tuple{Type{Base.Generator{I, F} where F where I}, StaticArrays.var"#277#280"{Int64}, Base.UnitRange{Int64}})
precompile(Tuple{typeof(Base.collect), Base.Generator{Base.UnitRange{Int64}, StaticArrays.var"#277#280"{Int64}}})
precompile(Tuple{typeof(Base.setindex!), Array{Expr, 1}, Expr, Int64})
precompile(Tuple{typeof(Base.findfirst), StaticArrays.var"#275#278", Tuple{DataType}})
precompile(Tuple{typeof(HeatEqCalc.heateq4), Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 1}, Float64, Float64})
precompile(Tuple{Type{NamedTuple{(:t, :x, :u, :m), T} where T<:Tuple}, Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 2}, Int64}})
precompile(Tuple{typeof(HeatEqCalc.save_sol), NamedTuple{(:t, :x, :u, :m), Tuple{Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 2}, Int64}}})
precompile(Tuple{typeof(Base.iterate), Base.Generator{Base.UnitRange{Int64}, HeatEqCalc.var"#2#3"{Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 2}}}})
precompile(Tuple{typeof(Base.iterate), Base.Generator{Base.UnitRange{Int64}, HeatEqCalc.var"#2#3"{Array{StaticArrays.SArray{Tuple{200}, Float64, 1, 200}, 2}}}, Int64})
precompile(Tuple{typeof(Base.vcat), Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Vararg{Array{Float64, 2}}})
precompile(Tuple{typeof(Base.typed_vcat), Type{Float64}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Vararg{Array{Float64, 2}}})
precompile(Tuple{typeof(Base._typed_vcat), Type{Float64}, Tuple{Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}}})
precompile(Tuple{typeof(Base.afoldl), Base.MappingRF{Base.var"#130#132", Base.BottomRF{typeof(Base.add_sum)}}, Base._InitialValue, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Array{Float64, 2}, Vararg{Array{Float64, 2}}})
precompile(Tuple{Base.var"##open#345", Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), DelimitedFiles.var"#16#17"{Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Int64, Char}, String, Vararg{String}})
precompile(Tuple{Base.var"##open#345", Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), DelimitedFiles.var"#16#17"{Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Base.StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}, Char}, String, Vararg{String}})
precompile(Tuple{Base.var"##open#345", Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), DelimitedFiles.var"#16#17"{Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Array{Float64, 2}, Char}, String, Vararg{String}})

max_stars_repo_name: genkuroki/public

max_issues_repo_name: genkuroki/public

max_forks_repo_name: genkuroki/public


text:
import GeometryBasics
import Observables
import GLMakie
import AbstractPlotting

using Porta

# This model is inspired by exercise 3.12.3 from Mark J.D. Hamilton (2017)
# The best description at the moment is: the orbit of SU(2)×U(1) acting on the vacuum vector
# of the Higgs field

τ₁ = SU2([0im -im/2; -im/2 0im])
τ₂ = SU2([0im -1/2; 1/2 0im])
τ₃ = SU2([-im/2 0im; 0im im/2])
×(a::SU2, b::U1) = SU2(ℯ^(im * angle(b)) .* a.a)
gaction(A::SU2, u::U1, v::ComplexPlane) = ComplexPlane((A × u).a * vec(v))

orbit(α::Float64, v₀::Float64, segments::Int) = begin
    array = Array{ℝ³,2}(undef, segments, segments)
    colors = Array{ℝ³,2}(undef, segments, segments)
    θlspace = range(-π/2, stop = π/2, length = segments)
    ϕlspace = range(-π, stop = π, length = segments)
    p = ComplexPlane([0im; v₀ + 0im])
    q = Quaternion(p)
    u1 = U1(α)
    for (i, ϕ) in enumerate(ϕlspace)
        for (j, θ) in enumerate(θlspace)
            u = ℝ³(Cartesian(Geographic(1.0, ϕ, θ)))
            u₁, u₂, u₃ = vec(u)
            A = u₁ * τ₁ + u₂ * τ₂ + u₃ * τ₃
            p′ = gaction(A, u1, p)
            q′ = Quaternion(p′)
            normalized = normalize(q′)
            r3 = compressedλmap(normalized)
            scale = norm(q′)
            array[i, j] = r3 * scale * sign(v₀)
            hue = acos(dot(normalize(q), normalized)) / π * 360
            colors[i, j] = ℝ³(hsvtorgb([hue; 1.0; 1.0]))
        end
    end
    array, colors
end

interactive = false
segments = 36
frames = 240

scene3d = AbstractPlotting.Scene(camera = AbstractPlotting.cam3d_cad!)

v₀linspace = AbstractPlotting.LinRange(-1, 1, 100)
αlinsapce = AbstractPlotting.LinRange(-π, π, 100)
τ₃linsapce = AbstractPlotting.LinRange(0, 1, 100)
v₀slider, v₀observable = AbstractPlotting.textslider(v₀linspace, "v₀", raw = true,
                                                     camera = AbstractPlotting.campixel!,
                                                     start = 1)
αslider, αobservable = AbstractPlotting.textslider(αlinsapce, "α", raw = true,
                                                   camera = AbstractPlotting.campixel!,
                                                   start = 0)
τ₃slider, τ₃observable = AbstractPlotting.textslider(τ₃linsapce, "τ₃", raw = true,
                                                     camera = AbstractPlotting.campixel!,
                                                     start = 0)
transparency = true
α = π / 4
v₀ = 1.0
p = ComplexPlane([0im; v₀ + 0im])
r3 = compressedλmap(p)
config = Biquaternion(r3)
radius = 0.05
color = AbstractPlotting.RGBAf0(1.0, 0.2705, 0.0, 0.5)
sprite = Sphere(config, scene3d, radius = radius, segments = segments, color = color,
                transparency = transparency)
array, colors = orbit(α, v₀, segments)
colorarray = Observables.Observable(map(x -> AbstractPlotting.RGBAf0(vec(x)..., 0.9),
                                        colors))
#color = AbstractPlotting.RGBAf0(1.0, 0.2705, 0.0, 0.5)
#colorarray = Observables.Observable(fill(color, segments, segments))
observable = buildsurface(scene3d, array, colorarray, transparency = transparency)

animate() = begin
    α = Observables.to_value(αobservable)
    v₀ = Observables.to_value(v₀observable)
    τ₃coefficient = Observables.to_value(τ₃observable)
    A = (1 - τ₃coefficient) * (√2/2 * τ₁ + √2/2 * τ₂) + τ₃coefficient * τ₃
    array, colors = orbit(α, v₀, segments)
    updatesurface(array, observable)
    colorarray[] = map(x -> AbstractPlotting.RGBAf0(vec(x)..., 0.5), colors)
    p = ComplexPlane([0im; v₀ + 0im])
    u1 = U1(α)
    p′ = gaction(A, u1, p)
    r3 = compressedλmap(p′)
    config = Biquaternion(r3)
    update(sprite, config)
    q = normalize(Quaternion(p))
    q′ = normalize(Quaternion(p′))
    hue = acos(dot(q, q′)) / π * 360
    color = AbstractPlotting.RGBAf0(hsvtorgb([hue; 1.0; 1.0])..., 0.5)
    update(sprite, color)
end

Observables.on(v₀observable) do x animate() end
Observables.on(αobservable) do x animate() end
Observables.on(τ₃observable) do x animate() end

final = AbstractPlotting.hbox(scene3d, AbstractPlotting.vbox(v₀slider, αslider, τ₃slider),
                              parent = AbstractPlotting.Scene(resolution = (500, 500)))

n = ℝ³(0, 0, 1)
v = ℝ³(1, 1, 0.1) * 2
# update eye position
# scene.camera.eyeposition.val
upvector = GeometryBasics.Vec3f0(vec(n)...)
eyeposition = GeometryBasics.Vec3f0(vec(v)...)
lookat = GeometryBasics.Vec3f0(0, 0, 0)
AbstractPlotting.update_cam!(scene3d, eyeposition, lookat, upvector)
scene3d.center = false # prevent scene from recentering on display

animate(i) = begin
    t = (i - 1) / frames
    if i < frames / 2
        t = 2t
        α = t * 2π - π
        αobservable[] = α
        rangeindex = max(1, Int(100(α + π) ÷ 2pi))
        rangeindex = min(100, rangeindex)
        AbstractPlotting.move!(αslider[end], rangeindex)
    else
        t = 2(t - 0.5)
        v₀ = 2(t - 0.5)
        v₀observable[] = v₀
        rangeindex = max(1, Int(100(v₀ + 1) ÷ 2))
        rangeindex = min(100, rangeindex)
        AbstractPlotting.move!(v₀slider[end], rangeindex)
    end
end

if interactive
    path = joinpath("gallery", "interactions", "groupactions.mp4")
    AbstractPlotting.record(final, path; framerate = 30) do io
        for i = 1:900        # sampling time
            sleep(0.05)       # sampling rate
            AbstractPlotting.recordframe!(io) # record a new frame
        end
    end
else
    path = joinpath("gallery", "groupactions.gif")
    AbstractPlotting.record(final, path) do io
        for i in 1:frames
            animate(i) # animate the scene
            AbstractPlotting.recordframe!(io) # record a new frame
        end
    end
end


text:
using Test, QuHamiltonian
using Lattices
r = UndefRegion(4)

collect(sites(r))

length(sites(r))

max_stars_repo_name: Roger-luo/QuHamiltonian

max_issues_repo_name: Roger-luo/QuHamiltonian

max_forks_repo_name: Roger-luo/QuHamiltonian


text:
const gpuAState{T} = GPUArray{T,1}
const gpuAStateBatch{T} = GPUArray{T,2}
const gpuAStateBatchVec{T} = GPUArray{T,3}

const gpuADoubleState{T} = NTuple{2, gpuAState{T}} where T
const gpuADoubleStateBatch{T} = NTuple{2, gpuAStateBatch{T}} where T
const gpuADoubleStateBatchVec{T} = NTuple{2, gpuAStateBatchVec{T}} where T

function state_collect(s::Union{gpuADoubleStateBatchVec,gpuADoubleStateBatch,gpuADoubleState})
    return (state_collect(row(s)), state_collect(col(s)))
end

state_collect(s::Union{gpuAStateBatchVec,gpuAStateBatch,gpuAState}) = collect(s)

# efficient state generation for homogeneous spaces on gpu
# could be improved with a custom kernel...
function Random.rand!(rng::AbstractRNG, σ::Union{gpuAState,gpuAStateBatch}, h::HomogeneousFock{N}) where N
    T = eltype(σ)
    rand!(rng, σ) # must find a way to use an RNG in here...
    σ .*= N
    σ .= floor.(σ)
end


text:
using MetaUtils
using Test

x = 10

@testset "MetaUtils.jl" begin
    @test (@teval (:call, :+, (:call, :*, 2, :x), 1)) == 21
    @test (@teval (:+, (:*, 2, :x), 1)) == 21
    @test sprint(show_expr, :(2x + 1)) ==
        "Expr(:call, :+, \n    Expr(:call, :*, 2, :x), 1)"
    @test sprint(show_texpr, :(2x + 1)) ==
        "(:call, :+, \n    (:call, :*, 2, :x), 1)"
    @test sprint(print_subtypes, AbstractFloat) ==
        "AbstractFloat\n├─ BigFloat\n├─ Float16\n├─ Float32\n└─ Float64\n"
    @test sprint(print_subtypes, Ref) ==
        "Ref\n├─ Base.CFunction\n├─ Base.RefArray\n├─ Base.RefValue\n├─ Core.Compiler.RefValue\n├─ Core.LLVMPtr\n└─ Ptr\n"
end


text:
push!(LOAD_PATH,"../src/")

using ClimateMARGO
using Documenter, Literate

const EXAMPLES_DIR = joinpath(@__DIR__, "src/examples_literate")
const OUTPUT_DIR   = joinpath(@__DIR__, "src/generated")

print(@__DIR__)

examples = [
    "default_optimization.jl",
    "two_dimensional_optimization.jl"
]

for example in examples
    example_filepath = joinpath(EXAMPLES_DIR, example)
    Literate.markdown(example_filepath, OUTPUT_DIR, documenter=true)
end

#### Organize page structure
example_pages = [
    "Optimization with default parameters" => "generated/default_optimization.md",
    "Two-dimensional optimization" => "generated/two_dimensional_optimization.md"
]

pages = [
    "Home" => "index.md",
    "Installation instructions" => "installation_instructions.md",
    "Theory" => "theory.md",
    "Examples" => example_pages,
    "Submodules" => [
        "Domain" => "Submodules/Domain.md",
        "Physics" => "Submodules/Physics.md",
        "Economics" => "Submodules/Economics.md",
        "Controls" => "Submodules/Controls.md",
    ],
    "Diagnostics" => "diagnostics.md",
    "Optimization" => "optimization.md",
    "Function index" => "function_index.md"
]

makedocs(
    sitename="ClimateMARGO.jl",
    doctest = true,
    authors = "Henri F. Drake",
    format = Documenter.HTML(
        prettyurls = get(ENV, "CI", nothing) == "true",
    ),
    pages = pages
)

deploydocs(repo = "github.com/hdrake/ClimateMARGO.jl.git",)