diff --git a/previews/PR2003/api/array/index.html b/previews/PR2003/api/array/index.html new file mode 100644 index 0000000000..49a4f04ced --- /dev/null +++ b/previews/PR2003/api/array/index.html @@ -0,0 +1,6 @@ + +Array programming · CUDA.jl

Array programming

The CUDA array type, CuArray, generally implements the Base array interface and all of its expected methods.

diff --git a/previews/PR2003/api/compiler/index.html b/previews/PR2003/api/compiler/index.html new file mode 100644 index 0000000000..786117e802 --- /dev/null +++ b/previews/PR2003/api/compiler/index.html @@ -0,0 +1,17 @@ + +Compiler · CUDA.jl

Compiler

Execution

The main entry-point to the compiler is the @cuda macro:

CUDA.@cudaMacro
@cuda [kwargs...] func(args...)

High-level interface for executing code on a GPU. The @cuda macro should prefix a call, with func a callable function or object that should return nothing. It will be compiled to a CUDA function upon first use, and to a certain extent arguments will be converted and managed automatically using cudaconvert. Finally, a call to cudacall is performed, scheduling a kernel launch on the current CUDA context.

Several keyword arguments are supported that influence the behavior of @cuda.

  • launch: whether to launch this kernel, defaults to true. If false the returned kernel object should be launched by calling it and passing arguments again.
  • dynamic: use dynamic parallelism to launch device-side kernels, defaults to false.
  • arguments that influence kernel compilation: see cufunction and dynamic_cufunction
  • arguments that influence kernel launch: see CUDA.HostKernel and CUDA.DeviceKernel
source

If needed, you can use a lower-level API that lets you inspect the compiler kernel:

CUDA.cudaconvertFunction
cudaconvert(x)

This function is called for every argument to be passed to a kernel, allowing it to be converted to a GPU-friendly format. By default, the function does nothing and returns the input object x as-is.

Do not add methods to this function, but instead extend the underlying Adapt.jl package and register methods for the the CUDA.Adaptor type.

source
CUDA.cufunctionFunction
cufunction(f, tt=Tuple{}; kwargs...)

Low-level interface to compile a function invocation for the currently-active GPU, returning a callable kernel object. For a higher-level interface, use @cuda.

The following keyword arguments are supported:

  • minthreads: the required number of threads in a thread block
  • maxthreads: the maximum number of threads in a thread block
  • blocks_per_sm: a minimum number of thread blocks to be scheduled on a single multiprocessor
  • maxregs: the maximum number of registers to be allocated to a single thread (only supported on LLVM 4.0+)
  • name: override the name that the kernel will have in the generated code
  • always_inline: inline all function calls in the kernel

The output of this function is automatically cached, i.e. you can simply call cufunction in a hot path without degrading performance. New code will be generated automatically, when when function changes, or when different types or keyword arguments are provided.

source
CUDA.HostKernelType
(::HostKernel)(args...; kwargs...)
+(::DeviceKernel)(args...; kwargs...)

Low-level interface to call a compiled kernel, passing GPU-compatible arguments in args. For a higher-level interface, use @cuda.

The following keyword arguments are supported:

  • threads (defaults to 1)
  • blocks (defaults to 1)
  • shmem (defaults to 0)
  • stream (defaults to the default stream)
source
CUDA.versionFunction
version(k::HostKernel)

Queries the PTX and SM versions a kernel was compiled for. Returns a named tuple.

source
CUDA.maxthreadsFunction
maxthreads(k::HostKernel)

Queries the maximum amount of threads a kernel can use in a single block.

source
CUDA.memoryFunction
memory(k::HostKernel)

Queries the local, shared and constant memory usage of a compiled kernel in bytes. Returns a named tuple.

source

Reflection

If you want to inspect generated code, you can use macros that resemble functionality from the InteractiveUtils standard library:

@device_code_lowered
+@device_code_typed
+@device_code_warntype
+@device_code_llvm
+@device_code_ptx
+@device_code_sass
+@device_code

These macros are also available in function-form:

CUDA.code_typed
+CUDA.code_warntype
+CUDA.code_llvm
+CUDA.code_ptx
+CUDA.code_sass

For more information, please consult the GPUCompiler.jl documentation. Only the code_sass functionality is actually defined in CUDA.jl:

CUDA.code_sassFunction
code_sass([io], f, types; verbose=false)

Prints the SASS code generated for the method matching the given generic function and type signature to io which defaults to stdout.

The following keyword arguments are supported:

  • verbose: enable verbose mode, which displays code generation statistics
  • all keyword arguments from cufunction

See also: @device_code_sass

source
diff --git a/previews/PR2003/api/essentials/index.html b/previews/PR2003/api/essentials/index.html new file mode 100644 index 0000000000..b15daaf290 --- /dev/null +++ b/previews/PR2003/api/essentials/index.html @@ -0,0 +1,10 @@ + +Essentials · CUDA.jl

Essentials

Initialization

CUDA.functionalMethod
functional(show_reason=false)

Check if the package has been configured successfully and is ready to use.

This call is intended for packages that support conditionally using an available GPU. If you fail to check whether CUDA is functional, actual use of functionality might warn and error.

source
CUDA.has_cudaFunction
has_cuda()::Bool

Check whether the local system provides an installation of the CUDA driver and runtime. Use this function if your code loads packages that require CUDA.jl. ```

source
CUDA.has_cuda_gpuFunction
has_cuda_gpu()::Bool

Check whether the local system provides an installation of the CUDA driver and runtime, and if it contains a CUDA-capable GPU. See has_cuda for more details.

Note that this function initializes the CUDA API in order to check for the number of GPUs.

source

Global state

CUDA.contextFunction
context(ptr)

Identify the context a CUDA memory buffer was allocated in.

source
context()::CuContext

Get or create a CUDA context for the current thread (as opposed to current_context which may return nothing if there is no context bound to the current thread).

source
CUDA.context!Function
context!(ctx::CuContext)
+context!(ctx::CuContext) do ... end

Bind the current host thread to the context ctx. Returns the previously-bound context. If used with do-block syntax, the change is only temporary.

Note that the contexts used with this call should be previously acquired by calling context, and not arbitrary contexts created by calling the CuContext constructor.

source
CUDA.deviceFunction
device(::CuContext)

Returns the device for a context.

source
device(ptr)

Identify the device a CUDA memory buffer was allocated on.

source
device()::CuDevice

Get the CUDA device for the current thread, similar to how context() works compared to current_context().

source
CUDA.device!Function
device!(dev::Integer)
+device!(dev::CuDevice)
+device!(dev) do ... end

Sets dev as the current active device for the calling host thread. Devices can be specified by integer id, or as a CuDevice (slightly faster). Both functions can be used with do-block syntax, in which case the device is only changed temporarily, without changing the default device used to initialize new threads or tasks.

Calling this function at the start of a session will make sure CUDA is initialized (i.e., a primary context will be created and activated).

source
CUDA.device_reset!Function
device_reset!(dev::CuDevice=device())

Reset the CUDA state associated with a device. This call with release the underlying context, at which point any objects allocated in that context will be invalidated.

source
CUDA.streamFunction
stream()

Get the CUDA stream that should be used as the default one for the currently executing task.

source
CUDA.stream!Function
stream!(::CuStream)
+stream!(::CuStream) do ... end

Change the default CUDA stream for the currently executing task, temporarily if using the do-block version of this function.

source
diff --git a/previews/PR2003/api/kernel/index.html b/previews/PR2003/api/kernel/index.html new file mode 100644 index 0000000000..3fda829b5f --- /dev/null +++ b/previews/PR2003/api/kernel/index.html @@ -0,0 +1,80 @@ + +Kernel programming · CUDA.jl

Kernel programming

This section lists the package's public functionality that corresponds to special CUDA functions for use in device code. It is loosely organized according to the C language extensions appendix from the CUDA C programming guide. For more information about certain intrinsics, refer to the aforementioned NVIDIA documentation.

Indexing and dimensions

CUDA.warpsizeFunction
warpsize(dev::CuDevice)

Returns the warp size (in threads) of the device.

source
warpsize()::Int32

Returns the warp size (in threads).

source
CUDA.laneidFunction
laneid()::Int32

Returns the thread's lane within the warp.

source
CUDA.active_maskFunction
active_mask()

Returns a 32-bit mask indicating which threads in a warp are active with the current executing thread.

source

Device arrays

CUDA.jl provides a primitive, lightweight array type to manage GPU data organized in an plain, dense fashion. This is the device-counterpart to the CuArray, and implements (part of) the array interface as well as other functionality for use on the GPU:

CUDA.CuDeviceArrayType
CuDeviceArray{T,N,A}(ptr, dims, [maxsize])

Construct an N-dimensional dense CUDA device array with element type T wrapping a pointer, where N is determined from the length of dims and T is determined from the type of ptr. dims may be a single scalar, or a tuple of integers corresponding to the lengths in each dimension). If the rank N is supplied explicitly as in Array{T,N}(dims), then it must match the length of dims. The same applies to the element type T, which should match the type of the pointer ptr.

source
CUDA.ConstType
Const(A::CuDeviceArray)

Mark a CuDeviceArray as constant/read-only. The invariant guaranteed is that you will not modify an CuDeviceArray for the duration of the current kernel.

This API can only be used on devices with compute capability 3.5 or higher.

Warning

Experimental API. Subject to change without deprecation.

source

Memory types

Shared memory

CUDA.CuStaticSharedArrayFunction
CuStaticSharedArray(T::Type, dims) -> CuDeviceArray{T,N,AS.Shared}

Get an array of type T and dimensions dims (either an integer length or tuple shape) pointing to a statically-allocated piece of shared memory. The type should be statically inferable and the dimensions should be constant, or an error will be thrown and the generator function will be called dynamically.

source
CUDA.CuDynamicSharedArrayFunction
CuDynamicSharedArray(T::Type, dims, offset::Integer=0) -> CuDeviceArray{T,N,AS.Shared}

Get an array of type T and dimensions dims (either an integer length or tuple shape) pointing to a dynamically-allocated piece of shared memory. The type should be statically inferable or an error will be thrown and the generator function will be called dynamically.

Note that the amount of dynamic shared memory needs to specified when launching the kernel.

Optionally, an offset parameter indicating how many bytes to add to the base shared memory pointer can be specified. This is useful when dealing with a heterogeneous buffer of dynamic shared memory; in the case of a homogeneous multi-part buffer it is preferred to use view.

source

Texture memory

CUDA.CuDeviceTextureType
CuDeviceTexture{T,N,M,NC,I}

N-dimensional device texture with elements of type T. This type is the device-side counterpart of CuTexture{T,N,P}, and can be used to access textures using regular indexing notation. If NC is true, indices used by these accesses should be normalized, i.e., fall into the [0,1) domain. The I type parameter indicates the kind of interpolation that happens when indexing into this texture. The source memory of the texture is specified by the M parameter, either linear memory or a texture array.

Device-side texture objects cannot be created directly, but should be created host-side using CuTexture{T,N,P} and passed to the kernel as an argument.

Warning

Experimental API. Subject to change without deprecation.

source

Synchronization

CUDA.sync_threadsFunction
sync_threads()

Waits until all threads in the thread block have reached this point and all global and shared memory accesses made by these threads prior to sync_threads() are visible to all threads in the block.

source
CUDA.sync_threads_countFunction
sync_threads_count(predicate::Int32)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns the number of threads for which predicate evaluates to non-zero.

source
sync_threads_count(predicate::Bool)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns the number of threads for which predicate evaluates to true.

source
CUDA.sync_threads_andFunction
sync_threads_and(predicate::Int32)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns non-zero if and only if predicate evaluates to non-zero for all of them.

source
sync_threads_and(predicate::Bool)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns true if and only if predicate evaluates to true for all of them.

source
CUDA.sync_threads_orFunction
sync_threads_or(predicate::Int32)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns non-zero if and only if predicate evaluates to non-zero for any of them.

source
sync_threads_or(predicate::Bool)

Identical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns true if and only if predicate evaluates to true for any of them.

source
CUDA.sync_warpFunction
sync_warp(mask::Integer=0xffffffff)

Waits threads in the warp, selected by means of the bitmask mask, have reached this point and all global and shared memory accesses made by these threads prior to sync_warp() are visible to those threads in the warp. The default value for mask selects all threads in the warp.

Note

Requires CUDA >= 9.0 and sm_6.2

source
CUDA.threadfence_blockFunction
threadfence_block()

A memory fence that ensures that:

  • All writes to all memory made by the calling thread before the call to threadfence_block() are observed by all threads in the block of the calling thread as occurring before all writes to all memory made by the calling thread after the call to threadfence_block()
  • All reads from all memory made by the calling thread before the call to threadfence_block() are ordered before all reads from all memory made by the calling thread after the call to threadfence_block().
source
CUDA.threadfenceFunction
threadfence()

A memory fence that acts as threadfence_block for all threads in the block of the calling thread and also ensures that no writes to all memory made by the calling thread after the call to threadfence() are observed by any thread in the device as occurring before any write to all memory made by the calling thread before the call to threadfence().

Note that for this ordering guarantee to be true, the observing threads must truly observe the memory and not cached versions of it; this is requires the use of volatile loads and stores, which is not available from Julia right now.

source
CUDA.threadfence_systemFunction
threadfence_system()

A memory fence that acts as threadfence_block for all threads in the block of the calling thread and also ensures that all writes to all memory made by the calling thread before the call to threadfence_system() are observed by all threads in the device, host threads, and all threads in peer devices as occurring before all writes to all memory made by the calling thread after the call to threadfence_system().

source

Time functions

CUDA.clockFunction
clock(UInt32)

Returns the value of a per-multiprocessor counter that is incremented every clock cycle.

source
clock(UInt64)

Returns the value of a per-multiprocessor counter that is incremented every clock cycle.

source
CUDA.nanosleepFunction
nanosleep(t)

Puts a thread for a given amount t(in nanoseconds).

Note

Requires CUDA >= 10.0 and sm_6.2

source

Warp-level functions

Voting

The warp vote functions allow the threads of a given warp to perform a reduction-and-broadcast operation. These functions take as input a boolean predicate from each thread in the warp and evaluate it. The results of that evaluation are combined (reduced) across the active threads of the warp in one different ways, broadcasting a single return value to each participating thread.

CUDA.vote_allFunction
vote_all(predicate::Bool)
+vote_all_sync(mask::UInt32, predicate::Bool)

Evaluate predicate for all active threads of the warp and return whether predicate is true for all of them.

source
CUDA.vote_anyFunction
vote_any(predicate::Bool)
+vote_any_sync(mask::UInt32, predicate::Bool)

Evaluate predicate for all active threads of the warp and return whether predicate is true for any of them.

source
CUDA.vote_uniFunction
vote_uni(predicate::Bool)
+vote_uni_sync(mask::UInt32, predicate::Bool)

Evaluate predicate for all active threads of the warp and return whether predicate is the same for any of them.

source
CUDA.vote_ballotFunction
vote_ballot(predicate::Bool)
+vote_ballot_sync(mask::UInt32, predicate::Bool)

Evaluate predicate for all active threads of the warp and return an integer whose Nth bit is set if and only if predicate is true for the Nth thread of the warp and the Nth thread is active.

source

Shuffle

CUDA.shfl_syncFunction
shfl_sync(threadmask::UInt32, val, lane::Integer, width::Integer=32)

Shuffle a value from a directly indexed lane lane, and synchronize threads according to threadmask.

source
CUDA.shfl_up_syncFunction
shfl_up_sync(threadmask::UInt32, val, delta::Integer, width::Integer=32)

Shuffle a value from a lane with lower ID relative to caller, and synchronize threads according to threadmask.

source
CUDA.shfl_down_syncFunction
shfl_down_sync(threadmask::UInt32, val, delta::Integer, width::Integer=32)

Shuffle a value from a lane with higher ID relative to caller, and synchronize threads according to threadmask.

source
CUDA.shfl_xor_syncFunction
shfl_xor_sync(threadmask::UInt32, val, mask::Integer, width::Integer=32)

Shuffle a value from a lane based on bitwise XOR of own lane ID with mask, and synchronize threads according to threadmask.

source

Formatted Output

CUDA.@cushowMacro
@cushow(ex)

GPU analog of Base.@show. It comes with the same type restrictions as @cuprintf.

@cushow threadIdx().x
source
CUDA.@cuprintMacro
@cuprint(xs...)
+@cuprintln(xs...)

Print a textual representation of values xs to standard output from the GPU. The functionality builds on @cuprintf, and is intended as a more use friendly alternative of that API. However, that also means there's only limited support for argument types, handling 16/32/64 signed and unsigned integers, 32 and 64-bit floating point numbers, Cchars and pointers. For more complex output, use @cuprintf directly.

Limited string interpolation is also possible:

    @cuprint("Hello, World ", 42, "\n")
+    @cuprint "Hello, World $(42)\n"
source
CUDA.@cuprintlnMacro
@cuprint(xs...)
+@cuprintln(xs...)

Print a textual representation of values xs to standard output from the GPU. The functionality builds on @cuprintf, and is intended as a more use friendly alternative of that API. However, that also means there's only limited support for argument types, handling 16/32/64 signed and unsigned integers, 32 and 64-bit floating point numbers, Cchars and pointers. For more complex output, use @cuprintf directly.

Limited string interpolation is also possible:

    @cuprint("Hello, World ", 42, "\n")
+    @cuprint "Hello, World $(42)\n"
source
CUDA.@cuprintfMacro
@cuprintf("%Fmt", args...)

Print a formatted string in device context on the host standard output.

Note that this is not a fully C-compliant printf implementation; see the CUDA documentation for supported options and inputs.

Also beware that it is an untyped, and unforgiving printf implementation. Type widths need to match, eg. printing a 64-bit Julia integer requires the %ld formatting string.

source

Assertions

CUDA.@cuassertMacro
@assert cond [text]

Signal assertion failure to the CUDA driver if cond is false. Preferred syntax for writing assertions, mimicking Base.@assert. Message text is optionally displayed upon assertion failure.

Warning

A failed assertion will crash the GPU, so use sparingly as a debugging tool. Furthermore, the assertion might be disabled at various optimization levels, and thus should not cause any side-effects.

source

Atomics

A high-level macro is available to annotate expressions with:

CUDA.@atomicMacro
@atomic a[I] = op(a[I], val)
+@atomic a[I] ...= val

Atomically perform a sequence of operations that loads an array element a[I], performs the operation op on that value and a second value val, and writes the result back to the array. This sequence can be written out as a regular assignment, in which case the same array element should be used in the left and right hand side of the assignment, or as an in-place application of a known operator. In both cases, the array reference should be pure and not induce any side-effects.

Warn

This interface is experimental, and might change without warning. Use the lower-level atomic_...! functions for a stable API, albeit one limited to natively-supported ops.

source

If your expression is not recognized, or you need more control, use the underlying functions:

CUDA.atomic_cas!Function
atomic_cas!(ptr::LLVMPtr{T}, cmp::T, val::T)

Reads the value old located at address ptr and compare with cmp. If old equals to cmp, stores val at the same address. Otherwise, doesn't change the value old. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64. Additionally, on GPU hardware with compute capability 7.0+, values of type UInt16 are supported.

source
CUDA.atomic_xchg!Function
atomic_xchg!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr and stores val at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_add!Function
atomic_add!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes old + val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32, UInt64, and Float32. Additionally, on GPU hardware with compute capability 6.0+, values of type Float64 are supported.

source
CUDA.atomic_sub!Function
atomic_sub!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes old - val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_and!Function
atomic_and!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes old & val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_or!Function
atomic_or!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes old | val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_xor!Function
atomic_xor!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes old ⊻ val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_min!Function
atomic_min!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes min(old, val), and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_max!Function
atomic_max!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes max(old, val), and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.

This operation is supported for values of type Int32, Int64, UInt32 and UInt64.

source
CUDA.atomic_inc!Function
atomic_inc!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes ((old >= val) ? 0 : (old+1)), and stores the result back to memory at the same address. These three operations are performed in one atomic transaction. The function returns old.

This operation is only supported for values of type Int32.

source
CUDA.atomic_dec!Function
atomic_dec!(ptr::LLVMPtr{T}, val::T)

Reads the value old located at address ptr, computes (((old == 0) | (old > val)) ? val : (old-1) ), and stores the result back to memory at the same address. These three operations are performed in one atomic transaction. The function returns old.

This operation is only supported for values of type Int32.

source

Dynamic parallelism

Similarly to launching kernels from the host, you can use @cuda while passing dynamic=true for launching kernels from the device. A lower-level API is available as well:

CUDA.dynamic_cufunctionFunction
dynamic_cufunction(f, tt=Tuple{})

Low-level interface to compile a function invocation for the currently-active GPU, returning a callable kernel object. Device-side equivalent of CUDA.cufunction.

No keyword arguments are supported.

source
CUDA.DeviceKernelType
(::HostKernel)(args...; kwargs...)
+(::DeviceKernel)(args...; kwargs...)

Low-level interface to call a compiled kernel, passing GPU-compatible arguments in args. For a higher-level interface, use @cuda.

The following keyword arguments are supported:

  • threads (defaults to 1)
  • blocks (defaults to 1)
  • shmem (defaults to 0)
  • stream (defaults to the default stream)
source

CUDA runtime

Certain parts of the CUDA API are available for use on the GPU, for example to launch dynamic kernels or set-up cooperative groups. Coverage of this part of the API, provided by the libcudadevrt library, is under development and contributions are welcome.

CUDA.device_synchronizeFunction
device_synchronize()

Block for the all operations on ctx to complete. This is a heavyweight operation, typically you only need to call synchronize which only synchronizes the stream associated with the current task.

On the device, device_synchronize acts as a synchronization point for child grids in the context of dynamic parallelism.

source
CUDA.this_gridFunction
this_grid()

Returns a grid_handle of the grid group this thread belongs to. Only available if a cooperative kernel is launched.

source
CUDA.sync_gridFunction
sync_grid(grid_handle::Culonglong)

Waits until all threads in all blocks in the grid grid_handle have reached this point and all global memory accesses made by these threads prior to sync_grid() are visible to all threads in the grid. A 32-bit integer cudaError_t is returned.

source

Math

Many mathematical functions are provided by the libdevice library, and are wrapped by CUDA.jl. These functions are used to implement well-known functions from the Julia standard library and packages like SpecialFunctions.jl, e.g., calling the cos function will automatically use __nv_cos from libdevice if possible.

Some functions do not have a counterpart in the Julia ecosystem, those have to be called directly. For example, to call __nv_logb or __nv_logbf you use CUDA.logb in a kernel.

For a list of available functions, look at src/device/intrinsics/math.jl.

WMMA

Warp matrix multiply-accumulate (WMMA) is a CUDA API to access Tensor Cores, a new hardware feature in Volta GPUs to perform mixed precision matrix multiply-accumulate operations. The interface is split in two levels, both available in the WMMA submodule: low level wrappers around the LLVM intrinsics, and a higher-level API similar to that of CUDA C.

Note

Requires Julia v"1.4.0-DEV.666" or later, or you run into LLVM errors.

Note

For optimal performance, you should use Julia v1.5.0-DEV.324 or later.

Terminology

The WMMA operations perform a matrix multiply-accumulate. More concretely, it calculates $D = A \cdot B + C$, where $A$ is a $M \times K$ matrix, $B$ is a $K \times N$ matrix, and $C$ and $D$ are $M \times N$ matrices.

However, not all values of $M$, $N$ and $K$ are allowed. The tuple $(M, N, K)$ is often called the "shape" of the multiply accumulate operation.

The multiply-accumulate consists of the following steps:

  • Load the matrices $A$, $B$ and $C$ from memory to registers using a WMMA load operation.
  • Perform the matrix multiply-accumulate of $A$, $B$ and $C$ to obtain $D$ using a WMMA MMA operation. $D$ is stored in hardware registers after this step.
  • Store the result $D$ back to memory using a WMMA store operation.

Note that WMMA is a warp-wide operation, which means that all threads in a warp must cooperate, and execute the WMMA operations in lockstep. Failure to do so will result in undefined behaviour.

Each thread in a warp will hold a part of the matrix in its registers. In WMMA parlance, this part is referred to as a "fragment". Note that the exact mapping between matrix elements and fragment is unspecified, and subject to change in future versions.

Finally, it is important to note that the resultant $D$ matrix can be used as a $C$ matrix for a subsequent multiply-accumulate. This is useful if one needs to calculate a sum of the form $\sum_{i=0}^{n} A_i B_i$, where $A_i$ and $B_i$ are matrices of the correct dimension.

LLVM Intrinsics

The LLVM intrinsics are accessible by using the one-to-one Julia wrappers. The return type of each wrapper is the Julia type that corresponds closest to the return type of the LLVM intrinsic. For example, LLVM's [8 x <2 x half>] becomes NTuple{8, NTuple{2, VecElement{Float16}}} in Julia. In essence, these wrappers return the SSA values returned by the LLVM intrinsic. Currently, all intrinsics that are available in LLVM 6, PTX 6.0 and SM 70 are implemented.

These LLVM intrinsics are then lowered to the correct PTX instructions by the LLVM NVPTX backend. For more information about the PTX instructions, please refer to the PTX Instruction Set Architecture Manual.

The LLVM intrinsics are subdivided in three categories: load, store and multiply-accumulate. In what follows, each of these will be discussed.

Load matrix

CUDA.WMMA.llvm_wmma_loadFunction
WMMA.llvm_wmma_load_{matrix}_{layout}_{shape}_{addr_space}_stride_{elem_type}(src_addr, stride)

Wrapper around the LLVM intrinsic @llvm.nvvm.wmma.load.{matrix}.sync.{layout}.{shape}.{addr_space}.stride.{elem_type}.

Arguments

  • src_addr: The memory address to load from.
  • stride: The leading dimension of the matrix, in numbers of elements.

Placeholders

  • {matrix}: The matrix to load. Can be a, b or c.
  • {layout}: The storage layout for the matrix. Can be row or col, for row major (C style) or column major (Julia style), respectively.
  • {shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.
  • {addr_space}: The address space of src_addr. Can be empty (generic addressing), shared or global.
  • {elem_type}: The type of each element in the matrix. For a and b matrices, valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point). For c and d matrices, valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).
source

Perform multiply-accumulate

CUDA.WMMA.llvm_wmma_mmaFunction
WMMA.llvm_wmma_mma_{a_layout}_{b_layout}_{shape}_{d_elem_type}_{c_elem_type}(a, b, c) or
+WMMA.llvm_wmma_mma_{a_layout}_{b_layout}_{shape}_{a_elem_type}(a, b, c)

For floating point operations: wrapper around the LLVM intrinsic @llvm.nvvm.wmma.mma.sync.{a_layout}.{b_layout}.{shape}.{d_elem_type}.{c_elem_type} For all other operations: wrapper around the LLVM intrinsic @llvm.nvvm.wmma.mma.sync.{a_layout}.{b_layout}.{shape}.{a_elem_type}

Arguments

  • a: The WMMA fragment corresponding to the matrix $A$.
  • b: The WMMA fragment corresponding to the matrix $B$.
  • c: The WMMA fragment corresponding to the matrix $C$.

Placeholders

  • {a_layout}: The storage layout for matrix $A$. Can be row or col, for row major (C style) or column major (Julia style), respectively. Note that this must match the layout used in the load operation.
  • {b_layout}: The storage layout for matrix $B$. Can be row or col, for row major (C style) or column major (Julia style), respectively. Note that this must match the layout used in the load operation.
  • {shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.
  • {a_elem_type}: The type of each element in the $A$ matrix. Valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point).
  • {d_elem_type}: The type of each element in the resultant $D$ matrix. Valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).
  • {c_elem_type}: The type of each element in the $C$ matrix. Valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).
Warning

Remember that the shape, type and layout of all operations (be it MMA, load or store) MUST match. Otherwise, the behaviour is undefined!

source

Store matrix

CUDA.WMMA.llvm_wmma_storeFunction
WMMA.llvm_wmma_store_d_{layout}_{shape}_{addr_space}_stride_{elem_type}(dst_addr, data, stride)

Wrapper around the LLVM intrinsic @llvm.nvvm.wmma.store.d.sync.{layout}.{shape}.{addr_space}.stride.{elem_type}.

Arguments

  • dst_addr: The memory address to store to.
  • data: The $D$ fragment to store.
  • stride: The leading dimension of the matrix, in numbers of elements.

Placeholders

  • {layout}: The storage layout for the matrix. Can be row or col, for row major (C style) or column major (Julia style), respectively.
  • {shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.
  • {addr_space}: The address space of src_addr. Can be empty (generic addressing), shared or global.
  • {elem_type}: The type of each element in the matrix. For a and b matrices, valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point). For c and d matrices, valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).
source

Example

using Test
+
+using CUDA
+
+# Generate input matrices
+a     = rand(Float16, (16, 16))
+a_dev = CuArray(a)
+b     = rand(Float16, (16, 16))
+b_dev = CuArray(b)
+c     = rand(Float32, (16, 16))
+c_dev = CuArray(c)
+
+# Allocate space for result
+d_dev = similar(c_dev)
+
+# Matrix multiply-accumulate kernel (D = A * B + C)
+function kernel(a_dev, b_dev, c_dev, d_dev)
+    a_frag = WMMA.llvm_wmma_load_a_col_m16n16k16_global_stride_f16(pointer(a_dev), 16)
+    b_frag = WMMA.llvm_wmma_load_b_col_m16n16k16_global_stride_f16(pointer(b_dev), 16)
+    c_frag = WMMA.llvm_wmma_load_c_col_m16n16k16_global_stride_f32(pointer(c_dev), 16)
+
+    d_frag = WMMA.llvm_wmma_mma_col_col_m16n16k16_f32_f32(a_frag, b_frag, c_frag)
+
+    WMMA.llvm_wmma_store_d_col_m16n16k16_global_stride_f32(pointer(d_dev), d_frag, 16)
+    return
+end
+
+@cuda threads=32 kernel(a_dev, b_dev, c_dev, d_dev)
+@test all(isapprox.(a * b + c, Array(d_dev); rtol=0.01))

CUDA C-like API

The main difference between the CUDA C-like API and the lower level wrappers, is that the former enforces several constraints when working with WMMA. For example, it ensures that the $A$ fragment argument to the MMA instruction was obtained by a load_a call, and not by a load_b or load_c. Additionally, it makes sure that the data type and storage layout of the load/store operations and the MMA operation match.

The CUDA C-like API heavily uses Julia's dispatch mechanism. As such, the method names are much shorter than the LLVM intrinsic wrappers, as most information is baked into the type of the arguments rather than the method name.

Note that, in CUDA C++, the fragment is responsible for both the storage of intermediate results and the WMMA configuration. All CUDA C++ WMMA calls are function templates that take the resultant fragment as a by-reference argument. As a result, the type of this argument can be used during overload resolution to select the correct WMMA instruction to call.

In contrast, the API in Julia separates the WMMA storage (WMMA.Fragment) and configuration (WMMA.Config). Instead of taking the resultant fragment by reference, the Julia functions just return it. This makes the dataflow clearer, but it also means that the type of that fragment cannot be used for selection of the correct WMMA instruction. Thus, there is still a limited amount of information that cannot be inferred from the argument types, but must nonetheless match for all WMMA operations, such as the overall shape of the MMA. This is accomplished by a separate "WMMA configuration" (see WMMA.Config) that you create once, and then give as an argument to all intrinsics.

Fragment

CUDA.WMMA.UnspecifiedType
WMMA.Unspecified

Type that represents a matrix stored in an unspecified order.

Warning

This storage format is not valid for all WMMA operations!

source
CUDA.WMMA.FragmentType
WMMA.Fragment

Type that represents per-thread intermediate results of WMMA operations.

You can access individual elements using the x member or [] operator, but beware that the exact ordering of elements is unspecified.

source

WMMA configuration

CUDA.WMMA.ConfigType
WMMA.Config{M, N, K, d_type}

Type that contains all information for WMMA operations that cannot be inferred from the argument's types.

WMMA instructions calculate the matrix multiply-accumulate operation $D = A \cdot B + C$, where $A$ is a $M \times K$ matrix, $B$ a $K \times N$ matrix, and $C$ and $D$ are $M \times N$ matrices.

d_type refers to the type of the elements of matrix $D$, and can be either Float16 or Float32.

All WMMA operations take a Config as their final argument.

Examples

julia> config = WMMA.Config{16, 16, 16, Float32}
+CUDA.WMMA.Config{16, 16, 16, Float32}
source

Load matrix

CUDA.WMMA.load_aFunction
WMMA.load_a(addr, stride, layout, config)
+WMMA.load_b(addr, stride, layout, config)
+WMMA.load_c(addr, stride, layout, config)

Load the matrix a, b or c from the memory location indicated by addr, and return the resulting WMMA.Fragment.

Arguments

  • addr: The address to load the matrix from.
  • stride: The leading dimension of the matrix pointed to by addr, specified in number of elements.
  • layout: The storage layout of the matrix. Possible values are WMMA.RowMajor and WMMA.ColMajor.
  • config: The WMMA configuration that should be used for loading this matrix. See WMMA.Config.

See also: WMMA.Fragment, WMMA.FragmentLayout, WMMA.Config

Warning

All threads in a warp MUST execute the load operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.

source

WMMA.load_b and WMMA.load_c have the same signature.

Perform multiply-accumulate

CUDA.WMMA.mmaFunction
WMMA.mma(a, b, c, conf)

Perform the matrix multiply-accumulate operation $D = A \cdot B + C$.

Arguments

Warning

All threads in a warp MUST execute the mma operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.

source

Store matrix

CUDA.WMMA.store_dFunction
WMMA.store_d(addr, d, stride, layout, config)

Store the result matrix d to the memory location indicated by addr.

Arguments

  • addr: The address to store the matrix to.
  • d: The WMMA.Fragment corresponding to the d matrix.
  • stride: The leading dimension of the matrix pointed to by addr, specified in number of elements.
  • layout: The storage layout of the matrix. Possible values are WMMA.RowMajor and WMMA.ColMajor.
  • config: The WMMA configuration that should be used for storing this matrix. See WMMA.Config.

See also: WMMA.Fragment, WMMA.FragmentLayout, WMMA.Config

Warning

All threads in a warp MUST execute the store operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.

source

Fill fragment

CUDA.WMMA.fill_cFunction
WMMA.fill_c(value, config)

Return a WMMA.Fragment filled with the value value.

This operation is useful if you want to implement a matrix multiplication (and thus want to set $C = O$).

Arguments

  • value: The value used to fill the fragment. Can be a Float16 or Float32.
  • config: The WMMA configuration that should be used for this WMMA operation. See WMMA.Config.
source

Element access and broadcasting

Similar to the CUDA C++ WMMA API, WMMA.Fragments have an x member that can be used to access individual elements. Note that, in contrast to the values returned by the LLVM intrinsics, the x member is flattened. For example, while the Float16 variants of the load_a instrinsics return NTuple{8, NTuple{2, VecElement{Float16}}}, the x member has type NTuple{16, Float16}.

Typically, you will only need to access the x member to perform elementwise operations. This can be more succinctly expressed using Julia's broadcast mechanism. For example, to double each element in a fragment, you can simply use:

frag = 2.0f0 .* frag

Example

using Test
+
+using CUDA
+
+a     = rand(Float16, (16, 16))
+b     = rand(Float16, (16, 16))
+c     = rand(Float32, (16, 16))
+
+a_dev = CuArray(a)
+b_dev = CuArray(b)
+c_dev = CuArray(c)
+d_dev = similar(c_dev)
+
+function kernel(a_dev, b_dev, c_dev, d_dev)
+    conf = WMMA.Config{16, 16, 16, Float32}
+
+    a_frag = WMMA.load_a(pointer(a_dev), 16, WMMA.ColMajor, conf)
+    b_frag = WMMA.load_b(pointer(b_dev), 16, WMMA.ColMajor, conf)
+    c_frag = WMMA.load_c(pointer(c_dev), 16, WMMA.ColMajor, conf)
+
+    c_frag = 0.5f0 .* c_frag
+
+    d_frag = WMMA.mma(a_frag, b_frag, c_frag, conf)
+
+    WMMA.store_d(pointer(d_dev), d_frag, 16, WMMA.ColMajor, conf)
+
+    return
+end
+
+@cuda threads=32 kernel(a_dev, b_dev, c_dev, d_dev)
+d = Array(d_dev)
+
+@test all(isapprox.(a * b + 0.5 * c, d; rtol=0.01))
diff --git a/previews/PR2003/assets/documenter.js b/previews/PR2003/assets/documenter.js new file mode 100644 index 0000000000..6adfbbbf4b --- /dev/null +++ b/previews/PR2003/assets/documenter.js @@ -0,0 +1,331 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/julia.min', + 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min', + 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/contrib/auto-render.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min', + 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', + 'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/julia-repl.min', + }, + shim: { + "highlight-julia": { + "deps": [ + "highlight" + ] + }, + "katex-auto-render": { + "deps": [ + "katex" + ] + }, + "headroom-jquery": { + "deps": [ + "jquery", + "headroom" + ] + }, + "highlight-julia-repl": { + "deps": [ + "highlight" + ] + } +} +}); +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) { +$(document).ready(function() { + renderMathInElement( + document.body, + { + "delimiters": [ + { + "left": "$", + "right": "$", + "display": false + }, + { + "left": "$$", + "right": "$$", + "display": true + }, + { + "left": "\\[", + "right": "\\]", + "display": true + } + ] +} + + ); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) { +$(document).ready(function() { + hljs.highlightAll(); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require([], function() { +function addCopyButtonCallbacks() { + for (const el of document.getElementsByTagName("pre")) { + const button = document.createElement("button"); + button.classList.add("copy-button", "fas", "fa-copy"); + el.appendChild(button); + + const success = function () { + button.classList.add("success", "fa-check"); + button.classList.remove("fa-copy"); + }; + + const failure = function () { + button.classList.add("error", "fa-times"); + button.classList.remove("fa-copy"); + }; + + button.addEventListener("click", function () { + copyToClipboard(el.innerText).then(success, failure); + + setTimeout(function () { + button.classList.add("fa-copy"); + button.classList.remove("success", "fa-check", "fa-times"); + }, 5000); + }); + } +} + +function copyToClipboard(text) { + // clipboard API is only available in secure contexts + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(text); + } else { + return new Promise(function (resolve, reject) { + try { + const el = document.createElement("textarea"); + el.textContent = text; + el.style.position = "fixed"; + el.style.opacity = 0; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + + resolve(); + } catch (err) { + reject(err); + } finally { + document.body.removeChild(el); + } + }); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks); +} else { + addCopyButtonCallbacks(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { + +// Manages the top navigation bar (hides it when the user starts scrolling down on the +// mobile). +window.Headroom = Headroom; // work around buggy module loading? +$(document).ready(function() { + $('#documenter .docs-navbar').headroom({ + "tolerance": {"up": 10, "down": 10}, + }); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Modal settings dialog +$(document).ready(function() { + var settings = $('#documenter-settings'); + $('#documenter-settings-button').click(function(){ + settings.toggleClass('is-active'); + }); + // Close the dialog if X is clicked + $('#documenter-settings button.delete').click(function(){ + settings.removeClass('is-active'); + }); + // Close dialog if ESC is pressed + $(document).keyup(function(e) { + if (e.keyCode == 27) settings.removeClass('is-active'); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Manages the showing and hiding of the sidebar. +$(document).ready(function() { + var sidebar = $("#documenter > .docs-sidebar"); + var sidebar_button = $("#documenter-sidebar-button") + sidebar_button.click(function(ev) { + ev.preventDefault(); + sidebar.toggleClass('visible'); + if (sidebar.hasClass('visible')) { + // Makes sure that the current menu item is visible in the sidebar. + $("#documenter .docs-menu a.is-active").focus(); + } + }); + $("#documenter > .docs-main").bind('click', function(ev) { + if ($(ev.target).is(sidebar_button)) { + return; + } + if (sidebar.hasClass('visible')) { + sidebar.removeClass('visible'); + } + }); +}) + +// Resizes the package name / sitename in the sidebar if it is too wide. +// Inspired by: https://github.com/davatron5000/FitText.js +$(document).ready(function() { + e = $("#documenter .docs-autofit"); + function resize() { + var L = parseInt(e.css('max-width'), 10); + var L0 = e.width(); + if(L0 > L) { + var h0 = parseInt(e.css('font-size'), 10); + e.css('font-size', L * h0 / L0); + // TODO: make sure it survives resizes? + } + } + // call once and then register events + resize(); + $(window).resize(resize); + $(window).on('orientationchange', resize); +}); + +// Scroll the navigation bar to the currently selected menu item +$(document).ready(function() { + var sidebar = $("#documenter .docs-menu").get(0); + var active = $("#documenter .docs-menu .is-active").get(0); + if(typeof active !== 'undefined') { + sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; + } +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +function set_theme(theme) { + var active = null; + var disabled = []; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + var themename = ss.ownerNode.getAttribute("data-theme-name"); + if(themename === null) continue; // ignore non-theme stylesheets + // Find the active theme + if(themename === theme) active = ss; + else disabled.push(ss); + } + if(active !== null) { + active.disabled = false; + if(active.ownerNode.getAttribute("data-theme-primary") === null) { + document.getElementsByTagName('html')[0].className = "theme--" + theme; + } else { + document.getElementsByTagName('html')[0].className = ""; + } + disabled.forEach(function(ss){ + ss.disabled = true; + }); + } + + // Store the theme in localStorage + if(typeof(window.localStorage) !== "undefined") { + window.localStorage.setItem("documenter-theme", theme); + } else { + console.error("Browser does not support window.localStorage"); + } +} + +// Theme picker setup +$(document).ready(function() { + // onchange callback + $('#documenter-themepicker').change(function themepick_callback(ev){ + var themename = $('#documenter-themepicker option:selected').attr('value'); + set_theme(themename); + }); + + // Make sure that the themepicker displays the correct theme when the theme is retrieved + // from localStorage + if(typeof(window.localStorage) !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if(theme !== null) { + $('#documenter-themepicker option').each(function(i,e) { + e.selected = (e.value === theme); + }) + } else { + $('#documenter-themepicker option').each(function(i,e) { + e.selected = $("html").hasClass(`theme--${e.value}`); + }) + } + } +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// update the version selector with info from the siteinfo.js and ../versions.js files +$(document).ready(function() { + // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the + // siteinfo.js file, we just return immediately and not display the version selector. + if (typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === 'boolean' && DOCUMENTER_VERSION_SELECTOR_DISABLED) { + return; + } + + var version_selector = $("#documenter .docs-version-selector"); + var version_selector_select = $("#documenter .docs-version-selector select"); + + version_selector_select.change(function(x) { + target_href = version_selector_select.children("option:selected").get(0).value; + window.location.href = target_href; + }); + + // add the current version to the selector based on siteinfo.js, but only if the selector is empty + if (typeof DOCUMENTER_CURRENT_VERSION !== 'undefined' && $('#version-selector > option').length == 0) { + var option = $(""); + version_selector_select.append(option); + } + + if (typeof DOC_VERSIONS !== 'undefined') { + var existing_versions = version_selector_select.children("option"); + var existing_versions_texts = existing_versions.map(function(i,x){return x.text}); + DOC_VERSIONS.forEach(function(each) { + var version_url = documenterBaseURL + "/../" + each; + var existing_id = $.inArray(each, existing_versions_texts); + // if not already in the version selector, add it as a new option, + // otherwise update the old option with the URL and enable it + if (existing_id == -1) { + var option = $(""); + version_selector_select.append(option); + } else { + var option = existing_versions[existing_id]; + option.value = version_url; + option.disabled = false; + } + }); + } + + // only show the version selector if the selector has been populated + if (version_selector_select.children("option").length > 0) { + version_selector.toggleClass("visible"); + } +}) + +}) diff --git a/previews/PR2003/assets/favicon.ico b/previews/PR2003/assets/favicon.ico new file mode 100644 index 0000000000..9021a68fbb Binary files /dev/null and b/previews/PR2003/assets/favicon.ico differ diff --git a/previews/PR2003/assets/logo.png b/previews/PR2003/assets/logo.png new file mode 100644 index 0000000000..c5610d094d Binary files /dev/null and b/previews/PR2003/assets/logo.png differ diff --git a/previews/PR2003/assets/search.js b/previews/PR2003/assets/search.js new file mode 100644 index 0000000000..c133f74101 --- /dev/null +++ b/previews/PR2003/assets/search.js @@ -0,0 +1,267 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'lunr': 'https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.9/lunr.min', + 'lodash': 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min', + } +}); +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'lunr', 'lodash'], function($, lunr, _) { + +$(document).ready(function() { + // parseUri 1.2.2 + // (c) Steven Levithan + // MIT License + function parseUri (str) { + var o = parseUri.options, + m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), + uri = {}, + i = 14; + + while (i--) uri[o.key[i]] = m[i] || ""; + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) uri[o.q.name][$1] = $2; + }); + + return uri; + }; + parseUri.options = { + strictMode: false, + key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } + }; + + $("#search-form").submit(function(e) { + e.preventDefault() + }) + + // list below is the lunr 2.1.3 list minus the intersect with names(Base) + // (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) + // ideally we'd just filter the original list but it's not available as a variable + lunr.stopWordFilter = lunr.generateStopWordFilter([ + 'a', + 'able', + 'about', + 'across', + 'after', + 'almost', + 'also', + 'am', + 'among', + 'an', + 'and', + 'are', + 'as', + 'at', + 'be', + 'because', + 'been', + 'but', + 'by', + 'can', + 'cannot', + 'could', + 'dear', + 'did', + 'does', + 'either', + 'ever', + 'every', + 'from', + 'got', + 'had', + 'has', + 'have', + 'he', + 'her', + 'hers', + 'him', + 'his', + 'how', + 'however', + 'i', + 'if', + 'into', + 'it', + 'its', + 'just', + 'least', + 'like', + 'likely', + 'may', + 'me', + 'might', + 'most', + 'must', + 'my', + 'neither', + 'no', + 'nor', + 'not', + 'of', + 'off', + 'often', + 'on', + 'or', + 'other', + 'our', + 'own', + 'rather', + 'said', + 'say', + 'says', + 'she', + 'should', + 'since', + 'so', + 'some', + 'than', + 'that', + 'the', + 'their', + 'them', + 'then', + 'there', + 'these', + 'they', + 'this', + 'tis', + 'to', + 'too', + 'twas', + 'us', + 'wants', + 'was', + 'we', + 'were', + 'what', + 'when', + 'who', + 'whom', + 'why', + 'will', + 'would', + 'yet', + 'you', + 'your' + ]) + + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!" + // would not find anything if searching for "add!", only for the entire qualification + lunr.tokenizer.separator = /[\s\-\.]+/ + + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + lunr.trimmer = function (token) { + return token.update(function (s) { + return s.replace(/^[^a-zA-Z0-9@!]+/, '').replace(/[^a-zA-Z0-9@!]+$/, '') + }) + } + + lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'juliaStopWordFilter') + lunr.Pipeline.registerFunction(lunr.trimmer, 'juliaTrimmer') + + var index = lunr(function () { + this.ref('location') + this.field('title',{boost: 100}) + this.field('text') + documenterSearchIndex['docs'].forEach(function(e) { + this.add(e) + }, this) + }) + var store = {} + + documenterSearchIndex['docs'].forEach(function(e) { + store[e.location] = {title: e.title, category: e.category, page: e.page} + }) + + $(function(){ + searchresults = $('#documenter-search-results'); + searchinfo = $('#documenter-search-info'); + searchbox = $('#documenter-search-query'); + searchform = $('.docs-search'); + sidebar = $('.docs-sidebar'); + function update_search(querystring) { + tokens = lunr.tokenizer(querystring) + results = index.query(function (q) { + tokens.forEach(function (t) { + q.term(t.toString(), { + fields: ["title"], + boost: 100, + usePipeline: true, + editDistance: 0, + wildcard: lunr.Query.wildcard.NONE + }) + q.term(t.toString(), { + fields: ["title"], + boost: 10, + usePipeline: true, + editDistance: 2, + wildcard: lunr.Query.wildcard.NONE + }) + q.term(t.toString(), { + fields: ["text"], + boost: 1, + usePipeline: true, + editDistance: 0, + wildcard: lunr.Query.wildcard.NONE + }) + }) + }) + searchinfo.text("Number of results: " + results.length) + searchresults.empty() + results.forEach(function(result) { + data = store[result.ref] + link = $(''+data.title+'') + link.attr('href', documenterBaseURL+'/'+result.ref) + if (data.category != "page"){ + cat = $('('+data.category+', '+data.page+')') + } else { + cat = $('('+data.category+')') + } + li = $('
  • ').append(link).append(" ").append(cat) + searchresults.append(li) + }) + } + + function update_search_box() { + querystring = searchbox.val() + update_search(querystring) + } + + searchbox.keyup(_.debounce(update_search_box, 250)) + searchbox.change(update_search_box) + + // Disable enter-key form submission for the searchbox on the search page + // and just re-run search rather than refresh the whole page. + searchform.keypress( + function(event){ + if (event.which == '13') { + if (sidebar.hasClass('visible')) { + sidebar.removeClass('visible'); + } + update_search_box(); + event.preventDefault(); + } + } + ); + + search_query_uri = parseUri(window.location).queryKey["q"] + if(search_query_uri !== undefined) { + search_query = decodeURIComponent(search_query_uri.replace(/\+/g, '%20')) + searchbox.val(search_query) + } + update_search_box(); + }) +}) + +}) diff --git a/previews/PR2003/assets/themes/documenter-dark.css b/previews/PR2003/assets/themes/documenter-dark.css new file mode 100644 index 0000000000..0bf1af7d5e --- /dev/null +++ b/previews/PR2003/assets/themes/documenter-dark.css @@ -0,0 +1,7702 @@ +@charset "UTF-8"; +/* Font Awesome 5 mixin. Can be included in any rule that should render Font Awesome icons. */ +@keyframes spinAround { + from { + transform: rotate(0deg); } + to { + transform: rotate(359deg); } } + +html.theme--documenter-dark .tabs, html.theme--documenter-dark .pagination-previous, +html.theme--documenter-dark .pagination-next, +html.theme--documenter-dark .pagination-link, +html.theme--documenter-dark .pagination-ellipsis, html.theme--documenter-dark .breadcrumb, html.theme--documenter-dark .file, html.theme--documenter-dark .button, .is-unselectable, html.theme--documenter-dark .modal-close, html.theme--documenter-dark .delete { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after, html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after { + border: 3px solid transparent; + border-radius: 2px; + border-right: 0; + border-top: 0; + content: " "; + display: block; + height: 0.625em; + margin-top: -0.4375em; + pointer-events: none; + position: absolute; + top: 50%; + transform: rotate(-45deg); + transform-origin: center; + width: 0.625em; } + +html.theme--documenter-dark .admonition:not(:last-child), html.theme--documenter-dark .tabs:not(:last-child), html.theme--documenter-dark .message:not(:last-child), html.theme--documenter-dark .list:not(:last-child), html.theme--documenter-dark .level:not(:last-child), html.theme--documenter-dark .breadcrumb:not(:last-child), html.theme--documenter-dark .highlight:not(:last-child), html.theme--documenter-dark .block:not(:last-child), html.theme--documenter-dark .title:not(:last-child), +html.theme--documenter-dark .subtitle:not(:last-child), html.theme--documenter-dark .table-container:not(:last-child), html.theme--documenter-dark .table:not(:last-child), html.theme--documenter-dark .progress:not(:last-child), html.theme--documenter-dark .notification:not(:last-child), html.theme--documenter-dark .content:not(:last-child), html.theme--documenter-dark .box:not(:last-child) { + margin-bottom: 1.5rem; } + +html.theme--documenter-dark .modal-close, html.theme--documenter-dark .delete { + -moz-appearance: none; + -webkit-appearance: none; + background-color: rgba(10, 10, 10, 0.2); + border: none; + border-radius: 290486px; + cursor: pointer; + pointer-events: auto; + display: inline-block; + flex-grow: 0; + flex-shrink: 0; + font-size: 0; + height: 20px; + max-height: 20px; + max-width: 20px; + min-height: 20px; + min-width: 20px; + outline: none; + position: relative; + vertical-align: top; + width: 20px; } + html.theme--documenter-dark .modal-close::before, html.theme--documenter-dark .delete::before, html.theme--documenter-dark .modal-close::after, html.theme--documenter-dark .delete::after { + background-color: white; + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; } + html.theme--documenter-dark .modal-close::before, html.theme--documenter-dark .delete::before { + height: 2px; + width: 50%; } + html.theme--documenter-dark .modal-close::after, html.theme--documenter-dark .delete::after { + height: 50%; + width: 2px; } + html.theme--documenter-dark .modal-close:hover, html.theme--documenter-dark .delete:hover, html.theme--documenter-dark .modal-close:focus, html.theme--documenter-dark .delete:focus { + background-color: rgba(10, 10, 10, 0.3); } + html.theme--documenter-dark .modal-close:active, html.theme--documenter-dark .delete:active { + background-color: rgba(10, 10, 10, 0.4); } + html.theme--documenter-dark .is-small.modal-close, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.modal-close, html.theme--documenter-dark .is-small.delete, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.delete { + height: 16px; + max-height: 16px; + max-width: 16px; + min-height: 16px; + min-width: 16px; + width: 16px; } + html.theme--documenter-dark .is-medium.modal-close, html.theme--documenter-dark .is-medium.delete { + height: 24px; + max-height: 24px; + max-width: 24px; + min-height: 24px; + min-width: 24px; + width: 24px; } + html.theme--documenter-dark .is-large.modal-close, html.theme--documenter-dark .is-large.delete { + height: 32px; + max-height: 32px; + max-width: 32px; + min-height: 32px; + min-width: 32px; + width: 32px; } + +html.theme--documenter-dark .control.is-loading::after, html.theme--documenter-dark .select.is-loading::after, html.theme--documenter-dark .loader, html.theme--documenter-dark .button.is-loading::after { + animation: spinAround 500ms infinite linear; + border: 2px solid #dbdee0; + border-radius: 290486px; + border-right-color: transparent; + border-top-color: transparent; + content: ""; + display: block; + height: 1em; + position: relative; + width: 1em; } + +html.theme--documenter-dark .hero-video, html.theme--documenter-dark .modal-background, html.theme--documenter-dark .modal, html.theme--documenter-dark .image.is-square img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-square img, +html.theme--documenter-dark .image.is-square .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-square .has-ratio, html.theme--documenter-dark .image.is-1by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by1 img, +html.theme--documenter-dark .image.is-1by1 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by1 .has-ratio, html.theme--documenter-dark .image.is-5by4 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by4 img, +html.theme--documenter-dark .image.is-5by4 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by4 .has-ratio, html.theme--documenter-dark .image.is-4by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by3 img, +html.theme--documenter-dark .image.is-4by3 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by3 .has-ratio, html.theme--documenter-dark .image.is-3by2 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by2 img, +html.theme--documenter-dark .image.is-3by2 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by2 .has-ratio, html.theme--documenter-dark .image.is-5by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by3 img, +html.theme--documenter-dark .image.is-5by3 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by3 .has-ratio, html.theme--documenter-dark .image.is-16by9 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16by9 img, +html.theme--documenter-dark .image.is-16by9 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16by9 .has-ratio, html.theme--documenter-dark .image.is-2by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by1 img, +html.theme--documenter-dark .image.is-2by1 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by1 .has-ratio, html.theme--documenter-dark .image.is-3by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by1 img, +html.theme--documenter-dark .image.is-3by1 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by1 .has-ratio, html.theme--documenter-dark .image.is-4by5 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by5 img, +html.theme--documenter-dark .image.is-4by5 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by5 .has-ratio, html.theme--documenter-dark .image.is-3by4 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by4 img, +html.theme--documenter-dark .image.is-3by4 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by4 .has-ratio, html.theme--documenter-dark .image.is-2by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by3 img, +html.theme--documenter-dark .image.is-2by3 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by3 .has-ratio, html.theme--documenter-dark .image.is-3by5 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by5 img, +html.theme--documenter-dark .image.is-3by5 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by5 .has-ratio, html.theme--documenter-dark .image.is-9by16 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-9by16 img, +html.theme--documenter-dark .image.is-9by16 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-9by16 .has-ratio, html.theme--documenter-dark .image.is-1by2 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by2 img, +html.theme--documenter-dark .image.is-1by2 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by2 .has-ratio, html.theme--documenter-dark .image.is-1by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by3 img, +html.theme--documenter-dark .image.is-1by3 .has-ratio, +html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by3 .has-ratio, .is-overlay { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; } + +html.theme--documenter-dark .pagination-previous, +html.theme--documenter-dark .pagination-next, +html.theme--documenter-dark .pagination-link, +html.theme--documenter-dark .pagination-ellipsis, html.theme--documenter-dark .file-cta, +html.theme--documenter-dark .file-name, html.theme--documenter-dark .select select, html.theme--documenter-dark .textarea, html.theme--documenter-dark .input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input, html.theme--documenter-dark .button { + -moz-appearance: none; + -webkit-appearance: none; + align-items: center; + border: 1px solid transparent; + border-radius: 0.4em; + box-shadow: none; + display: inline-flex; + font-size: 15px; + height: 2.25em; + justify-content: flex-start; + line-height: 1.5; + padding-bottom: calc(0.375em - 1px); + padding-left: calc(0.625em - 1px); + padding-right: calc(0.625em - 1px); + padding-top: calc(0.375em - 1px); + position: relative; + vertical-align: top; } + html.theme--documenter-dark .pagination-previous:focus, + html.theme--documenter-dark .pagination-next:focus, + html.theme--documenter-dark .pagination-link:focus, + html.theme--documenter-dark .pagination-ellipsis:focus, html.theme--documenter-dark .file-cta:focus, + html.theme--documenter-dark .file-name:focus, html.theme--documenter-dark .select select:focus, html.theme--documenter-dark .textarea:focus, html.theme--documenter-dark .input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:focus, html.theme--documenter-dark .button:focus, html.theme--documenter-dark .is-focused.pagination-previous, + html.theme--documenter-dark .is-focused.pagination-next, + html.theme--documenter-dark .is-focused.pagination-link, + html.theme--documenter-dark .is-focused.pagination-ellipsis, html.theme--documenter-dark .is-focused.file-cta, + html.theme--documenter-dark .is-focused.file-name, html.theme--documenter-dark .select select.is-focused, html.theme--documenter-dark .is-focused.textarea, html.theme--documenter-dark .is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-focused.button, html.theme--documenter-dark .pagination-previous:active, + html.theme--documenter-dark .pagination-next:active, + html.theme--documenter-dark .pagination-link:active, + html.theme--documenter-dark .pagination-ellipsis:active, html.theme--documenter-dark .file-cta:active, + html.theme--documenter-dark .file-name:active, html.theme--documenter-dark .select select:active, html.theme--documenter-dark .textarea:active, html.theme--documenter-dark .input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:active, html.theme--documenter-dark .button:active, html.theme--documenter-dark .is-active.pagination-previous, + html.theme--documenter-dark .is-active.pagination-next, + html.theme--documenter-dark .is-active.pagination-link, + html.theme--documenter-dark .is-active.pagination-ellipsis, html.theme--documenter-dark .is-active.file-cta, + html.theme--documenter-dark .is-active.file-name, html.theme--documenter-dark .select select.is-active, html.theme--documenter-dark .is-active.textarea, html.theme--documenter-dark .is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active, html.theme--documenter-dark .is-active.button { + outline: none; } + html.theme--documenter-dark .pagination-previous[disabled], + html.theme--documenter-dark .pagination-next[disabled], + html.theme--documenter-dark .pagination-link[disabled], + html.theme--documenter-dark .pagination-ellipsis[disabled], html.theme--documenter-dark .file-cta[disabled], + html.theme--documenter-dark .file-name[disabled], html.theme--documenter-dark .select select[disabled], html.theme--documenter-dark .textarea[disabled], html.theme--documenter-dark .input[disabled], html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled], html.theme--documenter-dark .button[disabled], fieldset[disabled] html.theme--documenter-dark .pagination-previous, html.theme--documenter-dark fieldset[disabled] .pagination-previous, + fieldset[disabled] html.theme--documenter-dark .pagination-next, + html.theme--documenter-dark fieldset[disabled] .pagination-next, + fieldset[disabled] html.theme--documenter-dark .pagination-link, + html.theme--documenter-dark fieldset[disabled] .pagination-link, + fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis, + html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis, fieldset[disabled] html.theme--documenter-dark .file-cta, html.theme--documenter-dark fieldset[disabled] .file-cta, + fieldset[disabled] html.theme--documenter-dark .file-name, + html.theme--documenter-dark fieldset[disabled] .file-name, fieldset[disabled] html.theme--documenter-dark .select select, fieldset[disabled] html.theme--documenter-dark .textarea, fieldset[disabled] html.theme--documenter-dark .input, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input, html.theme--documenter-dark fieldset[disabled] .select select, html.theme--documenter-dark .select fieldset[disabled] select, html.theme--documenter-dark fieldset[disabled] .textarea, html.theme--documenter-dark fieldset[disabled] .input, html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search > input, html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search > input, fieldset[disabled] html.theme--documenter-dark .button, html.theme--documenter-dark fieldset[disabled] .button { + cursor: not-allowed; } + +/*! minireset.css v0.0.4 | MIT License | github.com/jgthms/minireset.css */ +html, +body, +p, +ol, +ul, +li, +dl, +dt, +dd, +blockquote, +figure, +fieldset, +legend, +textarea, +pre, +iframe, +hr, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + padding: 0; } + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: 100%; + font-weight: normal; } + +ul { + list-style: none; } + +button, +input, +select, +textarea { + margin: 0; } + +html { + box-sizing: border-box; } + +*, *::before, *::after { + box-sizing: inherit; } + +img, +embed, +iframe, +object, +video { + height: auto; + max-width: 100%; } + +audio { + max-width: 100%; } + +iframe { + border: 0; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + td:not([align]), + th:not([align]) { + text-align: left; } + +.is-clearfix::after { + clear: both; + content: " "; + display: table; } + +.is-pulled-left { + float: left !important; } + +.is-pulled-right { + float: right !important; } + +.is-clipped { + overflow: hidden !important; } + +.is-size-1 { + font-size: 3rem !important; } + +.is-size-2 { + font-size: 2.5rem !important; } + +.is-size-3 { + font-size: 2rem !important; } + +.is-size-4 { + font-size: 1.5rem !important; } + +.is-size-5 { + font-size: 1.25rem !important; } + +.is-size-6 { + font-size: 15px !important; } + +.is-size-7, html.theme--documenter-dark .docstring > section > a.docs-sourcelink { + font-size: 0.85em !important; } + +@media screen and (max-width: 768px) { + .is-size-1-mobile { + font-size: 3rem !important; } + .is-size-2-mobile { + font-size: 2.5rem !important; } + .is-size-3-mobile { + font-size: 2rem !important; } + .is-size-4-mobile { + font-size: 1.5rem !important; } + .is-size-5-mobile { + font-size: 1.25rem !important; } + .is-size-6-mobile { + font-size: 15px !important; } + .is-size-7-mobile { + font-size: 0.85em !important; } } + +@media screen and (min-width: 769px), print { + .is-size-1-tablet { + font-size: 3rem !important; } + .is-size-2-tablet { + font-size: 2.5rem !important; } + .is-size-3-tablet { + font-size: 2rem !important; } + .is-size-4-tablet { + font-size: 1.5rem !important; } + .is-size-5-tablet { + font-size: 1.25rem !important; } + .is-size-6-tablet { + font-size: 15px !important; } + .is-size-7-tablet { + font-size: 0.85em !important; } } + +@media screen and (max-width: 1055px) { + .is-size-1-touch { + font-size: 3rem !important; } + .is-size-2-touch { + font-size: 2.5rem !important; } + .is-size-3-touch { + font-size: 2rem !important; } + .is-size-4-touch { + font-size: 1.5rem !important; } + .is-size-5-touch { + font-size: 1.25rem !important; } + .is-size-6-touch { + font-size: 15px !important; } + .is-size-7-touch { + font-size: 0.85em !important; } } + +@media screen and (min-width: 1056px) { + .is-size-1-desktop { + font-size: 3rem !important; } + .is-size-2-desktop { + font-size: 2.5rem !important; } + .is-size-3-desktop { + font-size: 2rem !important; } + .is-size-4-desktop { + font-size: 1.5rem !important; } + .is-size-5-desktop { + font-size: 1.25rem !important; } + .is-size-6-desktop { + font-size: 15px !important; } + .is-size-7-desktop { + font-size: 0.85em !important; } } + +@media screen and (min-width: 1216px) { + .is-size-1-widescreen { + font-size: 3rem !important; } + .is-size-2-widescreen { + font-size: 2.5rem !important; } + .is-size-3-widescreen { + font-size: 2rem !important; } + .is-size-4-widescreen { + font-size: 1.5rem !important; } + .is-size-5-widescreen { + font-size: 1.25rem !important; } + .is-size-6-widescreen { + font-size: 15px !important; } + .is-size-7-widescreen { + font-size: 0.85em !important; } } + +@media screen and (min-width: 1408px) { + .is-size-1-fullhd { + font-size: 3rem !important; } + .is-size-2-fullhd { + font-size: 2.5rem !important; } + .is-size-3-fullhd { + font-size: 2rem !important; } + .is-size-4-fullhd { + font-size: 1.5rem !important; } + .is-size-5-fullhd { + font-size: 1.25rem !important; } + .is-size-6-fullhd { + font-size: 15px !important; } + .is-size-7-fullhd { + font-size: 0.85em !important; } } + +.has-text-centered { + text-align: center !important; } + +.has-text-justified { + text-align: justify !important; } + +.has-text-left { + text-align: left !important; } + +.has-text-right { + text-align: right !important; } + +@media screen and (max-width: 768px) { + .has-text-centered-mobile { + text-align: center !important; } } + +@media screen and (min-width: 769px), print { + .has-text-centered-tablet { + text-align: center !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-centered-tablet-only { + text-align: center !important; } } + +@media screen and (max-width: 1055px) { + .has-text-centered-touch { + text-align: center !important; } } + +@media screen and (min-width: 1056px) { + .has-text-centered-desktop { + text-align: center !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-centered-desktop-only { + text-align: center !important; } } + +@media screen and (min-width: 1216px) { + .has-text-centered-widescreen { + text-align: center !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-centered-widescreen-only { + text-align: center !important; } } + +@media screen and (min-width: 1408px) { + .has-text-centered-fullhd { + text-align: center !important; } } + +@media screen and (max-width: 768px) { + .has-text-justified-mobile { + text-align: justify !important; } } + +@media screen and (min-width: 769px), print { + .has-text-justified-tablet { + text-align: justify !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-justified-tablet-only { + text-align: justify !important; } } + +@media screen and (max-width: 1055px) { + .has-text-justified-touch { + text-align: justify !important; } } + +@media screen and (min-width: 1056px) { + .has-text-justified-desktop { + text-align: justify !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-justified-desktop-only { + text-align: justify !important; } } + +@media screen and (min-width: 1216px) { + .has-text-justified-widescreen { + text-align: justify !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-justified-widescreen-only { + text-align: justify !important; } } + +@media screen and (min-width: 1408px) { + .has-text-justified-fullhd { + text-align: justify !important; } } + +@media screen and (max-width: 768px) { + .has-text-left-mobile { + text-align: left !important; } } + +@media screen and (min-width: 769px), print { + .has-text-left-tablet { + text-align: left !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-left-tablet-only { + text-align: left !important; } } + +@media screen and (max-width: 1055px) { + .has-text-left-touch { + text-align: left !important; } } + +@media screen and (min-width: 1056px) { + .has-text-left-desktop { + text-align: left !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-left-desktop-only { + text-align: left !important; } } + +@media screen and (min-width: 1216px) { + .has-text-left-widescreen { + text-align: left !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-left-widescreen-only { + text-align: left !important; } } + +@media screen and (min-width: 1408px) { + .has-text-left-fullhd { + text-align: left !important; } } + +@media screen and (max-width: 768px) { + .has-text-right-mobile { + text-align: right !important; } } + +@media screen and (min-width: 769px), print { + .has-text-right-tablet { + text-align: right !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-right-tablet-only { + text-align: right !important; } } + +@media screen and (max-width: 1055px) { + .has-text-right-touch { + text-align: right !important; } } + +@media screen and (min-width: 1056px) { + .has-text-right-desktop { + text-align: right !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-right-desktop-only { + text-align: right !important; } } + +@media screen and (min-width: 1216px) { + .has-text-right-widescreen { + text-align: right !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-right-widescreen-only { + text-align: right !important; } } + +@media screen and (min-width: 1408px) { + .has-text-right-fullhd { + text-align: right !important; } } + +.is-capitalized { + text-transform: capitalize !important; } + +.is-lowercase { + text-transform: lowercase !important; } + +.is-uppercase { + text-transform: uppercase !important; } + +.is-italic { + font-style: italic !important; } + +.has-text-white { + color: white !important; } + +a.has-text-white:hover, a.has-text-white:focus { + color: #e6e6e6 !important; } + +.has-background-white { + background-color: white !important; } + +.has-text-black { + color: #0a0a0a !important; } + +a.has-text-black:hover, a.has-text-black:focus { + color: black !important; } + +.has-background-black { + background-color: #0a0a0a !important; } + +.has-text-light { + color: #ecf0f1 !important; } + +a.has-text-light:hover, a.has-text-light:focus { + color: #cfd9db !important; } + +.has-background-light { + background-color: #ecf0f1 !important; } + +.has-text-dark { + color: #282f2f !important; } + +a.has-text-dark:hover, a.has-text-dark:focus { + color: #111414 !important; } + +.has-background-dark { + background-color: #282f2f !important; } + +.has-text-primary { + color: #375a7f !important; } + +a.has-text-primary:hover, a.has-text-primary:focus { + color: #28415b !important; } + +.has-background-primary { + background-color: #375a7f !important; } + +.has-text-link { + color: #1abc9c !important; } + +a.has-text-link:hover, a.has-text-link:focus { + color: #148f77 !important; } + +.has-background-link { + background-color: #1abc9c !important; } + +.has-text-info { + color: #024c7d !important; } + +a.has-text-info:hover, a.has-text-info:focus { + color: #012d4b !important; } + +.has-background-info { + background-color: #024c7d !important; } + +.has-text-success { + color: #008438 !important; } + +a.has-text-success:hover, a.has-text-success:focus { + color: #005122 !important; } + +.has-background-success { + background-color: #008438 !important; } + +.has-text-warning { + color: #ad8100 !important; } + +a.has-text-warning:hover, a.has-text-warning:focus { + color: #7a5b00 !important; } + +.has-background-warning { + background-color: #ad8100 !important; } + +.has-text-danger { + color: #9e1b0d !important; } + +a.has-text-danger:hover, a.has-text-danger:focus { + color: #6f1309 !important; } + +.has-background-danger { + background-color: #9e1b0d !important; } + +.has-text-black-bis { + color: #121212 !important; } + +.has-background-black-bis { + background-color: #121212 !important; } + +.has-text-black-ter { + color: #242424 !important; } + +.has-background-black-ter { + background-color: #242424 !important; } + +.has-text-grey-darker { + color: #282f2f !important; } + +.has-background-grey-darker { + background-color: #282f2f !important; } + +.has-text-grey-dark { + color: #343c3d !important; } + +.has-background-grey-dark { + background-color: #343c3d !important; } + +.has-text-grey { + color: #5e6d6f !important; } + +.has-background-grey { + background-color: #5e6d6f !important; } + +.has-text-grey-light { + color: #8c9b9d !important; } + +.has-background-grey-light { + background-color: #8c9b9d !important; } + +.has-text-grey-lighter { + color: #dbdee0 !important; } + +.has-background-grey-lighter { + background-color: #dbdee0 !important; } + +.has-text-white-ter { + color: #ecf0f1 !important; } + +.has-background-white-ter { + background-color: #ecf0f1 !important; } + +.has-text-white-bis { + color: #fafafa !important; } + +.has-background-white-bis { + background-color: #fafafa !important; } + +.has-text-weight-light { + font-weight: 300 !important; } + +.has-text-weight-normal { + font-weight: 400 !important; } + +.has-text-weight-medium { + font-weight: 500 !important; } + +.has-text-weight-semibold { + font-weight: 600 !important; } + +.has-text-weight-bold { + font-weight: 700 !important; } + +.is-family-primary { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-secondary { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-sans-serif { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-monospace { + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace !important; } + +.is-family-code { + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace !important; } + +.is-block { + display: block !important; } + +@media screen and (max-width: 768px) { + .is-block-mobile { + display: block !important; } } + +@media screen and (min-width: 769px), print { + .is-block-tablet { + display: block !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-block-tablet-only { + display: block !important; } } + +@media screen and (max-width: 1055px) { + .is-block-touch { + display: block !important; } } + +@media screen and (min-width: 1056px) { + .is-block-desktop { + display: block !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-block-desktop-only { + display: block !important; } } + +@media screen and (min-width: 1216px) { + .is-block-widescreen { + display: block !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-block-widescreen-only { + display: block !important; } } + +@media screen and (min-width: 1408px) { + .is-block-fullhd { + display: block !important; } } + +.is-flex { + display: flex !important; } + +@media screen and (max-width: 768px) { + .is-flex-mobile { + display: flex !important; } } + +@media screen and (min-width: 769px), print { + .is-flex-tablet { + display: flex !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-flex-tablet-only { + display: flex !important; } } + +@media screen and (max-width: 1055px) { + .is-flex-touch { + display: flex !important; } } + +@media screen and (min-width: 1056px) { + .is-flex-desktop { + display: flex !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-flex-desktop-only { + display: flex !important; } } + +@media screen and (min-width: 1216px) { + .is-flex-widescreen { + display: flex !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-flex-widescreen-only { + display: flex !important; } } + +@media screen and (min-width: 1408px) { + .is-flex-fullhd { + display: flex !important; } } + +.is-inline { + display: inline !important; } + +@media screen and (max-width: 768px) { + .is-inline-mobile { + display: inline !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-tablet { + display: inline !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-tablet-only { + display: inline !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-touch { + display: inline !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-desktop { + display: inline !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-desktop-only { + display: inline !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-widescreen { + display: inline !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-widescreen-only { + display: inline !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-fullhd { + display: inline !important; } } + +.is-inline-block { + display: inline-block !important; } + +@media screen and (max-width: 768px) { + .is-inline-block-mobile { + display: inline-block !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-block-tablet { + display: inline-block !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-block-tablet-only { + display: inline-block !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-block-touch { + display: inline-block !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-block-desktop { + display: inline-block !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-block-desktop-only { + display: inline-block !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-block-widescreen { + display: inline-block !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-block-widescreen-only { + display: inline-block !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-block-fullhd { + display: inline-block !important; } } + +.is-inline-flex { + display: inline-flex !important; } + +@media screen and (max-width: 768px) { + .is-inline-flex-mobile { + display: inline-flex !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-flex-tablet { + display: inline-flex !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-flex-tablet-only { + display: inline-flex !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-flex-touch { + display: inline-flex !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-flex-desktop { + display: inline-flex !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-flex-desktop-only { + display: inline-flex !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-flex-widescreen { + display: inline-flex !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-flex-widescreen-only { + display: inline-flex !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-flex-fullhd { + display: inline-flex !important; } } + +.is-hidden { + display: none !important; } + +.is-sr-only { + border: none !important; + clip: rect(0, 0, 0, 0) !important; + height: 0.01em !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + white-space: nowrap !important; + width: 0.01em !important; } + +@media screen and (max-width: 768px) { + .is-hidden-mobile { + display: none !important; } } + +@media screen and (min-width: 769px), print { + .is-hidden-tablet { + display: none !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-hidden-tablet-only { + display: none !important; } } + +@media screen and (max-width: 1055px) { + .is-hidden-touch { + display: none !important; } } + +@media screen and (min-width: 1056px) { + .is-hidden-desktop { + display: none !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-hidden-desktop-only { + display: none !important; } } + +@media screen and (min-width: 1216px) { + .is-hidden-widescreen { + display: none !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-hidden-widescreen-only { + display: none !important; } } + +@media screen and (min-width: 1408px) { + .is-hidden-fullhd { + display: none !important; } } + +.is-invisible { + visibility: hidden !important; } + +@media screen and (max-width: 768px) { + .is-invisible-mobile { + visibility: hidden !important; } } + +@media screen and (min-width: 769px), print { + .is-invisible-tablet { + visibility: hidden !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-invisible-tablet-only { + visibility: hidden !important; } } + +@media screen and (max-width: 1055px) { + .is-invisible-touch { + visibility: hidden !important; } } + +@media screen and (min-width: 1056px) { + .is-invisible-desktop { + visibility: hidden !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-invisible-desktop-only { + visibility: hidden !important; } } + +@media screen and (min-width: 1216px) { + .is-invisible-widescreen { + visibility: hidden !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-invisible-widescreen-only { + visibility: hidden !important; } } + +@media screen and (min-width: 1408px) { + .is-invisible-fullhd { + visibility: hidden !important; } } + +.is-marginless { + margin: 0 !important; } + +.is-paddingless { + padding: 0 !important; } + +.is-radiusless { + border-radius: 0 !important; } + +.is-shadowless { + box-shadow: none !important; } + +.is-relative { + position: relative !important; } + +html.theme--documenter-dark { + /* This file contain the overall layout. + * + * The main container is
    that is identified by id #documenter. + */ + /*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/ + /* Comment */ + /* Red */ + /* Orange */ + /* Yellow */ + /* Green */ + /* Blue */ + /* Purple */ } + html.theme--documenter-dark html { + background-color: #1f2424; + font-size: 16px; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + min-width: 300px; + overflow-x: auto; + overflow-y: scroll; + text-rendering: optimizeLegibility; + text-size-adjust: 100%; } + html.theme--documenter-dark article, + html.theme--documenter-dark aside, + html.theme--documenter-dark figure, + html.theme--documenter-dark footer, + html.theme--documenter-dark header, + html.theme--documenter-dark hgroup, + html.theme--documenter-dark section { + display: block; } + html.theme--documenter-dark body, + html.theme--documenter-dark button, + html.theme--documenter-dark input, + html.theme--documenter-dark select, + html.theme--documenter-dark textarea { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif; } + html.theme--documenter-dark code, + html.theme--documenter-dark pre { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: auto; + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace; } + html.theme--documenter-dark body { + color: #fff; + font-size: 1em; + font-weight: 400; + line-height: 1.5; } + html.theme--documenter-dark a { + color: #1abc9c; + cursor: pointer; + text-decoration: none; } + html.theme--documenter-dark a strong { + color: currentColor; } + html.theme--documenter-dark a:hover { + color: #1dd2af; } + html.theme--documenter-dark code { + background-color: rgba(255, 255, 255, 0.05); + color: #ececec; + font-size: 0.875em; + font-weight: normal; + padding: 0.1em; } + html.theme--documenter-dark hr { + background-color: #282f2f; + border: none; + display: block; + height: 2px; + margin: 1.5rem 0; } + html.theme--documenter-dark img { + height: auto; + max-width: 100%; } + html.theme--documenter-dark input[type="checkbox"], + html.theme--documenter-dark input[type="radio"] { + vertical-align: baseline; } + html.theme--documenter-dark small { + font-size: 0.875em; } + html.theme--documenter-dark span { + font-style: inherit; + font-weight: inherit; } + html.theme--documenter-dark strong { + color: #f2f2f2; + font-weight: 700; } + html.theme--documenter-dark fieldset { + border: none; } + html.theme--documenter-dark pre { + -webkit-overflow-scrolling: touch; + background-color: #282f2f; + color: #fff; + font-size: 0.875em; + overflow-x: auto; + padding: 1.25rem 1.5rem; + white-space: pre; + word-wrap: normal; } + html.theme--documenter-dark pre code { + background-color: transparent; + color: currentColor; + font-size: 1em; + padding: 0; } + html.theme--documenter-dark table td, + html.theme--documenter-dark table th { + vertical-align: top; } + html.theme--documenter-dark table td:not([align]), + html.theme--documenter-dark table th:not([align]) { + text-align: left; } + html.theme--documenter-dark table th { + color: #f2f2f2; } + html.theme--documenter-dark .box { + background-color: #343c3d; + border-radius: 8px; + box-shadow: none; + color: #fff; + display: block; + padding: 1.25rem; } + html.theme--documenter-dark a.box:hover, html.theme--documenter-dark a.box:focus { + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px #1abc9c; } + html.theme--documenter-dark a.box:active { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #1abc9c; } + html.theme--documenter-dark .button { + background-color: #282f2f; + border-color: #4c5759; + border-width: 1px; + color: #375a7f; + cursor: pointer; + justify-content: center; + padding-bottom: calc(0.375em - 1px); + padding-left: 0.75em; + padding-right: 0.75em; + padding-top: calc(0.375em - 1px); + text-align: center; + white-space: nowrap; } + html.theme--documenter-dark .button strong { + color: inherit; } + html.theme--documenter-dark .button .icon, html.theme--documenter-dark .button .icon.is-small, html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search > input.icon, html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search > input.icon, html.theme--documenter-dark .button .icon.is-medium, html.theme--documenter-dark .button .icon.is-large { + height: 1.5em; + width: 1.5em; } + html.theme--documenter-dark .button .icon:first-child:not(:last-child) { + margin-left: calc(-0.375em - 1px); + margin-right: 0.1875em; } + html.theme--documenter-dark .button .icon:last-child:not(:first-child) { + margin-left: 0.1875em; + margin-right: calc(-0.375em - 1px); } + html.theme--documenter-dark .button .icon:first-child:last-child { + margin-left: calc(-0.375em - 1px); + margin-right: calc(-0.375em - 1px); } + html.theme--documenter-dark .button:hover, html.theme--documenter-dark .button.is-hovered { + border-color: #8c9b9d; + color: #f2f2f2; } + html.theme--documenter-dark .button:focus, html.theme--documenter-dark .button.is-focused { + border-color: #8c9b9d; + color: #17a689; } + html.theme--documenter-dark .button:focus:not(:active), html.theme--documenter-dark .button.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(26, 188, 156, 0.25); } + html.theme--documenter-dark .button:active, html.theme--documenter-dark .button.is-active { + border-color: #343c3d; + color: #f2f2f2; } + html.theme--documenter-dark .button.is-text { + background-color: transparent; + border-color: transparent; + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .button.is-text:hover, html.theme--documenter-dark .button.is-text.is-hovered, html.theme--documenter-dark .button.is-text:focus, html.theme--documenter-dark .button.is-text.is-focused { + background-color: #282f2f; + color: #f2f2f2; } + html.theme--documenter-dark .button.is-text:active, html.theme--documenter-dark .button.is-text.is-active { + background-color: #1d2122; + color: #f2f2f2; } + html.theme--documenter-dark .button.is-text[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-text { + background-color: transparent; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-white { + background-color: white; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white:hover, html.theme--documenter-dark .button.is-white.is-hovered { + background-color: #f9f9f9; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white:focus, html.theme--documenter-dark .button.is-white.is-focused { + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white:focus:not(:active), html.theme--documenter-dark .button.is-white.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + html.theme--documenter-dark .button.is-white:active, html.theme--documenter-dark .button.is-white.is-active { + background-color: #f2f2f2; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-white { + background-color: white; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-white.is-inverted { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .button.is-white.is-inverted:hover, html.theme--documenter-dark .button.is-white.is-inverted.is-hovered { + background-color: black; } + html.theme--documenter-dark .button.is-white.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted { + background-color: #0a0a0a; + border-color: transparent; + box-shadow: none; + color: white; } + html.theme--documenter-dark .button.is-white.is-loading::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + html.theme--documenter-dark .button.is-white.is-outlined { + background-color: transparent; + border-color: white; + color: white; } + html.theme--documenter-dark .button.is-white.is-outlined:hover, html.theme--documenter-dark .button.is-white.is-outlined.is-hovered, html.theme--documenter-dark .button.is-white.is-outlined:focus, html.theme--documenter-dark .button.is-white.is-outlined.is-focused { + background-color: white; + border-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after { + border-color: transparent transparent white white !important; } + html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + html.theme--documenter-dark .button.is-white.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined { + background-color: transparent; + border-color: white; + box-shadow: none; + color: white; } + html.theme--documenter-dark .button.is-white.is-inverted.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent white white !important; } + html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + box-shadow: none; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black { + background-color: #0a0a0a; + border-color: transparent; + color: white; } + html.theme--documenter-dark .button.is-black:hover, html.theme--documenter-dark .button.is-black.is-hovered { + background-color: #040404; + border-color: transparent; + color: white; } + html.theme--documenter-dark .button.is-black:focus, html.theme--documenter-dark .button.is-black.is-focused { + border-color: transparent; + color: white; } + html.theme--documenter-dark .button.is-black:focus:not(:active), html.theme--documenter-dark .button.is-black.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + html.theme--documenter-dark .button.is-black:active, html.theme--documenter-dark .button.is-black.is-active { + background-color: black; + border-color: transparent; + color: white; } + html.theme--documenter-dark .button.is-black[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-black { + background-color: #0a0a0a; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-black.is-inverted { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black.is-inverted:hover, html.theme--documenter-dark .button.is-black.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-black.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted { + background-color: white; + border-color: transparent; + box-shadow: none; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black.is-loading::after { + border-color: transparent transparent white white !important; } + html.theme--documenter-dark .button.is-black.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black.is-outlined:hover, html.theme--documenter-dark .button.is-black.is-outlined.is-hovered, html.theme--documenter-dark .button.is-black.is-outlined:focus, html.theme--documenter-dark .button.is-black.is-outlined.is-focused { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent white white !important; } + html.theme--documenter-dark .button.is-black.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + box-shadow: none; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black.is-inverted.is-outlined { + background-color: transparent; + border-color: white; + color: white; } + html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined { + background-color: transparent; + border-color: white; + box-shadow: none; + color: white; } + html.theme--documenter-dark .button.is-light { + background-color: #ecf0f1; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .button.is-light:hover, html.theme--documenter-dark .button.is-light.is-hovered { + background-color: #e5eaec; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .button.is-light:focus, html.theme--documenter-dark .button.is-light.is-focused { + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .button.is-light:focus:not(:active), html.theme--documenter-dark .button.is-light.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(236, 240, 241, 0.25); } + html.theme--documenter-dark .button.is-light:active, html.theme--documenter-dark .button.is-light.is-active { + background-color: #dde4e6; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .button.is-light[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-light { + background-color: #ecf0f1; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-light.is-inverted { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-light.is-inverted:hover, html.theme--documenter-dark .button.is-light.is-inverted.is-hovered { + background-color: #1d2122; } + html.theme--documenter-dark .button.is-light.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted { + background-color: #282f2f; + border-color: transparent; + box-shadow: none; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-light.is-loading::after { + border-color: transparent transparent #282f2f #282f2f !important; } + html.theme--documenter-dark .button.is-light.is-outlined { + background-color: transparent; + border-color: #ecf0f1; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-light.is-outlined:hover, html.theme--documenter-dark .button.is-light.is-outlined.is-hovered, html.theme--documenter-dark .button.is-light.is-outlined:focus, html.theme--documenter-dark .button.is-light.is-outlined.is-focused { + background-color: #ecf0f1; + border-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after { + border-color: transparent transparent #ecf0f1 #ecf0f1 !important; } + html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #282f2f #282f2f !important; } + html.theme--documenter-dark .button.is-light.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined { + background-color: transparent; + border-color: #ecf0f1; + box-shadow: none; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-light.is-inverted.is-outlined { + background-color: transparent; + border-color: #282f2f; + color: #282f2f; } + html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #ecf0f1 #ecf0f1 !important; } + html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined { + background-color: transparent; + border-color: #282f2f; + box-shadow: none; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark, html.theme--documenter-dark .content kbd.button { + background-color: #282f2f; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark:hover, html.theme--documenter-dark .content kbd.button:hover, html.theme--documenter-dark .button.is-dark.is-hovered, html.theme--documenter-dark .content kbd.button.is-hovered { + background-color: #232829; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark:focus, html.theme--documenter-dark .content kbd.button:focus, html.theme--documenter-dark .button.is-dark.is-focused, html.theme--documenter-dark .content kbd.button.is-focused { + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark:focus:not(:active), html.theme--documenter-dark .content kbd.button:focus:not(:active), html.theme--documenter-dark .button.is-dark.is-focused:not(:active), html.theme--documenter-dark .content kbd.button.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(40, 47, 47, 0.25); } + html.theme--documenter-dark .button.is-dark:active, html.theme--documenter-dark .content kbd.button:active, html.theme--documenter-dark .button.is-dark.is-active, html.theme--documenter-dark .content kbd.button.is-active { + background-color: #1d2122; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark[disabled], html.theme--documenter-dark .content kbd.button[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-dark, fieldset[disabled] html.theme--documenter-dark .content kbd.button { + background-color: #282f2f; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-dark.is-inverted, html.theme--documenter-dark .content kbd.button.is-inverted { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark.is-inverted:hover, html.theme--documenter-dark .content kbd.button.is-inverted:hover, html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered, html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered { + background-color: #dde4e6; } + html.theme--documenter-dark .button.is-dark.is-inverted[disabled], html.theme--documenter-dark .content kbd.button.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted, fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted { + background-color: #ecf0f1; + border-color: transparent; + box-shadow: none; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark.is-loading::after, html.theme--documenter-dark .content kbd.button.is-loading::after { + border-color: transparent transparent #ecf0f1 #ecf0f1 !important; } + html.theme--documenter-dark .button.is-dark.is-outlined, html.theme--documenter-dark .content kbd.button.is-outlined { + background-color: transparent; + border-color: #282f2f; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark.is-outlined:hover, html.theme--documenter-dark .content kbd.button.is-outlined:hover, html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered, html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered, html.theme--documenter-dark .button.is-dark.is-outlined:focus, html.theme--documenter-dark .content kbd.button.is-outlined:focus, html.theme--documenter-dark .button.is-dark.is-outlined.is-focused, html.theme--documenter-dark .content kbd.button.is-outlined.is-focused { + background-color: #282f2f; + border-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after, html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after { + border-color: transparent transparent #282f2f #282f2f !important; } + html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after, html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after, html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after, html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #ecf0f1 #ecf0f1 !important; } + html.theme--documenter-dark .button.is-dark.is-outlined[disabled], html.theme--documenter-dark .content kbd.button.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined, fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined { + background-color: transparent; + border-color: #282f2f; + box-shadow: none; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined { + background-color: transparent; + border-color: #ecf0f1; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after, html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #282f2f #282f2f !important; } + html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled], html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined, fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined { + background-color: transparent; + border-color: #ecf0f1; + box-shadow: none; + color: #ecf0f1; } + html.theme--documenter-dark .button.is-primary, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink { + background-color: #375a7f; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-primary:hover, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:hover, html.theme--documenter-dark .button.is-primary.is-hovered, html.theme--documenter-dark .docstring > section > a.button.is-hovered.docs-sourcelink { + background-color: #335476; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-primary:focus, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:focus, html.theme--documenter-dark .button.is-primary.is-focused, html.theme--documenter-dark .docstring > section > a.button.is-focused.docs-sourcelink { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-primary:focus:not(:active), html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:focus:not(:active), html.theme--documenter-dark .button.is-primary.is-focused:not(:active), html.theme--documenter-dark .docstring > section > a.button.is-focused.docs-sourcelink:not(:active) { + box-shadow: 0 0 0 0.125em rgba(55, 90, 127, 0.25); } + html.theme--documenter-dark .button.is-primary:active, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:active, html.theme--documenter-dark .button.is-primary.is-active, html.theme--documenter-dark .docstring > section > a.button.is-active.docs-sourcelink { + background-color: #2f4d6d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-primary[disabled], html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-primary, fieldset[disabled] html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink { + background-color: #375a7f; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-primary.is-inverted, html.theme--documenter-dark .docstring > section > a.button.is-inverted.docs-sourcelink { + background-color: #fff; + color: #375a7f; } + html.theme--documenter-dark .button.is-primary.is-inverted:hover, html.theme--documenter-dark .docstring > section > a.button.is-inverted.docs-sourcelink:hover, html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-hovered.docs-sourcelink { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-primary.is-inverted[disabled], html.theme--documenter-dark .docstring > section > a.button.is-inverted.docs-sourcelink[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted, fieldset[disabled] html.theme--documenter-dark .docstring > section > a.button.is-inverted.docs-sourcelink { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #375a7f; } + html.theme--documenter-dark .button.is-primary.is-loading::after, html.theme--documenter-dark .docstring > section > a.button.is-loading.docs-sourcelink::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-primary.is-outlined, html.theme--documenter-dark .docstring > section > a.button.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #375a7f; + color: #375a7f; } + html.theme--documenter-dark .button.is-primary.is-outlined:hover, html.theme--documenter-dark .docstring > section > a.button.is-outlined.docs-sourcelink:hover, html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-hovered.docs-sourcelink, html.theme--documenter-dark .button.is-primary.is-outlined:focus, html.theme--documenter-dark .docstring > section > a.button.is-outlined.docs-sourcelink:focus, html.theme--documenter-dark .button.is-primary.is-outlined.is-focused, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-focused.docs-sourcelink { + background-color: #375a7f; + border-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink::after { + border-color: transparent transparent #375a7f #375a7f !important; } + html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink:hover::after, html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after, html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink:focus::after, html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after, html.theme--documenter-dark .docstring > section > a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-primary.is-outlined[disabled], html.theme--documenter-dark .docstring > section > a.button.is-outlined.docs-sourcelink[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined, fieldset[disabled] html.theme--documenter-dark .docstring > section > a.button.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #375a7f; + box-shadow: none; + color: #375a7f; } + html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink:hover, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink:focus, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-focused.docs-sourcelink { + background-color: #fff; + color: #375a7f; } + html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after, html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after, html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after { + border-color: transparent transparent #375a7f #375a7f !important; } + html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled], html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined, fieldset[disabled] html.theme--documenter-dark .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-link { + background-color: #1abc9c; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-link:hover, html.theme--documenter-dark .button.is-link.is-hovered { + background-color: #18b193; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-link:focus, html.theme--documenter-dark .button.is-link.is-focused { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-link:focus:not(:active), html.theme--documenter-dark .button.is-link.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(26, 188, 156, 0.25); } + html.theme--documenter-dark .button.is-link:active, html.theme--documenter-dark .button.is-link.is-active { + background-color: #17a689; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-link[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-link { + background-color: #1abc9c; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-link.is-inverted { + background-color: #fff; + color: #1abc9c; } + html.theme--documenter-dark .button.is-link.is-inverted:hover, html.theme--documenter-dark .button.is-link.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-link.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #1abc9c; } + html.theme--documenter-dark .button.is-link.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-link.is-outlined { + background-color: transparent; + border-color: #1abc9c; + color: #1abc9c; } + html.theme--documenter-dark .button.is-link.is-outlined:hover, html.theme--documenter-dark .button.is-link.is-outlined.is-hovered, html.theme--documenter-dark .button.is-link.is-outlined:focus, html.theme--documenter-dark .button.is-link.is-outlined.is-focused { + background-color: #1abc9c; + border-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after { + border-color: transparent transparent #1abc9c #1abc9c !important; } + html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-link.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined { + background-color: transparent; + border-color: #1abc9c; + box-shadow: none; + color: #1abc9c; } + html.theme--documenter-dark .button.is-link.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #1abc9c; } + html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #1abc9c #1abc9c !important; } + html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-info { + background-color: #024c7d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-info:hover, html.theme--documenter-dark .button.is-info.is-hovered { + background-color: #024470; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-info:focus, html.theme--documenter-dark .button.is-info.is-focused { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-info:focus:not(:active), html.theme--documenter-dark .button.is-info.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(2, 76, 125, 0.25); } + html.theme--documenter-dark .button.is-info:active, html.theme--documenter-dark .button.is-info.is-active { + background-color: #023d64; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-info[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-info { + background-color: #024c7d; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-info.is-inverted { + background-color: #fff; + color: #024c7d; } + html.theme--documenter-dark .button.is-info.is-inverted:hover, html.theme--documenter-dark .button.is-info.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-info.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #024c7d; } + html.theme--documenter-dark .button.is-info.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-info.is-outlined { + background-color: transparent; + border-color: #024c7d; + color: #024c7d; } + html.theme--documenter-dark .button.is-info.is-outlined:hover, html.theme--documenter-dark .button.is-info.is-outlined.is-hovered, html.theme--documenter-dark .button.is-info.is-outlined:focus, html.theme--documenter-dark .button.is-info.is-outlined.is-focused { + background-color: #024c7d; + border-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after { + border-color: transparent transparent #024c7d #024c7d !important; } + html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-info.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined { + background-color: transparent; + border-color: #024c7d; + box-shadow: none; + color: #024c7d; } + html.theme--documenter-dark .button.is-info.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #024c7d; } + html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #024c7d #024c7d !important; } + html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-success { + background-color: #008438; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-success:hover, html.theme--documenter-dark .button.is-success.is-hovered { + background-color: #007733; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-success:focus, html.theme--documenter-dark .button.is-success.is-focused { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-success:focus:not(:active), html.theme--documenter-dark .button.is-success.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(0, 132, 56, 0.25); } + html.theme--documenter-dark .button.is-success:active, html.theme--documenter-dark .button.is-success.is-active { + background-color: #006b2d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-success[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-success { + background-color: #008438; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-success.is-inverted { + background-color: #fff; + color: #008438; } + html.theme--documenter-dark .button.is-success.is-inverted:hover, html.theme--documenter-dark .button.is-success.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-success.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #008438; } + html.theme--documenter-dark .button.is-success.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-success.is-outlined { + background-color: transparent; + border-color: #008438; + color: #008438; } + html.theme--documenter-dark .button.is-success.is-outlined:hover, html.theme--documenter-dark .button.is-success.is-outlined.is-hovered, html.theme--documenter-dark .button.is-success.is-outlined:focus, html.theme--documenter-dark .button.is-success.is-outlined.is-focused { + background-color: #008438; + border-color: #008438; + color: #fff; } + html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after { + border-color: transparent transparent #008438 #008438 !important; } + html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-success.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined { + background-color: transparent; + border-color: #008438; + box-shadow: none; + color: #008438; } + html.theme--documenter-dark .button.is-success.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #008438; } + html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #008438 #008438 !important; } + html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-warning { + background-color: #ad8100; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-warning:hover, html.theme--documenter-dark .button.is-warning.is-hovered { + background-color: #a07700; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-warning:focus, html.theme--documenter-dark .button.is-warning.is-focused { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-warning:focus:not(:active), html.theme--documenter-dark .button.is-warning.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(173, 129, 0, 0.25); } + html.theme--documenter-dark .button.is-warning:active, html.theme--documenter-dark .button.is-warning.is-active { + background-color: #946e00; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-warning[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-warning { + background-color: #ad8100; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-warning.is-inverted { + background-color: #fff; + color: #ad8100; } + html.theme--documenter-dark .button.is-warning.is-inverted:hover, html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-warning.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #ad8100; } + html.theme--documenter-dark .button.is-warning.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-warning.is-outlined { + background-color: transparent; + border-color: #ad8100; + color: #ad8100; } + html.theme--documenter-dark .button.is-warning.is-outlined:hover, html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered, html.theme--documenter-dark .button.is-warning.is-outlined:focus, html.theme--documenter-dark .button.is-warning.is-outlined.is-focused { + background-color: #ad8100; + border-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after { + border-color: transparent transparent #ad8100 #ad8100 !important; } + html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-warning.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined { + background-color: transparent; + border-color: #ad8100; + box-shadow: none; + color: #ad8100; } + html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #ad8100; } + html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #ad8100 #ad8100 !important; } + html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-danger { + background-color: #9e1b0d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-danger:hover, html.theme--documenter-dark .button.is-danger.is-hovered { + background-color: #92190c; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-danger:focus, html.theme--documenter-dark .button.is-danger.is-focused { + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-danger:focus:not(:active), html.theme--documenter-dark .button.is-danger.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(158, 27, 13, 0.25); } + html.theme--documenter-dark .button.is-danger:active, html.theme--documenter-dark .button.is-danger.is-active { + background-color: #86170b; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .button.is-danger[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-danger { + background-color: #9e1b0d; + border-color: transparent; + box-shadow: none; } + html.theme--documenter-dark .button.is-danger.is-inverted { + background-color: #fff; + color: #9e1b0d; } + html.theme--documenter-dark .button.is-danger.is-inverted:hover, html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered { + background-color: #f2f2f2; } + html.theme--documenter-dark .button.is-danger.is-inverted[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #9e1b0d; } + html.theme--documenter-dark .button.is-danger.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-danger.is-outlined { + background-color: transparent; + border-color: #9e1b0d; + color: #9e1b0d; } + html.theme--documenter-dark .button.is-danger.is-outlined:hover, html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered, html.theme--documenter-dark .button.is-danger.is-outlined:focus, html.theme--documenter-dark .button.is-danger.is-outlined.is-focused { + background-color: #9e1b0d; + border-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after { + border-color: transparent transparent #9e1b0d #9e1b0d !important; } + html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + html.theme--documenter-dark .button.is-danger.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined { + background-color: transparent; + border-color: #9e1b0d; + box-shadow: none; + color: #9e1b0d; } + html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #9e1b0d; } + html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after, html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #9e1b0d #9e1b0d !important; } + html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled], fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + html.theme--documenter-dark .button.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.button { + border-radius: 3px; + font-size: 0.85em; } + html.theme--documenter-dark .button.is-normal { + font-size: 15px; } + html.theme--documenter-dark .button.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .button.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .button[disabled], fieldset[disabled] html.theme--documenter-dark .button { + background-color: #8c9b9d; + border-color: #dbdee0; + box-shadow: none; + opacity: 0.5; } + html.theme--documenter-dark .button.is-fullwidth { + display: flex; + width: 100%; } + html.theme--documenter-dark .button.is-loading { + color: transparent !important; + pointer-events: none; } + html.theme--documenter-dark .button.is-loading::after { + position: absolute; + left: calc(50% - (1em / 2)); + top: calc(50% - (1em / 2)); + position: absolute !important; } + html.theme--documenter-dark .button.is-static { + background-color: #282f2f; + border-color: #5e6d6f; + color: #dbdee0; + box-shadow: none; + pointer-events: none; } + html.theme--documenter-dark .button.is-rounded, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.button { + border-radius: 290486px; + padding-left: 1em; + padding-right: 1em; } + html.theme--documenter-dark .buttons { + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + html.theme--documenter-dark .buttons .button { + margin-bottom: 0.5rem; } + html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth) { + margin-right: 0.5rem; } + html.theme--documenter-dark .buttons:last-child { + margin-bottom: -0.5rem; } + html.theme--documenter-dark .buttons:not(:last-child) { + margin-bottom: 1rem; } + html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large) { + border-radius: 3px; + font-size: 0.85em; } + html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large) { + font-size: 1.25rem; } + html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium) { + font-size: 1.5rem; } + html.theme--documenter-dark .buttons.has-addons .button:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + html.theme--documenter-dark .buttons.has-addons .button:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + margin-right: -1px; } + html.theme--documenter-dark .buttons.has-addons .button:last-child { + margin-right: 0; } + html.theme--documenter-dark .buttons.has-addons .button:hover, html.theme--documenter-dark .buttons.has-addons .button.is-hovered { + z-index: 2; } + html.theme--documenter-dark .buttons.has-addons .button:focus, html.theme--documenter-dark .buttons.has-addons .button.is-focused, html.theme--documenter-dark .buttons.has-addons .button:active, html.theme--documenter-dark .buttons.has-addons .button.is-active, html.theme--documenter-dark .buttons.has-addons .button.is-selected { + z-index: 3; } + html.theme--documenter-dark .buttons.has-addons .button:focus:hover, html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover, html.theme--documenter-dark .buttons.has-addons .button:active:hover, html.theme--documenter-dark .buttons.has-addons .button.is-active:hover, html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover { + z-index: 4; } + html.theme--documenter-dark .buttons.has-addons .button.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .buttons.is-centered { + justify-content: center; } + html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth) { + margin-left: 0.25rem; + margin-right: 0.25rem; } + html.theme--documenter-dark .buttons.is-right { + justify-content: flex-end; } + html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth) { + margin-left: 0.25rem; + margin-right: 0.25rem; } + html.theme--documenter-dark .container { + flex-grow: 1; + margin: 0 auto; + position: relative; + width: auto; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .container { + max-width: 992px; } + html.theme--documenter-dark .container.is-fluid { + margin-left: 32px; + margin-right: 32px; + max-width: none; } } + @media screen and (max-width: 1215px) { + html.theme--documenter-dark .container.is-widescreen { + max-width: 1152px; } } + @media screen and (max-width: 1407px) { + html.theme--documenter-dark .container.is-fullhd { + max-width: 1344px; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .container { + max-width: 1152px; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .container { + max-width: 1344px; } } + html.theme--documenter-dark .content li + li { + margin-top: 0.25em; } + html.theme--documenter-dark .content p:not(:last-child), + html.theme--documenter-dark .content dl:not(:last-child), + html.theme--documenter-dark .content ol:not(:last-child), + html.theme--documenter-dark .content ul:not(:last-child), + html.theme--documenter-dark .content blockquote:not(:last-child), + html.theme--documenter-dark .content pre:not(:last-child), + html.theme--documenter-dark .content table:not(:last-child) { + margin-bottom: 1em; } + html.theme--documenter-dark .content h1, + html.theme--documenter-dark .content h2, + html.theme--documenter-dark .content h3, + html.theme--documenter-dark .content h4, + html.theme--documenter-dark .content h5, + html.theme--documenter-dark .content h6 { + color: #f2f2f2; + font-weight: 600; + line-height: 1.125; } + html.theme--documenter-dark .content h1 { + font-size: 2em; + margin-bottom: 0.5em; } + html.theme--documenter-dark .content h1:not(:first-child) { + margin-top: 1em; } + html.theme--documenter-dark .content h2 { + font-size: 1.75em; + margin-bottom: 0.5714em; } + html.theme--documenter-dark .content h2:not(:first-child) { + margin-top: 1.1428em; } + html.theme--documenter-dark .content h3 { + font-size: 1.5em; + margin-bottom: 0.6666em; } + html.theme--documenter-dark .content h3:not(:first-child) { + margin-top: 1.3333em; } + html.theme--documenter-dark .content h4 { + font-size: 1.25em; + margin-bottom: 0.8em; } + html.theme--documenter-dark .content h5 { + font-size: 1.125em; + margin-bottom: 0.8888em; } + html.theme--documenter-dark .content h6 { + font-size: 1em; + margin-bottom: 1em; } + html.theme--documenter-dark .content blockquote { + background-color: #282f2f; + border-left: 5px solid #5e6d6f; + padding: 1.25em 1.5em; } + html.theme--documenter-dark .content ol { + list-style-position: outside; + margin-left: 2em; + margin-top: 1em; } + html.theme--documenter-dark .content ol:not([type]) { + list-style-type: decimal; } + html.theme--documenter-dark .content ol.is-lower-alpha:not([type]) { + list-style-type: lower-alpha; } + html.theme--documenter-dark .content ol.is-lower-roman:not([type]) { + list-style-type: lower-roman; } + html.theme--documenter-dark .content ol.is-upper-alpha:not([type]) { + list-style-type: upper-alpha; } + html.theme--documenter-dark .content ol.is-upper-roman:not([type]) { + list-style-type: upper-roman; } + html.theme--documenter-dark .content ul { + list-style: disc outside; + margin-left: 2em; + margin-top: 1em; } + html.theme--documenter-dark .content ul ul { + list-style-type: circle; + margin-top: 0.5em; } + html.theme--documenter-dark .content ul ul ul { + list-style-type: square; } + html.theme--documenter-dark .content dd { + margin-left: 2em; } + html.theme--documenter-dark .content figure { + margin-left: 2em; + margin-right: 2em; + text-align: center; } + html.theme--documenter-dark .content figure:not(:first-child) { + margin-top: 2em; } + html.theme--documenter-dark .content figure:not(:last-child) { + margin-bottom: 2em; } + html.theme--documenter-dark .content figure img { + display: inline-block; } + html.theme--documenter-dark .content figure figcaption { + font-style: italic; } + html.theme--documenter-dark .content pre { + -webkit-overflow-scrolling: touch; + overflow-x: auto; + padding: 0; + white-space: pre; + word-wrap: normal; } + html.theme--documenter-dark .content sup, + html.theme--documenter-dark .content sub { + font-size: 75%; } + html.theme--documenter-dark .content table { + width: 100%; } + html.theme--documenter-dark .content table td, + html.theme--documenter-dark .content table th { + border: 1px solid #5e6d6f; + border-width: 0 0 1px; + padding: 0.5em 0.75em; + vertical-align: top; } + html.theme--documenter-dark .content table th { + color: #f2f2f2; } + html.theme--documenter-dark .content table th:not([align]) { + text-align: left; } + html.theme--documenter-dark .content table thead td, + html.theme--documenter-dark .content table thead th { + border-width: 0 0 2px; + color: #f2f2f2; } + html.theme--documenter-dark .content table tfoot td, + html.theme--documenter-dark .content table tfoot th { + border-width: 2px 0 0; + color: #f2f2f2; } + html.theme--documenter-dark .content table tbody tr:last-child td, + html.theme--documenter-dark .content table tbody tr:last-child th { + border-bottom-width: 0; } + html.theme--documenter-dark .content .tabs li + li { + margin-top: 0; } + html.theme--documenter-dark .content.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.content { + font-size: 0.85em; } + html.theme--documenter-dark .content.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .content.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .icon { + align-items: center; + display: inline-flex; + justify-content: center; + height: 1.5rem; + width: 1.5rem; } + html.theme--documenter-dark .icon.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.icon { + height: 1rem; + width: 1rem; } + html.theme--documenter-dark .icon.is-medium { + height: 2rem; + width: 2rem; } + html.theme--documenter-dark .icon.is-large { + height: 3rem; + width: 3rem; } + html.theme--documenter-dark .image, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img { + display: block; + position: relative; } + html.theme--documenter-dark .image img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img img { + display: block; + height: auto; + width: 100%; } + html.theme--documenter-dark .image img.is-rounded, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img img.is-rounded { + border-radius: 290486px; } + html.theme--documenter-dark .image.is-square img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-square img, + html.theme--documenter-dark .image.is-square .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-square .has-ratio, html.theme--documenter-dark .image.is-1by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by1 img, + html.theme--documenter-dark .image.is-1by1 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by1 .has-ratio, html.theme--documenter-dark .image.is-5by4 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by4 img, + html.theme--documenter-dark .image.is-5by4 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by4 .has-ratio, html.theme--documenter-dark .image.is-4by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by3 img, + html.theme--documenter-dark .image.is-4by3 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by3 .has-ratio, html.theme--documenter-dark .image.is-3by2 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by2 img, + html.theme--documenter-dark .image.is-3by2 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by2 .has-ratio, html.theme--documenter-dark .image.is-5by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by3 img, + html.theme--documenter-dark .image.is-5by3 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by3 .has-ratio, html.theme--documenter-dark .image.is-16by9 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16by9 img, + html.theme--documenter-dark .image.is-16by9 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16by9 .has-ratio, html.theme--documenter-dark .image.is-2by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by1 img, + html.theme--documenter-dark .image.is-2by1 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by1 .has-ratio, html.theme--documenter-dark .image.is-3by1 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by1 img, + html.theme--documenter-dark .image.is-3by1 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by1 .has-ratio, html.theme--documenter-dark .image.is-4by5 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by5 img, + html.theme--documenter-dark .image.is-4by5 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by5 .has-ratio, html.theme--documenter-dark .image.is-3by4 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by4 img, + html.theme--documenter-dark .image.is-3by4 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by4 .has-ratio, html.theme--documenter-dark .image.is-2by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by3 img, + html.theme--documenter-dark .image.is-2by3 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by3 .has-ratio, html.theme--documenter-dark .image.is-3by5 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by5 img, + html.theme--documenter-dark .image.is-3by5 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by5 .has-ratio, html.theme--documenter-dark .image.is-9by16 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-9by16 img, + html.theme--documenter-dark .image.is-9by16 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-9by16 .has-ratio, html.theme--documenter-dark .image.is-1by2 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by2 img, + html.theme--documenter-dark .image.is-1by2 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by2 .has-ratio, html.theme--documenter-dark .image.is-1by3 img, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by3 img, + html.theme--documenter-dark .image.is-1by3 .has-ratio, + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by3 .has-ratio { + height: 100%; + width: 100%; } + html.theme--documenter-dark .image.is-square, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-square, html.theme--documenter-dark .image.is-1by1, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by1 { + padding-top: 100%; } + html.theme--documenter-dark .image.is-5by4, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by4 { + padding-top: 80%; } + html.theme--documenter-dark .image.is-4by3, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by3 { + padding-top: 75%; } + html.theme--documenter-dark .image.is-3by2, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by2 { + padding-top: 66.6666%; } + html.theme--documenter-dark .image.is-5by3, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-5by3 { + padding-top: 60%; } + html.theme--documenter-dark .image.is-16by9, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16by9 { + padding-top: 56.25%; } + html.theme--documenter-dark .image.is-2by1, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by1 { + padding-top: 50%; } + html.theme--documenter-dark .image.is-3by1, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by1 { + padding-top: 33.3333%; } + html.theme--documenter-dark .image.is-4by5, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-4by5 { + padding-top: 125%; } + html.theme--documenter-dark .image.is-3by4, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by4 { + padding-top: 133.3333%; } + html.theme--documenter-dark .image.is-2by3, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-2by3 { + padding-top: 150%; } + html.theme--documenter-dark .image.is-3by5, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-3by5 { + padding-top: 166.6666%; } + html.theme--documenter-dark .image.is-9by16, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-9by16 { + padding-top: 177.7777%; } + html.theme--documenter-dark .image.is-1by2, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by2 { + padding-top: 200%; } + html.theme--documenter-dark .image.is-1by3, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-1by3 { + padding-top: 300%; } + html.theme--documenter-dark .image.is-16x16, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-16x16 { + height: 16px; + width: 16px; } + html.theme--documenter-dark .image.is-24x24, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-24x24 { + height: 24px; + width: 24px; } + html.theme--documenter-dark .image.is-32x32, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-32x32 { + height: 32px; + width: 32px; } + html.theme--documenter-dark .image.is-48x48, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-48x48 { + height: 48px; + width: 48px; } + html.theme--documenter-dark .image.is-64x64, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-64x64 { + height: 64px; + width: 64px; } + html.theme--documenter-dark .image.is-96x96, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-96x96 { + height: 96px; + width: 96px; } + html.theme--documenter-dark .image.is-128x128, html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img.is-128x128 { + height: 128px; + width: 128px; } + html.theme--documenter-dark .notification { + background-color: #282f2f; + border-radius: 0.4em; + padding: 1.25rem 2.5rem 1.25rem 1.5rem; + position: relative; } + html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item) { + color: currentColor; + text-decoration: underline; } + html.theme--documenter-dark .notification strong { + color: currentColor; } + html.theme--documenter-dark .notification code, + html.theme--documenter-dark .notification pre { + background: white; } + html.theme--documenter-dark .notification pre code { + background: transparent; } + html.theme--documenter-dark .notification > .delete { + position: absolute; + right: 0.5rem; + top: 0.5rem; } + html.theme--documenter-dark .notification .title, + html.theme--documenter-dark .notification .subtitle, + html.theme--documenter-dark .notification .content { + color: currentColor; } + html.theme--documenter-dark .notification.is-white { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .notification.is-black { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .notification.is-light { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .notification.is-dark, html.theme--documenter-dark .content kbd.notification { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .notification.is-primary, html.theme--documenter-dark .docstring > section > a.notification.docs-sourcelink { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .notification.is-link { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .notification.is-info { + background-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .notification.is-success { + background-color: #008438; + color: #fff; } + html.theme--documenter-dark .notification.is-warning { + background-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .notification.is-danger { + background-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .progress { + -moz-appearance: none; + -webkit-appearance: none; + border: none; + border-radius: 290486px; + display: block; + height: 15px; + overflow: hidden; + padding: 0; + width: 100%; } + html.theme--documenter-dark .progress::-webkit-progress-bar { + background-color: #5e6d6f; } + html.theme--documenter-dark .progress::-webkit-progress-value { + background-color: #dbdee0; } + html.theme--documenter-dark .progress::-moz-progress-bar { + background-color: #dbdee0; } + html.theme--documenter-dark .progress::-ms-fill { + background-color: #dbdee0; + border: none; } + html.theme--documenter-dark .progress.is-white::-webkit-progress-value { + background-color: white; } + html.theme--documenter-dark .progress.is-white::-moz-progress-bar { + background-color: white; } + html.theme--documenter-dark .progress.is-white::-ms-fill { + background-color: white; } + html.theme--documenter-dark .progress.is-white:indeterminate { + background-image: linear-gradient(to right, white 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-black::-webkit-progress-value { + background-color: #0a0a0a; } + html.theme--documenter-dark .progress.is-black::-moz-progress-bar { + background-color: #0a0a0a; } + html.theme--documenter-dark .progress.is-black::-ms-fill { + background-color: #0a0a0a; } + html.theme--documenter-dark .progress.is-black:indeterminate { + background-image: linear-gradient(to right, #0a0a0a 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-light::-webkit-progress-value { + background-color: #ecf0f1; } + html.theme--documenter-dark .progress.is-light::-moz-progress-bar { + background-color: #ecf0f1; } + html.theme--documenter-dark .progress.is-light::-ms-fill { + background-color: #ecf0f1; } + html.theme--documenter-dark .progress.is-light:indeterminate { + background-image: linear-gradient(to right, #ecf0f1 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-dark::-webkit-progress-value, html.theme--documenter-dark .content kbd.progress::-webkit-progress-value { + background-color: #282f2f; } + html.theme--documenter-dark .progress.is-dark::-moz-progress-bar, html.theme--documenter-dark .content kbd.progress::-moz-progress-bar { + background-color: #282f2f; } + html.theme--documenter-dark .progress.is-dark::-ms-fill, html.theme--documenter-dark .content kbd.progress::-ms-fill { + background-color: #282f2f; } + html.theme--documenter-dark .progress.is-dark:indeterminate, html.theme--documenter-dark .content kbd.progress:indeterminate { + background-image: linear-gradient(to right, #282f2f 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-primary::-webkit-progress-value, html.theme--documenter-dark .docstring > section > a.progress.docs-sourcelink::-webkit-progress-value { + background-color: #375a7f; } + html.theme--documenter-dark .progress.is-primary::-moz-progress-bar, html.theme--documenter-dark .docstring > section > a.progress.docs-sourcelink::-moz-progress-bar { + background-color: #375a7f; } + html.theme--documenter-dark .progress.is-primary::-ms-fill, html.theme--documenter-dark .docstring > section > a.progress.docs-sourcelink::-ms-fill { + background-color: #375a7f; } + html.theme--documenter-dark .progress.is-primary:indeterminate, html.theme--documenter-dark .docstring > section > a.progress.docs-sourcelink:indeterminate { + background-image: linear-gradient(to right, #375a7f 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-link::-webkit-progress-value { + background-color: #1abc9c; } + html.theme--documenter-dark .progress.is-link::-moz-progress-bar { + background-color: #1abc9c; } + html.theme--documenter-dark .progress.is-link::-ms-fill { + background-color: #1abc9c; } + html.theme--documenter-dark .progress.is-link:indeterminate { + background-image: linear-gradient(to right, #1abc9c 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-info::-webkit-progress-value { + background-color: #024c7d; } + html.theme--documenter-dark .progress.is-info::-moz-progress-bar { + background-color: #024c7d; } + html.theme--documenter-dark .progress.is-info::-ms-fill { + background-color: #024c7d; } + html.theme--documenter-dark .progress.is-info:indeterminate { + background-image: linear-gradient(to right, #024c7d 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-success::-webkit-progress-value { + background-color: #008438; } + html.theme--documenter-dark .progress.is-success::-moz-progress-bar { + background-color: #008438; } + html.theme--documenter-dark .progress.is-success::-ms-fill { + background-color: #008438; } + html.theme--documenter-dark .progress.is-success:indeterminate { + background-image: linear-gradient(to right, #008438 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-warning::-webkit-progress-value { + background-color: #ad8100; } + html.theme--documenter-dark .progress.is-warning::-moz-progress-bar { + background-color: #ad8100; } + html.theme--documenter-dark .progress.is-warning::-ms-fill { + background-color: #ad8100; } + html.theme--documenter-dark .progress.is-warning:indeterminate { + background-image: linear-gradient(to right, #ad8100 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress.is-danger::-webkit-progress-value { + background-color: #9e1b0d; } + html.theme--documenter-dark .progress.is-danger::-moz-progress-bar { + background-color: #9e1b0d; } + html.theme--documenter-dark .progress.is-danger::-ms-fill { + background-color: #9e1b0d; } + html.theme--documenter-dark .progress.is-danger:indeterminate { + background-image: linear-gradient(to right, #9e1b0d 30%, #5e6d6f 30%); } + html.theme--documenter-dark .progress:indeterminate { + animation-duration: 1.5s; + animation-iteration-count: infinite; + animation-name: moveIndeterminate; + animation-timing-function: linear; + background-color: #5e6d6f; + background-image: linear-gradient(to right, #fff 30%, #5e6d6f 30%); + background-position: top left; + background-repeat: no-repeat; + background-size: 150% 150%; } + html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar { + background-color: transparent; } + html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar { + background-color: transparent; } + html.theme--documenter-dark .progress.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.progress { + height: 0.85em; } + html.theme--documenter-dark .progress.is-medium { + height: 1.25rem; } + html.theme--documenter-dark .progress.is-large { + height: 1.5rem; } + +@keyframes moveIndeterminate { + from { + background-position: 200% 0; } + to { + background-position: -200% 0; } } + html.theme--documenter-dark .table { + background-color: #343c3d; + color: #fff; } + html.theme--documenter-dark .table td, + html.theme--documenter-dark .table th { + border: 1px solid #5e6d6f; + border-width: 0 0 1px; + padding: 0.5em 0.75em; + vertical-align: top; } + html.theme--documenter-dark .table td.is-white, + html.theme--documenter-dark .table th.is-white { + background-color: white; + border-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .table td.is-black, + html.theme--documenter-dark .table th.is-black { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .table td.is-light, + html.theme--documenter-dark .table th.is-light { + background-color: #ecf0f1; + border-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .table td.is-dark, + html.theme--documenter-dark .table th.is-dark { + background-color: #282f2f; + border-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .table td.is-primary, + html.theme--documenter-dark .table th.is-primary { + background-color: #375a7f; + border-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .table td.is-link, + html.theme--documenter-dark .table th.is-link { + background-color: #1abc9c; + border-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .table td.is-info, + html.theme--documenter-dark .table th.is-info { + background-color: #024c7d; + border-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .table td.is-success, + html.theme--documenter-dark .table th.is-success { + background-color: #008438; + border-color: #008438; + color: #fff; } + html.theme--documenter-dark .table td.is-warning, + html.theme--documenter-dark .table th.is-warning { + background-color: #ad8100; + border-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .table td.is-danger, + html.theme--documenter-dark .table th.is-danger { + background-color: #9e1b0d; + border-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .table td.is-narrow, + html.theme--documenter-dark .table th.is-narrow { + white-space: nowrap; + width: 1%; } + html.theme--documenter-dark .table td.is-selected, + html.theme--documenter-dark .table th.is-selected { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .table td.is-selected a, + html.theme--documenter-dark .table td.is-selected strong, + html.theme--documenter-dark .table th.is-selected a, + html.theme--documenter-dark .table th.is-selected strong { + color: currentColor; } + html.theme--documenter-dark .table th { + color: #f2f2f2; } + html.theme--documenter-dark .table th:not([align]) { + text-align: left; } + html.theme--documenter-dark .table tr.is-selected { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .table tr.is-selected a, + html.theme--documenter-dark .table tr.is-selected strong { + color: currentColor; } + html.theme--documenter-dark .table tr.is-selected td, + html.theme--documenter-dark .table tr.is-selected th { + border-color: #fff; + color: currentColor; } + html.theme--documenter-dark .table thead { + background-color: transparent; } + html.theme--documenter-dark .table thead td, + html.theme--documenter-dark .table thead th { + border-width: 0 0 2px; + color: #f2f2f2; } + html.theme--documenter-dark .table tfoot { + background-color: transparent; } + html.theme--documenter-dark .table tfoot td, + html.theme--documenter-dark .table tfoot th { + border-width: 2px 0 0; + color: #f2f2f2; } + html.theme--documenter-dark .table tbody { + background-color: transparent; } + html.theme--documenter-dark .table tbody tr:last-child td, + html.theme--documenter-dark .table tbody tr:last-child th { + border-bottom-width: 0; } + html.theme--documenter-dark .table.is-bordered td, + html.theme--documenter-dark .table.is-bordered th { + border-width: 1px; } + html.theme--documenter-dark .table.is-bordered tr:last-child td, + html.theme--documenter-dark .table.is-bordered tr:last-child th { + border-bottom-width: 1px; } + html.theme--documenter-dark .table.is-fullwidth { + width: 100%; } + html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover { + background-color: #282f2f; } + html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover { + background-color: #282f2f; } + html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even) { + background-color: #2d3435; } + html.theme--documenter-dark .table.is-narrow td, + html.theme--documenter-dark .table.is-narrow th { + padding: 0.25em 0.5em; } + html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even) { + background-color: #282f2f; } + html.theme--documenter-dark .table-container { + -webkit-overflow-scrolling: touch; + overflow: auto; + overflow-y: hidden; + max-width: 100%; } + html.theme--documenter-dark .tags { + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + html.theme--documenter-dark .tags .tag, html.theme--documenter-dark .tags .content kbd, html.theme--documenter-dark .content .tags kbd, html.theme--documenter-dark .tags .docstring > section > a.docs-sourcelink { + margin-bottom: 0.5rem; } + html.theme--documenter-dark .tags .tag:not(:last-child), html.theme--documenter-dark .tags .content kbd:not(:last-child), html.theme--documenter-dark .content .tags kbd:not(:last-child), html.theme--documenter-dark .tags .docstring > section > a.docs-sourcelink:not(:last-child) { + margin-right: 0.5rem; } + html.theme--documenter-dark .tags:last-child { + margin-bottom: -0.5rem; } + html.theme--documenter-dark .tags:not(:last-child) { + margin-bottom: 1rem; } + html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large), html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large), html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large), html.theme--documenter-dark .tags.are-medium .docstring > section > a.docs-sourcelink:not(.is-normal):not(.is-large) { + font-size: 15px; } + html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium), html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium), html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium), html.theme--documenter-dark .tags.are-large .docstring > section > a.docs-sourcelink:not(.is-normal):not(.is-medium) { + font-size: 1.25rem; } + html.theme--documenter-dark .tags.is-centered { + justify-content: center; } + html.theme--documenter-dark .tags.is-centered .tag, html.theme--documenter-dark .tags.is-centered .content kbd, html.theme--documenter-dark .content .tags.is-centered kbd, html.theme--documenter-dark .tags.is-centered .docstring > section > a.docs-sourcelink { + margin-right: 0.25rem; + margin-left: 0.25rem; } + html.theme--documenter-dark .tags.is-right { + justify-content: flex-end; } + html.theme--documenter-dark .tags.is-right .tag:not(:first-child), html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child), html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child), html.theme--documenter-dark .tags.is-right .docstring > section > a.docs-sourcelink:not(:first-child) { + margin-left: 0.5rem; } + html.theme--documenter-dark .tags.is-right .tag:not(:last-child), html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child), html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child), html.theme--documenter-dark .tags.is-right .docstring > section > a.docs-sourcelink:not(:last-child) { + margin-right: 0; } + html.theme--documenter-dark .tags.has-addons .tag, html.theme--documenter-dark .tags.has-addons .content kbd, html.theme--documenter-dark .content .tags.has-addons kbd, html.theme--documenter-dark .tags.has-addons .docstring > section > a.docs-sourcelink { + margin-right: 0; } + html.theme--documenter-dark .tags.has-addons .tag:not(:first-child), html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child), html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child), html.theme--documenter-dark .tags.has-addons .docstring > section > a.docs-sourcelink:not(:first-child) { + margin-left: 0; + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + html.theme--documenter-dark .tags.has-addons .tag:not(:last-child), html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child), html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child), html.theme--documenter-dark .tags.has-addons .docstring > section > a.docs-sourcelink:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + html.theme--documenter-dark .tag:not(body), html.theme--documenter-dark .content kbd:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) { + align-items: center; + background-color: #282f2f; + border-radius: 0.4em; + color: #fff; + display: inline-flex; + font-size: 0.85em; + height: 2em; + justify-content: center; + line-height: 1.5; + padding-left: 0.75em; + padding-right: 0.75em; + white-space: nowrap; } + html.theme--documenter-dark .tag:not(body) .delete, html.theme--documenter-dark .content kbd:not(body) .delete, html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) .delete { + margin-left: 0.25rem; + margin-right: -0.375rem; } + html.theme--documenter-dark .tag.is-white:not(body), html.theme--documenter-dark .content kbd.is-white:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-white:not(body) { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .tag.is-black:not(body), html.theme--documenter-dark .content kbd.is-black:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-black:not(body) { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .tag.is-light:not(body), html.theme--documenter-dark .content kbd.is-light:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-light:not(body) { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .tag.is-dark:not(body), html.theme--documenter-dark .content kbd:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-dark:not(body), html.theme--documenter-dark .content .docstring > section > kbd:not(body) { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .tag.is-primary:not(body), html.theme--documenter-dark .content kbd.is-primary:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .tag.is-link:not(body), html.theme--documenter-dark .content kbd.is-link:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-link:not(body) { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .tag.is-info:not(body), html.theme--documenter-dark .content kbd.is-info:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-info:not(body) { + background-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .tag.is-success:not(body), html.theme--documenter-dark .content kbd.is-success:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-success:not(body) { + background-color: #008438; + color: #fff; } + html.theme--documenter-dark .tag.is-warning:not(body), html.theme--documenter-dark .content kbd.is-warning:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-warning:not(body) { + background-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .tag.is-danger:not(body), html.theme--documenter-dark .content kbd.is-danger:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-danger:not(body) { + background-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .tag.is-normal:not(body), html.theme--documenter-dark .content kbd.is-normal:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-normal:not(body) { + font-size: 0.85em; } + html.theme--documenter-dark .tag.is-medium:not(body), html.theme--documenter-dark .content kbd.is-medium:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-medium:not(body) { + font-size: 15px; } + html.theme--documenter-dark .tag.is-large:not(body), html.theme--documenter-dark .content kbd.is-large:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-large:not(body) { + font-size: 1.25rem; } + html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child), html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child), html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) .icon:first-child:not(:last-child) { + margin-left: -0.375em; + margin-right: 0.1875em; } + html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child), html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child), html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) .icon:last-child:not(:first-child) { + margin-left: 0.1875em; + margin-right: -0.375em; } + html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child, html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child, html.theme--documenter-dark .docstring > section > a.docs-sourcelink:not(body) .icon:first-child:last-child { + margin-left: -0.375em; + margin-right: -0.375em; } + html.theme--documenter-dark .tag.is-delete:not(body), html.theme--documenter-dark .content kbd.is-delete:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body) { + margin-left: 1px; + padding: 0; + position: relative; + width: 2em; } + html.theme--documenter-dark .tag.is-delete:not(body)::before, html.theme--documenter-dark .content kbd.is-delete:not(body)::before, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body)::before, html.theme--documenter-dark .tag.is-delete:not(body)::after, html.theme--documenter-dark .content kbd.is-delete:not(body)::after, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body)::after { + background-color: currentColor; + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; } + html.theme--documenter-dark .tag.is-delete:not(body)::before, html.theme--documenter-dark .content kbd.is-delete:not(body)::before, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body)::before { + height: 1px; + width: 50%; } + html.theme--documenter-dark .tag.is-delete:not(body)::after, html.theme--documenter-dark .content kbd.is-delete:not(body)::after, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body)::after { + height: 50%; + width: 1px; } + html.theme--documenter-dark .tag.is-delete:not(body):hover, html.theme--documenter-dark .content kbd.is-delete:not(body):hover, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body):hover, html.theme--documenter-dark .tag.is-delete:not(body):focus, html.theme--documenter-dark .content kbd.is-delete:not(body):focus, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body):focus { + background-color: #1d2122; } + html.theme--documenter-dark .tag.is-delete:not(body):active, html.theme--documenter-dark .content kbd.is-delete:not(body):active, html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-delete:not(body):active { + background-color: #111414; } + html.theme--documenter-dark .tag.is-rounded:not(body), html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:not(body), html.theme--documenter-dark .content kbd.is-rounded:not(body), html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search > input:not(body), html.theme--documenter-dark .docstring > section > a.docs-sourcelink.is-rounded:not(body) { + border-radius: 290486px; } + html.theme--documenter-dark a.tag:hover, html.theme--documenter-dark .docstring > section > a.docs-sourcelink:hover { + text-decoration: underline; } + html.theme--documenter-dark .title, + html.theme--documenter-dark .subtitle { + word-break: break-word; } + html.theme--documenter-dark .title em, + html.theme--documenter-dark .title span, + html.theme--documenter-dark .subtitle em, + html.theme--documenter-dark .subtitle span { + font-weight: inherit; } + html.theme--documenter-dark .title sub, + html.theme--documenter-dark .subtitle sub { + font-size: 0.75em; } + html.theme--documenter-dark .title sup, + html.theme--documenter-dark .subtitle sup { + font-size: 0.75em; } + html.theme--documenter-dark .title .tag, html.theme--documenter-dark .title .content kbd, html.theme--documenter-dark .content .title kbd, html.theme--documenter-dark .title .docstring > section > a.docs-sourcelink, + html.theme--documenter-dark .subtitle .tag, + html.theme--documenter-dark .subtitle .content kbd, + html.theme--documenter-dark .content .subtitle kbd, + html.theme--documenter-dark .subtitle .docstring > section > a.docs-sourcelink { + vertical-align: middle; } + html.theme--documenter-dark .title { + color: #fff; + font-size: 2rem; + font-weight: 500; + line-height: 1.125; } + html.theme--documenter-dark .title strong { + color: inherit; + font-weight: inherit; } + html.theme--documenter-dark .title + .highlight { + margin-top: -0.75rem; } + html.theme--documenter-dark .title:not(.is-spaced) + .subtitle { + margin-top: -1.25rem; } + html.theme--documenter-dark .title.is-1 { + font-size: 3rem; } + html.theme--documenter-dark .title.is-2 { + font-size: 2.5rem; } + html.theme--documenter-dark .title.is-3 { + font-size: 2rem; } + html.theme--documenter-dark .title.is-4 { + font-size: 1.5rem; } + html.theme--documenter-dark .title.is-5 { + font-size: 1.25rem; } + html.theme--documenter-dark .title.is-6 { + font-size: 15px; } + html.theme--documenter-dark .title.is-7 { + font-size: 0.85em; } + html.theme--documenter-dark .subtitle { + color: #8c9b9d; + font-size: 1.25rem; + font-weight: 400; + line-height: 1.25; } + html.theme--documenter-dark .subtitle strong { + color: #8c9b9d; + font-weight: 600; } + html.theme--documenter-dark .subtitle:not(.is-spaced) + .title { + margin-top: -1.25rem; } + html.theme--documenter-dark .subtitle.is-1 { + font-size: 3rem; } + html.theme--documenter-dark .subtitle.is-2 { + font-size: 2.5rem; } + html.theme--documenter-dark .subtitle.is-3 { + font-size: 2rem; } + html.theme--documenter-dark .subtitle.is-4 { + font-size: 1.5rem; } + html.theme--documenter-dark .subtitle.is-5 { + font-size: 1.25rem; } + html.theme--documenter-dark .subtitle.is-6 { + font-size: 15px; } + html.theme--documenter-dark .subtitle.is-7 { + font-size: 0.85em; } + html.theme--documenter-dark .heading { + display: block; + font-size: 11px; + letter-spacing: 1px; + margin-bottom: 5px; + text-transform: uppercase; } + html.theme--documenter-dark .highlight { + font-weight: 400; + max-width: 100%; + overflow: hidden; + padding: 0; } + html.theme--documenter-dark .highlight pre { + overflow: auto; + max-width: 100%; } + html.theme--documenter-dark .number { + align-items: center; + background-color: #282f2f; + border-radius: 290486px; + display: inline-flex; + font-size: 1.25rem; + height: 2em; + justify-content: center; + margin-right: 1.5rem; + min-width: 2.5em; + padding: 0.25rem 0.5rem; + text-align: center; + vertical-align: top; } + html.theme--documenter-dark .select select, html.theme--documenter-dark .textarea, html.theme--documenter-dark .input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + background-color: #1f2424; + border-color: #5e6d6f; + border-radius: 0.4em; + color: #dbdee0; } + html.theme--documenter-dark .select select::-moz-placeholder, html.theme--documenter-dark .textarea::-moz-placeholder, html.theme--documenter-dark .input::-moz-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input::-moz-placeholder { + color: rgba(219, 222, 224, 0.3); } + html.theme--documenter-dark .select select::-webkit-input-placeholder, html.theme--documenter-dark .textarea::-webkit-input-placeholder, html.theme--documenter-dark .input::-webkit-input-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input::-webkit-input-placeholder { + color: rgba(219, 222, 224, 0.3); } + html.theme--documenter-dark .select select:-moz-placeholder, html.theme--documenter-dark .textarea:-moz-placeholder, html.theme--documenter-dark .input:-moz-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:-moz-placeholder { + color: rgba(219, 222, 224, 0.3); } + html.theme--documenter-dark .select select:-ms-input-placeholder, html.theme--documenter-dark .textarea:-ms-input-placeholder, html.theme--documenter-dark .input:-ms-input-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:-ms-input-placeholder { + color: rgba(219, 222, 224, 0.3); } + html.theme--documenter-dark .select select:hover, html.theme--documenter-dark .textarea:hover, html.theme--documenter-dark .input:hover, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:hover, html.theme--documenter-dark .select select.is-hovered, html.theme--documenter-dark .is-hovered.textarea, html.theme--documenter-dark .is-hovered.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-hovered { + border-color: #8c9b9d; } + html.theme--documenter-dark .select select:focus, html.theme--documenter-dark .textarea:focus, html.theme--documenter-dark .input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:focus, html.theme--documenter-dark .select select.is-focused, html.theme--documenter-dark .is-focused.textarea, html.theme--documenter-dark .is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .select select:active, html.theme--documenter-dark .textarea:active, html.theme--documenter-dark .input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:active, html.theme--documenter-dark .select select.is-active, html.theme--documenter-dark .is-active.textarea, html.theme--documenter-dark .is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + border-color: #1abc9c; + box-shadow: 0 0 0 0.125em rgba(26, 188, 156, 0.25); } + html.theme--documenter-dark .select select[disabled], html.theme--documenter-dark .textarea[disabled], html.theme--documenter-dark .input[disabled], html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled], fieldset[disabled] html.theme--documenter-dark .select select, fieldset[disabled] html.theme--documenter-dark .textarea, fieldset[disabled] html.theme--documenter-dark .input, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + background-color: #8c9b9d; + border-color: #282f2f; + box-shadow: none; + color: white; } + html.theme--documenter-dark .select select[disabled]::-moz-placeholder, html.theme--documenter-dark .textarea[disabled]::-moz-placeholder, html.theme--documenter-dark .input[disabled]::-moz-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled]::-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input::-moz-placeholder { + color: rgba(255, 255, 255, 0.3); } + html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder, html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder, html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled]::-webkit-input-placeholder, fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder, fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder, fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.3); } + html.theme--documenter-dark .select select[disabled]:-moz-placeholder, html.theme--documenter-dark .textarea[disabled]:-moz-placeholder, html.theme--documenter-dark .input[disabled]:-moz-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled]:-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder, fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:-moz-placeholder { + color: rgba(255, 255, 255, 0.3); } + html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder, html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder, html.theme--documenter-dark .input[disabled]:-ms-input-placeholder, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[disabled]:-ms-input-placeholder, fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder, fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder, fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder, fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input:-ms-input-placeholder { + color: rgba(255, 255, 255, 0.3); } + html.theme--documenter-dark .textarea, html.theme--documenter-dark .input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + max-width: 100%; + width: 100%; } + html.theme--documenter-dark .textarea[readonly], html.theme--documenter-dark .input[readonly], html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input[readonly] { + box-shadow: none; } + html.theme--documenter-dark .is-white.textarea, html.theme--documenter-dark .is-white.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-white { + border-color: white; } + html.theme--documenter-dark .is-white.textarea:focus, html.theme--documenter-dark .is-white.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-white:focus, html.theme--documenter-dark .is-white.is-focused.textarea, html.theme--documenter-dark .is-white.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-white.textarea:active, html.theme--documenter-dark .is-white.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-white:active, html.theme--documenter-dark .is-white.is-active.textarea, html.theme--documenter-dark .is-white.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + html.theme--documenter-dark .is-black.textarea, html.theme--documenter-dark .is-black.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-black { + border-color: #0a0a0a; } + html.theme--documenter-dark .is-black.textarea:focus, html.theme--documenter-dark .is-black.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-black:focus, html.theme--documenter-dark .is-black.is-focused.textarea, html.theme--documenter-dark .is-black.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-black.textarea:active, html.theme--documenter-dark .is-black.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-black:active, html.theme--documenter-dark .is-black.is-active.textarea, html.theme--documenter-dark .is-black.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + html.theme--documenter-dark .is-light.textarea, html.theme--documenter-dark .is-light.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-light { + border-color: #ecf0f1; } + html.theme--documenter-dark .is-light.textarea:focus, html.theme--documenter-dark .is-light.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-light:focus, html.theme--documenter-dark .is-light.is-focused.textarea, html.theme--documenter-dark .is-light.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-light.textarea:active, html.theme--documenter-dark .is-light.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-light:active, html.theme--documenter-dark .is-light.is-active.textarea, html.theme--documenter-dark .is-light.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(236, 240, 241, 0.25); } + html.theme--documenter-dark .is-dark.textarea, html.theme--documenter-dark .content kbd.textarea, html.theme--documenter-dark .is-dark.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-dark, html.theme--documenter-dark .content kbd.input { + border-color: #282f2f; } + html.theme--documenter-dark .is-dark.textarea:focus, html.theme--documenter-dark .content kbd.textarea:focus, html.theme--documenter-dark .is-dark.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-dark:focus, html.theme--documenter-dark .content kbd.input:focus, html.theme--documenter-dark .is-dark.is-focused.textarea, html.theme--documenter-dark .content kbd.is-focused.textarea, html.theme--documenter-dark .is-dark.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .content kbd.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search > input.is-focused, html.theme--documenter-dark .is-dark.textarea:active, html.theme--documenter-dark .content kbd.textarea:active, html.theme--documenter-dark .is-dark.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-dark:active, html.theme--documenter-dark .content kbd.input:active, html.theme--documenter-dark .is-dark.is-active.textarea, html.theme--documenter-dark .content kbd.is-active.textarea, html.theme--documenter-dark .is-dark.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active, html.theme--documenter-dark .content kbd.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(40, 47, 47, 0.25); } + html.theme--documenter-dark .is-primary.textarea, html.theme--documenter-dark .docstring > section > a.textarea.docs-sourcelink, html.theme--documenter-dark .is-primary.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-primary, html.theme--documenter-dark .docstring > section > a.input.docs-sourcelink { + border-color: #375a7f; } + html.theme--documenter-dark .is-primary.textarea:focus, html.theme--documenter-dark .docstring > section > a.textarea.docs-sourcelink:focus, html.theme--documenter-dark .is-primary.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-primary:focus, html.theme--documenter-dark .docstring > section > a.input.docs-sourcelink:focus, html.theme--documenter-dark .is-primary.is-focused.textarea, html.theme--documenter-dark .docstring > section > a.is-focused.textarea.docs-sourcelink, html.theme--documenter-dark .is-primary.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .docstring > section > a.is-focused.input.docs-sourcelink, html.theme--documenter-dark .is-primary.textarea:active, html.theme--documenter-dark .docstring > section > a.textarea.docs-sourcelink:active, html.theme--documenter-dark .is-primary.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-primary:active, html.theme--documenter-dark .docstring > section > a.input.docs-sourcelink:active, html.theme--documenter-dark .is-primary.is-active.textarea, html.theme--documenter-dark .docstring > section > a.is-active.textarea.docs-sourcelink, html.theme--documenter-dark .is-primary.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active, html.theme--documenter-dark .docstring > section > a.is-active.input.docs-sourcelink { + box-shadow: 0 0 0 0.125em rgba(55, 90, 127, 0.25); } + html.theme--documenter-dark .is-link.textarea, html.theme--documenter-dark .is-link.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-link { + border-color: #1abc9c; } + html.theme--documenter-dark .is-link.textarea:focus, html.theme--documenter-dark .is-link.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-link:focus, html.theme--documenter-dark .is-link.is-focused.textarea, html.theme--documenter-dark .is-link.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-link.textarea:active, html.theme--documenter-dark .is-link.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-link:active, html.theme--documenter-dark .is-link.is-active.textarea, html.theme--documenter-dark .is-link.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(26, 188, 156, 0.25); } + html.theme--documenter-dark .is-info.textarea, html.theme--documenter-dark .is-info.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-info { + border-color: #024c7d; } + html.theme--documenter-dark .is-info.textarea:focus, html.theme--documenter-dark .is-info.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-info:focus, html.theme--documenter-dark .is-info.is-focused.textarea, html.theme--documenter-dark .is-info.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-info.textarea:active, html.theme--documenter-dark .is-info.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-info:active, html.theme--documenter-dark .is-info.is-active.textarea, html.theme--documenter-dark .is-info.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(2, 76, 125, 0.25); } + html.theme--documenter-dark .is-success.textarea, html.theme--documenter-dark .is-success.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-success { + border-color: #008438; } + html.theme--documenter-dark .is-success.textarea:focus, html.theme--documenter-dark .is-success.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-success:focus, html.theme--documenter-dark .is-success.is-focused.textarea, html.theme--documenter-dark .is-success.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-success.textarea:active, html.theme--documenter-dark .is-success.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-success:active, html.theme--documenter-dark .is-success.is-active.textarea, html.theme--documenter-dark .is-success.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(0, 132, 56, 0.25); } + html.theme--documenter-dark .is-warning.textarea, html.theme--documenter-dark .is-warning.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-warning { + border-color: #ad8100; } + html.theme--documenter-dark .is-warning.textarea:focus, html.theme--documenter-dark .is-warning.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-warning:focus, html.theme--documenter-dark .is-warning.is-focused.textarea, html.theme--documenter-dark .is-warning.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-warning.textarea:active, html.theme--documenter-dark .is-warning.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-warning:active, html.theme--documenter-dark .is-warning.is-active.textarea, html.theme--documenter-dark .is-warning.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(173, 129, 0, 0.25); } + html.theme--documenter-dark .is-danger.textarea, html.theme--documenter-dark .is-danger.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-danger { + border-color: #9e1b0d; } + html.theme--documenter-dark .is-danger.textarea:focus, html.theme--documenter-dark .is-danger.input:focus, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-danger:focus, html.theme--documenter-dark .is-danger.is-focused.textarea, html.theme--documenter-dark .is-danger.is-focused.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-focused, html.theme--documenter-dark .is-danger.textarea:active, html.theme--documenter-dark .is-danger.input:active, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-danger:active, html.theme--documenter-dark .is-danger.is-active.textarea, html.theme--documenter-dark .is-danger.is-active.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(158, 27, 13, 0.25); } + html.theme--documenter-dark .is-small.textarea, html.theme--documenter-dark .is-small.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + border-radius: 3px; + font-size: 0.85em; } + html.theme--documenter-dark .is-medium.textarea, html.theme--documenter-dark .is-medium.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .is-large.textarea, html.theme--documenter-dark .is-large.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .is-fullwidth.textarea, html.theme--documenter-dark .is-fullwidth.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-fullwidth { + display: block; + width: 100%; } + html.theme--documenter-dark .is-inline.textarea, html.theme--documenter-dark .is-inline.input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-inline { + display: inline; + width: auto; } + html.theme--documenter-dark .input.is-rounded, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + border-radius: 290486px; + padding-left: 1em; + padding-right: 1em; } + html.theme--documenter-dark .input.is-static, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-static { + background-color: transparent; + border-color: transparent; + box-shadow: none; + padding-left: 0; + padding-right: 0; } + html.theme--documenter-dark .textarea { + display: block; + max-width: 100%; + min-width: 100%; + padding: 0.625em; + resize: vertical; } + html.theme--documenter-dark .textarea:not([rows]) { + max-height: 600px; + min-height: 120px; } + html.theme--documenter-dark .textarea[rows] { + height: initial; } + html.theme--documenter-dark .textarea.has-fixed-size { + resize: none; } + html.theme--documenter-dark .radio, html.theme--documenter-dark .checkbox { + cursor: pointer; + display: inline-block; + line-height: 1.25; + position: relative; } + html.theme--documenter-dark .radio input, html.theme--documenter-dark .checkbox input { + cursor: pointer; } + html.theme--documenter-dark .radio:hover, html.theme--documenter-dark .checkbox:hover { + color: #8c9b9d; } + html.theme--documenter-dark .radio[disabled], html.theme--documenter-dark .checkbox[disabled], fieldset[disabled] html.theme--documenter-dark .radio, fieldset[disabled] html.theme--documenter-dark .checkbox { + color: white; + cursor: not-allowed; } + html.theme--documenter-dark .radio + .radio { + margin-left: 0.5em; } + html.theme--documenter-dark .select { + display: inline-block; + max-width: 100%; + position: relative; + vertical-align: top; } + html.theme--documenter-dark .select:not(.is-multiple) { + height: 2.25em; } + html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after { + border-color: #1abc9c; + right: 1.125em; + z-index: 4; } + html.theme--documenter-dark .select.is-rounded select, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.select select { + border-radius: 290486px; + padding-left: 1em; } + html.theme--documenter-dark .select select { + cursor: pointer; + display: block; + font-size: 1em; + max-width: 100%; + outline: none; } + html.theme--documenter-dark .select select::-ms-expand { + display: none; } + html.theme--documenter-dark .select select[disabled]:hover, fieldset[disabled] html.theme--documenter-dark .select select:hover { + border-color: #282f2f; } + html.theme--documenter-dark .select select:not([multiple]) { + padding-right: 2.5em; } + html.theme--documenter-dark .select select[multiple] { + height: auto; + padding: 0; } + html.theme--documenter-dark .select select[multiple] option { + padding: 0.5em 1em; } + html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after { + border-color: #8c9b9d; } + html.theme--documenter-dark .select.is-white:not(:hover)::after { + border-color: white; } + html.theme--documenter-dark .select.is-white select { + border-color: white; } + html.theme--documenter-dark .select.is-white select:hover, html.theme--documenter-dark .select.is-white select.is-hovered { + border-color: #f2f2f2; } + html.theme--documenter-dark .select.is-white select:focus, html.theme--documenter-dark .select.is-white select.is-focused, html.theme--documenter-dark .select.is-white select:active, html.theme--documenter-dark .select.is-white select.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + html.theme--documenter-dark .select.is-black:not(:hover)::after { + border-color: #0a0a0a; } + html.theme--documenter-dark .select.is-black select { + border-color: #0a0a0a; } + html.theme--documenter-dark .select.is-black select:hover, html.theme--documenter-dark .select.is-black select.is-hovered { + border-color: black; } + html.theme--documenter-dark .select.is-black select:focus, html.theme--documenter-dark .select.is-black select.is-focused, html.theme--documenter-dark .select.is-black select:active, html.theme--documenter-dark .select.is-black select.is-active { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + html.theme--documenter-dark .select.is-light:not(:hover)::after { + border-color: #ecf0f1; } + html.theme--documenter-dark .select.is-light select { + border-color: #ecf0f1; } + html.theme--documenter-dark .select.is-light select:hover, html.theme--documenter-dark .select.is-light select.is-hovered { + border-color: #dde4e6; } + html.theme--documenter-dark .select.is-light select:focus, html.theme--documenter-dark .select.is-light select.is-focused, html.theme--documenter-dark .select.is-light select:active, html.theme--documenter-dark .select.is-light select.is-active { + box-shadow: 0 0 0 0.125em rgba(236, 240, 241, 0.25); } + html.theme--documenter-dark .select.is-dark:not(:hover)::after, html.theme--documenter-dark .content kbd.select:not(:hover)::after { + border-color: #282f2f; } + html.theme--documenter-dark .select.is-dark select, html.theme--documenter-dark .content kbd.select select { + border-color: #282f2f; } + html.theme--documenter-dark .select.is-dark select:hover, html.theme--documenter-dark .content kbd.select select:hover, html.theme--documenter-dark .select.is-dark select.is-hovered, html.theme--documenter-dark .content kbd.select select.is-hovered { + border-color: #1d2122; } + html.theme--documenter-dark .select.is-dark select:focus, html.theme--documenter-dark .content kbd.select select:focus, html.theme--documenter-dark .select.is-dark select.is-focused, html.theme--documenter-dark .content kbd.select select.is-focused, html.theme--documenter-dark .select.is-dark select:active, html.theme--documenter-dark .content kbd.select select:active, html.theme--documenter-dark .select.is-dark select.is-active, html.theme--documenter-dark .content kbd.select select.is-active { + box-shadow: 0 0 0 0.125em rgba(40, 47, 47, 0.25); } + html.theme--documenter-dark .select.is-primary:not(:hover)::after, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink:not(:hover)::after { + border-color: #375a7f; } + html.theme--documenter-dark .select.is-primary select, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select { + border-color: #375a7f; } + html.theme--documenter-dark .select.is-primary select:hover, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select:hover, html.theme--documenter-dark .select.is-primary select.is-hovered, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select.is-hovered { + border-color: #2f4d6d; } + html.theme--documenter-dark .select.is-primary select:focus, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select:focus, html.theme--documenter-dark .select.is-primary select.is-focused, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select.is-focused, html.theme--documenter-dark .select.is-primary select:active, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select:active, html.theme--documenter-dark .select.is-primary select.is-active, html.theme--documenter-dark .docstring > section > a.select.docs-sourcelink select.is-active { + box-shadow: 0 0 0 0.125em rgba(55, 90, 127, 0.25); } + html.theme--documenter-dark .select.is-link:not(:hover)::after { + border-color: #1abc9c; } + html.theme--documenter-dark .select.is-link select { + border-color: #1abc9c; } + html.theme--documenter-dark .select.is-link select:hover, html.theme--documenter-dark .select.is-link select.is-hovered { + border-color: #17a689; } + html.theme--documenter-dark .select.is-link select:focus, html.theme--documenter-dark .select.is-link select.is-focused, html.theme--documenter-dark .select.is-link select:active, html.theme--documenter-dark .select.is-link select.is-active { + box-shadow: 0 0 0 0.125em rgba(26, 188, 156, 0.25); } + html.theme--documenter-dark .select.is-info:not(:hover)::after { + border-color: #024c7d; } + html.theme--documenter-dark .select.is-info select { + border-color: #024c7d; } + html.theme--documenter-dark .select.is-info select:hover, html.theme--documenter-dark .select.is-info select.is-hovered { + border-color: #023d64; } + html.theme--documenter-dark .select.is-info select:focus, html.theme--documenter-dark .select.is-info select.is-focused, html.theme--documenter-dark .select.is-info select:active, html.theme--documenter-dark .select.is-info select.is-active { + box-shadow: 0 0 0 0.125em rgba(2, 76, 125, 0.25); } + html.theme--documenter-dark .select.is-success:not(:hover)::after { + border-color: #008438; } + html.theme--documenter-dark .select.is-success select { + border-color: #008438; } + html.theme--documenter-dark .select.is-success select:hover, html.theme--documenter-dark .select.is-success select.is-hovered { + border-color: #006b2d; } + html.theme--documenter-dark .select.is-success select:focus, html.theme--documenter-dark .select.is-success select.is-focused, html.theme--documenter-dark .select.is-success select:active, html.theme--documenter-dark .select.is-success select.is-active { + box-shadow: 0 0 0 0.125em rgba(0, 132, 56, 0.25); } + html.theme--documenter-dark .select.is-warning:not(:hover)::after { + border-color: #ad8100; } + html.theme--documenter-dark .select.is-warning select { + border-color: #ad8100; } + html.theme--documenter-dark .select.is-warning select:hover, html.theme--documenter-dark .select.is-warning select.is-hovered { + border-color: #946e00; } + html.theme--documenter-dark .select.is-warning select:focus, html.theme--documenter-dark .select.is-warning select.is-focused, html.theme--documenter-dark .select.is-warning select:active, html.theme--documenter-dark .select.is-warning select.is-active { + box-shadow: 0 0 0 0.125em rgba(173, 129, 0, 0.25); } + html.theme--documenter-dark .select.is-danger:not(:hover)::after { + border-color: #9e1b0d; } + html.theme--documenter-dark .select.is-danger select { + border-color: #9e1b0d; } + html.theme--documenter-dark .select.is-danger select:hover, html.theme--documenter-dark .select.is-danger select.is-hovered { + border-color: #86170b; } + html.theme--documenter-dark .select.is-danger select:focus, html.theme--documenter-dark .select.is-danger select.is-focused, html.theme--documenter-dark .select.is-danger select:active, html.theme--documenter-dark .select.is-danger select.is-active { + box-shadow: 0 0 0 0.125em rgba(158, 27, 13, 0.25); } + html.theme--documenter-dark .select.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.select { + border-radius: 3px; + font-size: 0.85em; } + html.theme--documenter-dark .select.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .select.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .select.is-disabled::after { + border-color: white; } + html.theme--documenter-dark .select.is-fullwidth { + width: 100%; } + html.theme--documenter-dark .select.is-fullwidth select { + width: 100%; } + html.theme--documenter-dark .select.is-loading::after { + margin-top: 0; + position: absolute; + right: 0.625em; + top: 0.625em; + transform: none; } + html.theme--documenter-dark .select.is-loading.is-small:after, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-loading:after { + font-size: 0.85em; } + html.theme--documenter-dark .select.is-loading.is-medium:after { + font-size: 1.25rem; } + html.theme--documenter-dark .select.is-loading.is-large:after { + font-size: 1.5rem; } + html.theme--documenter-dark .file { + align-items: stretch; + display: flex; + justify-content: flex-start; + position: relative; } + html.theme--documenter-dark .file.is-white .file-cta { + background-color: white; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .file.is-white:hover .file-cta, html.theme--documenter-dark .file.is-white.is-hovered .file-cta { + background-color: #f9f9f9; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .file.is-white:focus .file-cta, html.theme--documenter-dark .file.is-white.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(255, 255, 255, 0.25); + color: #0a0a0a; } + html.theme--documenter-dark .file.is-white:active .file-cta, html.theme--documenter-dark .file.is-white.is-active .file-cta { + background-color: #f2f2f2; + border-color: transparent; + color: #0a0a0a; } + html.theme--documenter-dark .file.is-black .file-cta { + background-color: #0a0a0a; + border-color: transparent; + color: white; } + html.theme--documenter-dark .file.is-black:hover .file-cta, html.theme--documenter-dark .file.is-black.is-hovered .file-cta { + background-color: #040404; + border-color: transparent; + color: white; } + html.theme--documenter-dark .file.is-black:focus .file-cta, html.theme--documenter-dark .file.is-black.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(10, 10, 10, 0.25); + color: white; } + html.theme--documenter-dark .file.is-black:active .file-cta, html.theme--documenter-dark .file.is-black.is-active .file-cta { + background-color: black; + border-color: transparent; + color: white; } + html.theme--documenter-dark .file.is-light .file-cta { + background-color: #ecf0f1; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .file.is-light:hover .file-cta, html.theme--documenter-dark .file.is-light.is-hovered .file-cta { + background-color: #e5eaec; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .file.is-light:focus .file-cta, html.theme--documenter-dark .file.is-light.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(236, 240, 241, 0.25); + color: #282f2f; } + html.theme--documenter-dark .file.is-light:active .file-cta, html.theme--documenter-dark .file.is-light.is-active .file-cta { + background-color: #dde4e6; + border-color: transparent; + color: #282f2f; } + html.theme--documenter-dark .file.is-dark .file-cta, html.theme--documenter-dark .content kbd.file .file-cta { + background-color: #282f2f; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .file.is-dark:hover .file-cta, html.theme--documenter-dark .content kbd.file:hover .file-cta, html.theme--documenter-dark .file.is-dark.is-hovered .file-cta, html.theme--documenter-dark .content kbd.file.is-hovered .file-cta { + background-color: #232829; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .file.is-dark:focus .file-cta, html.theme--documenter-dark .content kbd.file:focus .file-cta, html.theme--documenter-dark .file.is-dark.is-focused .file-cta, html.theme--documenter-dark .content kbd.file.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(40, 47, 47, 0.25); + color: #ecf0f1; } + html.theme--documenter-dark .file.is-dark:active .file-cta, html.theme--documenter-dark .content kbd.file:active .file-cta, html.theme--documenter-dark .file.is-dark.is-active .file-cta, html.theme--documenter-dark .content kbd.file.is-active .file-cta { + background-color: #1d2122; + border-color: transparent; + color: #ecf0f1; } + html.theme--documenter-dark .file.is-primary .file-cta, html.theme--documenter-dark .docstring > section > a.file.docs-sourcelink .file-cta { + background-color: #375a7f; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-primary:hover .file-cta, html.theme--documenter-dark .docstring > section > a.file.docs-sourcelink:hover .file-cta, html.theme--documenter-dark .file.is-primary.is-hovered .file-cta, html.theme--documenter-dark .docstring > section > a.file.is-hovered.docs-sourcelink .file-cta { + background-color: #335476; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-primary:focus .file-cta, html.theme--documenter-dark .docstring > section > a.file.docs-sourcelink:focus .file-cta, html.theme--documenter-dark .file.is-primary.is-focused .file-cta, html.theme--documenter-dark .docstring > section > a.file.is-focused.docs-sourcelink .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(55, 90, 127, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-primary:active .file-cta, html.theme--documenter-dark .docstring > section > a.file.docs-sourcelink:active .file-cta, html.theme--documenter-dark .file.is-primary.is-active .file-cta, html.theme--documenter-dark .docstring > section > a.file.is-active.docs-sourcelink .file-cta { + background-color: #2f4d6d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-link .file-cta { + background-color: #1abc9c; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-link:hover .file-cta, html.theme--documenter-dark .file.is-link.is-hovered .file-cta { + background-color: #18b193; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-link:focus .file-cta, html.theme--documenter-dark .file.is-link.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(26, 188, 156, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-link:active .file-cta, html.theme--documenter-dark .file.is-link.is-active .file-cta { + background-color: #17a689; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-info .file-cta { + background-color: #024c7d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-info:hover .file-cta, html.theme--documenter-dark .file.is-info.is-hovered .file-cta { + background-color: #024470; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-info:focus .file-cta, html.theme--documenter-dark .file.is-info.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(2, 76, 125, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-info:active .file-cta, html.theme--documenter-dark .file.is-info.is-active .file-cta { + background-color: #023d64; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-success .file-cta { + background-color: #008438; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-success:hover .file-cta, html.theme--documenter-dark .file.is-success.is-hovered .file-cta { + background-color: #007733; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-success:focus .file-cta, html.theme--documenter-dark .file.is-success.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(0, 132, 56, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-success:active .file-cta, html.theme--documenter-dark .file.is-success.is-active .file-cta { + background-color: #006b2d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-warning .file-cta { + background-color: #ad8100; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-warning:hover .file-cta, html.theme--documenter-dark .file.is-warning.is-hovered .file-cta { + background-color: #a07700; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-warning:focus .file-cta, html.theme--documenter-dark .file.is-warning.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(173, 129, 0, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-warning:active .file-cta, html.theme--documenter-dark .file.is-warning.is-active .file-cta { + background-color: #946e00; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-danger .file-cta { + background-color: #9e1b0d; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-danger:hover .file-cta, html.theme--documenter-dark .file.is-danger.is-hovered .file-cta { + background-color: #92190c; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-danger:focus .file-cta, html.theme--documenter-dark .file.is-danger.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(158, 27, 13, 0.25); + color: #fff; } + html.theme--documenter-dark .file.is-danger:active .file-cta, html.theme--documenter-dark .file.is-danger.is-active .file-cta { + background-color: #86170b; + border-color: transparent; + color: #fff; } + html.theme--documenter-dark .file.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.file { + font-size: 0.85em; } + html.theme--documenter-dark .file.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .file.is-medium .file-icon .fa { + font-size: 21px; } + html.theme--documenter-dark .file.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .file.is-large .file-icon .fa { + font-size: 28px; } + html.theme--documenter-dark .file.has-name .file-cta { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + html.theme--documenter-dark .file.has-name .file-name { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + html.theme--documenter-dark .file.has-name.is-empty .file-cta { + border-radius: 0.4em; } + html.theme--documenter-dark .file.has-name.is-empty .file-name { + display: none; } + html.theme--documenter-dark .file.is-boxed .file-label { + flex-direction: column; } + html.theme--documenter-dark .file.is-boxed .file-cta { + flex-direction: column; + height: auto; + padding: 1em 3em; } + html.theme--documenter-dark .file.is-boxed .file-name { + border-width: 0 1px 1px; } + html.theme--documenter-dark .file.is-boxed .file-icon { + height: 1.5em; + width: 1.5em; } + html.theme--documenter-dark .file.is-boxed .file-icon .fa { + font-size: 21px; } + html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-boxed .file-icon .fa { + font-size: 14px; } + html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa { + font-size: 28px; } + html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa { + font-size: 35px; } + html.theme--documenter-dark .file.is-boxed.has-name .file-cta { + border-radius: 0.4em 0.4em 0 0; } + html.theme--documenter-dark .file.is-boxed.has-name .file-name { + border-radius: 0 0 0.4em 0.4em; + border-width: 0 1px 1px; } + html.theme--documenter-dark .file.is-centered { + justify-content: center; } + html.theme--documenter-dark .file.is-fullwidth .file-label { + width: 100%; } + html.theme--documenter-dark .file.is-fullwidth .file-name { + flex-grow: 1; + max-width: none; } + html.theme--documenter-dark .file.is-right { + justify-content: flex-end; } + html.theme--documenter-dark .file.is-right .file-cta { + border-radius: 0 0.4em 0.4em 0; } + html.theme--documenter-dark .file.is-right .file-name { + border-radius: 0.4em 0 0 0.4em; + border-width: 1px 0 1px 1px; + order: -1; } + html.theme--documenter-dark .file-label { + align-items: stretch; + display: flex; + cursor: pointer; + justify-content: flex-start; + overflow: hidden; + position: relative; } + html.theme--documenter-dark .file-label:hover .file-cta { + background-color: #e5eaec; + color: #282f2f; } + html.theme--documenter-dark .file-label:hover .file-name { + border-color: #596668; } + html.theme--documenter-dark .file-label:active .file-cta { + background-color: #dde4e6; + color: #282f2f; } + html.theme--documenter-dark .file-label:active .file-name { + border-color: #535f61; } + html.theme--documenter-dark .file-input { + height: 100%; + left: 0; + opacity: 0; + outline: none; + position: absolute; + top: 0; + width: 100%; } + html.theme--documenter-dark .file-cta, + html.theme--documenter-dark .file-name { + border-color: #5e6d6f; + border-radius: 0.4em; + font-size: 1em; + padding-left: 1em; + padding-right: 1em; + white-space: nowrap; } + html.theme--documenter-dark .file-cta { + background-color: #ecf0f1; + color: #343c3d; } + html.theme--documenter-dark .file-name { + border-color: #5e6d6f; + border-style: solid; + border-width: 1px 1px 1px 0; + display: block; + max-width: 16em; + overflow: hidden; + text-align: left; + text-overflow: ellipsis; } + html.theme--documenter-dark .file-icon { + align-items: center; + display: flex; + height: 1em; + justify-content: center; + margin-right: 0.5em; + width: 1em; } + html.theme--documenter-dark .file-icon .fa { + font-size: 14px; } + html.theme--documenter-dark .label { + color: #282f2f; + display: block; + font-size: 15px; + font-weight: 700; } + html.theme--documenter-dark .label:not(:last-child) { + margin-bottom: 0.5em; } + html.theme--documenter-dark .label.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.label { + font-size: 0.85em; } + html.theme--documenter-dark .label.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .label.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .help { + display: block; + font-size: 0.85em; + margin-top: 0.25rem; } + html.theme--documenter-dark .help.is-white { + color: white; } + html.theme--documenter-dark .help.is-black { + color: #0a0a0a; } + html.theme--documenter-dark .help.is-light { + color: #ecf0f1; } + html.theme--documenter-dark .help.is-dark, html.theme--documenter-dark .content kbd.help { + color: #282f2f; } + html.theme--documenter-dark .help.is-primary, html.theme--documenter-dark .docstring > section > a.help.docs-sourcelink { + color: #375a7f; } + html.theme--documenter-dark .help.is-link { + color: #1abc9c; } + html.theme--documenter-dark .help.is-info { + color: #024c7d; } + html.theme--documenter-dark .help.is-success { + color: #008438; } + html.theme--documenter-dark .help.is-warning { + color: #ad8100; } + html.theme--documenter-dark .help.is-danger { + color: #9e1b0d; } + html.theme--documenter-dark .field:not(:last-child) { + margin-bottom: 0.75rem; } + html.theme--documenter-dark .field.has-addons { + display: flex; + justify-content: flex-start; } + html.theme--documenter-dark .field.has-addons .control:not(:last-child) { + margin-right: -1px; } + html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button, + html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input, + html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search > input, + html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select { + border-radius: 0; } + html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button, + html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input, + html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search > input, + html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button, + html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input, + html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search > input, + html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover, html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):hover, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]), + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-hovered:not([disabled]), + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-hovered:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]) { + z-index: 2; } + html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus, html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]), html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active, html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):focus, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):focus, + html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]), + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-focused:not([disabled]), + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-focused:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):active, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):active, + html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]), + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-active:not([disabled]), + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-active:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus, + html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]), + html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active, + html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]) { + z-index: 3; } + html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover, html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover, html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover, html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):focus:hover, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):focus:hover, + html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-focused:not([disabled]):hover, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-focused:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):active:hover, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):active:hover, + html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-active:not([disabled]):hover, + html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-active:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover, + html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover, + html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover, + html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover { + z-index: 4; } + html.theme--documenter-dark .field.has-addons .control.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .field.has-addons.has-addons-centered { + justify-content: center; } + html.theme--documenter-dark .field.has-addons.has-addons-right { + justify-content: flex-end; } + html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control { + flex-grow: 1; + flex-shrink: 0; } + html.theme--documenter-dark .field.is-grouped { + display: flex; + justify-content: flex-start; } + html.theme--documenter-dark .field.is-grouped > .control { + flex-shrink: 0; } + html.theme--documenter-dark .field.is-grouped > .control:not(:last-child) { + margin-bottom: 0; + margin-right: 0.75rem; } + html.theme--documenter-dark .field.is-grouped > .control.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .field.is-grouped.is-grouped-centered { + justify-content: center; } + html.theme--documenter-dark .field.is-grouped.is-grouped-right { + justify-content: flex-end; } + html.theme--documenter-dark .field.is-grouped.is-grouped-multiline { + flex-wrap: wrap; } + html.theme--documenter-dark .field.is-grouped.is-grouped-multiline > .control:last-child, html.theme--documenter-dark .field.is-grouped.is-grouped-multiline > .control:not(:last-child) { + margin-bottom: 0.75rem; } + html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child { + margin-bottom: -0.75rem; } + html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child) { + margin-bottom: 0; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .field.is-horizontal { + display: flex; } } + html.theme--documenter-dark .field-label .label { + font-size: inherit; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .field-label { + margin-bottom: 0.5rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .field-label { + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + margin-right: 1.5rem; + text-align: right; } + html.theme--documenter-dark .field-label.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.field-label { + font-size: 0.85em; + padding-top: 0.375em; } + html.theme--documenter-dark .field-label.is-normal { + padding-top: 0.375em; } + html.theme--documenter-dark .field-label.is-medium { + font-size: 1.25rem; + padding-top: 0.375em; } + html.theme--documenter-dark .field-label.is-large { + font-size: 1.5rem; + padding-top: 0.375em; } } + html.theme--documenter-dark .field-body .field .field { + margin-bottom: 0; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .field-body { + display: flex; + flex-basis: 0; + flex-grow: 5; + flex-shrink: 1; } + html.theme--documenter-dark .field-body .field { + margin-bottom: 0; } + html.theme--documenter-dark .field-body > .field { + flex-shrink: 1; } + html.theme--documenter-dark .field-body > .field:not(.is-narrow) { + flex-grow: 1; } + html.theme--documenter-dark .field-body > .field:not(:last-child) { + margin-right: 0.75rem; } } + html.theme--documenter-dark .control { + box-sizing: border-box; + clear: both; + font-size: 15px; + position: relative; + text-align: left; } + html.theme--documenter-dark .control.has-icons-left .input:focus ~ .icon, html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search > input:focus ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search > input:focus ~ .icon, + html.theme--documenter-dark .control.has-icons-left .select:focus ~ .icon, html.theme--documenter-dark .control.has-icons-right .input:focus ~ .icon, html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search > input:focus ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search > input:focus ~ .icon, + html.theme--documenter-dark .control.has-icons-right .select:focus ~ .icon { + color: #5e6d6f; } + html.theme--documenter-dark .control.has-icons-left .input.is-small ~ .icon, html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search > input ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search > input ~ .icon, + html.theme--documenter-dark .control.has-icons-left .select.is-small ~ .icon, html.theme--documenter-dark .control.has-icons-right .input.is-small ~ .icon, html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search > input ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search > input ~ .icon, + html.theme--documenter-dark .control.has-icons-right .select.is-small ~ .icon { + font-size: 0.85em; } + html.theme--documenter-dark .control.has-icons-left .input.is-medium ~ .icon, html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search > input.is-medium ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search > input.is-medium ~ .icon, + html.theme--documenter-dark .control.has-icons-left .select.is-medium ~ .icon, html.theme--documenter-dark .control.has-icons-right .input.is-medium ~ .icon, html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search > input.is-medium ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search > input.is-medium ~ .icon, + html.theme--documenter-dark .control.has-icons-right .select.is-medium ~ .icon { + font-size: 1.25rem; } + html.theme--documenter-dark .control.has-icons-left .input.is-large ~ .icon, html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search > input.is-large ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search > input.is-large ~ .icon, + html.theme--documenter-dark .control.has-icons-left .select.is-large ~ .icon, html.theme--documenter-dark .control.has-icons-right .input.is-large ~ .icon, html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search > input.is-large ~ .icon, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search > input.is-large ~ .icon, + html.theme--documenter-dark .control.has-icons-right .select.is-large ~ .icon { + font-size: 1.5rem; } + html.theme--documenter-dark .control.has-icons-left .icon, html.theme--documenter-dark .control.has-icons-right .icon { + color: #dbdee0; + height: 2.25em; + pointer-events: none; + position: absolute; + top: 0; + width: 2.25em; + z-index: 4; } + html.theme--documenter-dark .control.has-icons-left .input, html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search > input, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search > input, + html.theme--documenter-dark .control.has-icons-left .select select { + padding-left: 2.25em; } + html.theme--documenter-dark .control.has-icons-left .icon.is-left { + left: 0; } + html.theme--documenter-dark .control.has-icons-right .input, html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search > input, html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search > input, + html.theme--documenter-dark .control.has-icons-right .select select { + padding-right: 2.25em; } + html.theme--documenter-dark .control.has-icons-right .icon.is-right { + right: 0; } + html.theme--documenter-dark .control.is-loading::after { + position: absolute !important; + right: 0.625em; + top: 0.625em; + z-index: 4; } + html.theme--documenter-dark .control.is-loading.is-small:after, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.is-loading:after { + font-size: 0.85em; } + html.theme--documenter-dark .control.is-loading.is-medium:after { + font-size: 1.25rem; } + html.theme--documenter-dark .control.is-loading.is-large:after { + font-size: 1.5rem; } + html.theme--documenter-dark .breadcrumb { + font-size: 15px; + white-space: nowrap; } + html.theme--documenter-dark .breadcrumb a { + align-items: center; + color: #1abc9c; + display: flex; + justify-content: center; + padding: 0 0.75em; } + html.theme--documenter-dark .breadcrumb a:hover { + color: #1dd2af; } + html.theme--documenter-dark .breadcrumb li { + align-items: center; + display: flex; } + html.theme--documenter-dark .breadcrumb li:first-child a { + padding-left: 0; } + html.theme--documenter-dark .breadcrumb li.is-active a { + color: #f2f2f2; + cursor: default; + pointer-events: none; } + html.theme--documenter-dark .breadcrumb li + li::before { + color: #8c9b9d; + content: "\0002f"; } + html.theme--documenter-dark .breadcrumb ul, + html.theme--documenter-dark .breadcrumb ol { + align-items: flex-start; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + html.theme--documenter-dark .breadcrumb .icon:first-child { + margin-right: 0.5em; } + html.theme--documenter-dark .breadcrumb .icon:last-child { + margin-left: 0.5em; } + html.theme--documenter-dark .breadcrumb.is-centered ol, + html.theme--documenter-dark .breadcrumb.is-centered ul { + justify-content: center; } + html.theme--documenter-dark .breadcrumb.is-right ol, + html.theme--documenter-dark .breadcrumb.is-right ul { + justify-content: flex-end; } + html.theme--documenter-dark .breadcrumb.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.breadcrumb { + font-size: 0.85em; } + html.theme--documenter-dark .breadcrumb.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .breadcrumb.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .breadcrumb.has-arrow-separator li + li::before { + content: "\02192"; } + html.theme--documenter-dark .breadcrumb.has-bullet-separator li + li::before { + content: "\02022"; } + html.theme--documenter-dark .breadcrumb.has-dot-separator li + li::before { + content: "\000b7"; } + html.theme--documenter-dark .breadcrumb.has-succeeds-separator li + li::before { + content: "\0227B"; } + html.theme--documenter-dark .card { + background-color: white; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + color: #fff; + max-width: 100%; + position: relative; } + html.theme--documenter-dark .card-header { + background-color: transparent; + align-items: stretch; + box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1); + display: flex; } + html.theme--documenter-dark .card-header-title { + align-items: center; + color: #f2f2f2; + display: flex; + flex-grow: 1; + font-weight: 700; + padding: 0.75rem; } + html.theme--documenter-dark .card-header-title.is-centered { + justify-content: center; } + html.theme--documenter-dark .card-header-icon { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + padding: 0.75rem; } + html.theme--documenter-dark .card-image { + display: block; + position: relative; } + html.theme--documenter-dark .card-content { + background-color: transparent; + padding: 1.5rem; } + html.theme--documenter-dark .card-footer { + background-color: transparent; + border-top: 1px solid #5e6d6f; + align-items: stretch; + display: flex; } + html.theme--documenter-dark .card-footer-item { + align-items: center; + display: flex; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + justify-content: center; + padding: 0.75rem; } + html.theme--documenter-dark .card-footer-item:not(:last-child) { + border-right: 1px solid #5e6d6f; } + html.theme--documenter-dark .card .media:not(:last-child) { + margin-bottom: 1.5rem; } + html.theme--documenter-dark .dropdown { + display: inline-flex; + position: relative; + vertical-align: top; } + html.theme--documenter-dark .dropdown.is-active .dropdown-menu, html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu { + display: block; } + html.theme--documenter-dark .dropdown.is-right .dropdown-menu { + left: auto; + right: 0; } + html.theme--documenter-dark .dropdown.is-up .dropdown-menu { + bottom: 100%; + padding-bottom: 4px; + padding-top: initial; + top: auto; } + html.theme--documenter-dark .dropdown-menu { + display: none; + left: 0; + min-width: 12rem; + padding-top: 4px; + position: absolute; + top: 100%; + z-index: 20; } + html.theme--documenter-dark .dropdown-content { + background-color: #282f2f; + border-radius: 0.4em; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + padding-bottom: 0.5rem; + padding-top: 0.5rem; } + html.theme--documenter-dark .dropdown-item { + color: #fff; + display: block; + font-size: 0.875rem; + line-height: 1.5; + padding: 0.375rem 1rem; + position: relative; } + html.theme--documenter-dark a.dropdown-item, + html.theme--documenter-dark button.dropdown-item { + padding-right: 3rem; + text-align: left; + white-space: nowrap; + width: 100%; } + html.theme--documenter-dark a.dropdown-item:hover, + html.theme--documenter-dark button.dropdown-item:hover { + background-color: #282f2f; + color: #0a0a0a; } + html.theme--documenter-dark a.dropdown-item.is-active, + html.theme--documenter-dark button.dropdown-item.is-active { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .dropdown-divider { + background-color: #5e6d6f; + border: none; + display: block; + height: 1px; + margin: 0.5rem 0; } + html.theme--documenter-dark .level { + align-items: center; + justify-content: space-between; } + html.theme--documenter-dark .level code { + border-radius: 0.4em; } + html.theme--documenter-dark .level img { + display: inline-block; + vertical-align: top; } + html.theme--documenter-dark .level.is-mobile { + display: flex; } + html.theme--documenter-dark .level.is-mobile .level-left, + html.theme--documenter-dark .level.is-mobile .level-right { + display: flex; } + html.theme--documenter-dark .level.is-mobile .level-left + .level-right { + margin-top: 0; } + html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child) { + margin-bottom: 0; + margin-right: 0.75rem; } + html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow) { + flex-grow: 1; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .level { + display: flex; } + html.theme--documenter-dark .level > .level-item:not(.is-narrow) { + flex-grow: 1; } } + html.theme--documenter-dark .level-item { + align-items: center; + display: flex; + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; } + html.theme--documenter-dark .level-item .title, + html.theme--documenter-dark .level-item .subtitle { + margin-bottom: 0; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .level-item:not(:last-child) { + margin-bottom: 0.75rem; } } + html.theme--documenter-dark .level-left, + html.theme--documenter-dark .level-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; } + html.theme--documenter-dark .level-left .level-item.is-flexible, + html.theme--documenter-dark .level-right .level-item.is-flexible { + flex-grow: 1; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .level-left .level-item:not(:last-child), + html.theme--documenter-dark .level-right .level-item:not(:last-child) { + margin-right: 0.75rem; } } + html.theme--documenter-dark .level-left { + align-items: center; + justify-content: flex-start; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .level-left + .level-right { + margin-top: 1.5rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .level-left { + display: flex; } } + html.theme--documenter-dark .level-right { + align-items: center; + justify-content: flex-end; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .level-right { + display: flex; } } + html.theme--documenter-dark .list { + background-color: white; + border-radius: 0.4em; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .list-item { + display: block; + padding: 0.5em 1em; } + html.theme--documenter-dark .list-item:not(a) { + color: #fff; } + html.theme--documenter-dark .list-item:first-child { + border-top-left-radius: 0.4em; + border-top-right-radius: 0.4em; } + html.theme--documenter-dark .list-item:last-child { + border-bottom-left-radius: 0.4em; + border-bottom-right-radius: 0.4em; } + html.theme--documenter-dark .list-item:not(:last-child) { + border-bottom: 1px solid #5e6d6f; } + html.theme--documenter-dark .list-item.is-active { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark a.list-item { + background-color: #282f2f; + cursor: pointer; } + html.theme--documenter-dark .media { + align-items: flex-start; + display: flex; + text-align: left; } + html.theme--documenter-dark .media .content:not(:last-child) { + margin-bottom: 0.75rem; } + html.theme--documenter-dark .media .media { + border-top: 1px solid rgba(94, 109, 111, 0.5); + display: flex; + padding-top: 0.75rem; } + html.theme--documenter-dark .media .media .content:not(:last-child), + html.theme--documenter-dark .media .media .control:not(:last-child) { + margin-bottom: 0.5rem; } + html.theme--documenter-dark .media .media .media { + padding-top: 0.5rem; } + html.theme--documenter-dark .media .media .media + .media { + margin-top: 0.5rem; } + html.theme--documenter-dark .media + .media { + border-top: 1px solid rgba(94, 109, 111, 0.5); + margin-top: 1rem; + padding-top: 1rem; } + html.theme--documenter-dark .media.is-large + .media { + margin-top: 1.5rem; + padding-top: 1.5rem; } + html.theme--documenter-dark .media-left, + html.theme--documenter-dark .media-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; } + html.theme--documenter-dark .media-left { + margin-right: 1rem; } + html.theme--documenter-dark .media-right { + margin-left: 1rem; } + html.theme--documenter-dark .media-content { + flex-basis: auto; + flex-grow: 1; + flex-shrink: 1; + text-align: left; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .media-content { + overflow-x: auto; } } + html.theme--documenter-dark .menu { + font-size: 15px; } + html.theme--documenter-dark .menu.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.menu { + font-size: 0.85em; } + html.theme--documenter-dark .menu.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .menu.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .menu-list { + line-height: 1.25; } + html.theme--documenter-dark .menu-list a { + border-radius: 3px; + color: #fff; + display: block; + padding: 0.5em 0.75em; } + html.theme--documenter-dark .menu-list a:hover { + background-color: #282f2f; + color: #f2f2f2; } + html.theme--documenter-dark .menu-list a.is-active { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .menu-list li ul { + border-left: 1px solid #5e6d6f; + margin: 0.75em; + padding-left: 0.75em; } + html.theme--documenter-dark .menu-label { + color: white; + font-size: 0.75em; + letter-spacing: 0.1em; + text-transform: uppercase; } + html.theme--documenter-dark .menu-label:not(:first-child) { + margin-top: 1em; } + html.theme--documenter-dark .menu-label:not(:last-child) { + margin-bottom: 1em; } + html.theme--documenter-dark .message { + background-color: #282f2f; + border-radius: 0.4em; + font-size: 15px; } + html.theme--documenter-dark .message strong { + color: currentColor; } + html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item) { + color: currentColor; + text-decoration: underline; } + html.theme--documenter-dark .message.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.message { + font-size: 0.85em; } + html.theme--documenter-dark .message.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .message.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .message.is-white { + background-color: white; } + html.theme--documenter-dark .message.is-white .message-header { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .message.is-white .message-body { + border-color: white; + color: #4d4d4d; } + html.theme--documenter-dark .message.is-black { + background-color: #fafafa; } + html.theme--documenter-dark .message.is-black .message-header { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .message.is-black .message-body { + border-color: #0a0a0a; + color: #090909; } + html.theme--documenter-dark .message.is-light { + background-color: #f9fafb; } + html.theme--documenter-dark .message.is-light .message-header { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .message.is-light .message-body { + border-color: #ecf0f1; + color: #505050; } + html.theme--documenter-dark .message.is-dark, html.theme--documenter-dark .content kbd.message { + background-color: #f9fafa; } + html.theme--documenter-dark .message.is-dark .message-header, html.theme--documenter-dark .content kbd.message .message-header { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .message.is-dark .message-body, html.theme--documenter-dark .content kbd.message .message-body { + border-color: #282f2f; + color: #212526; } + html.theme--documenter-dark .message.is-primary, html.theme--documenter-dark .docstring > section > a.message.docs-sourcelink { + background-color: #f8fafc; } + html.theme--documenter-dark .message.is-primary .message-header, html.theme--documenter-dark .docstring > section > a.message.docs-sourcelink .message-header { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .message.is-primary .message-body, html.theme--documenter-dark .docstring > section > a.message.docs-sourcelink .message-body { + border-color: #375a7f; + color: #2b4159; } + html.theme--documenter-dark .message.is-link { + background-color: #f6fefc; } + html.theme--documenter-dark .message.is-link .message-header { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .message.is-link .message-body { + border-color: #1abc9c; + color: #0b2f28; } + html.theme--documenter-dark .message.is-info { + background-color: #f5fbff; } + html.theme--documenter-dark .message.is-info .message-header { + background-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .message.is-info .message-body { + border-color: #024c7d; + color: #033659; } + html.theme--documenter-dark .message.is-success { + background-color: #f5fff9; } + html.theme--documenter-dark .message.is-success .message-header { + background-color: #008438; + color: #fff; } + html.theme--documenter-dark .message.is-success .message-body { + border-color: #008438; + color: #023518; } + html.theme--documenter-dark .message.is-warning { + background-color: #fffcf5; } + html.theme--documenter-dark .message.is-warning .message-header { + background-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .message.is-warning .message-body { + border-color: #ad8100; + color: #3d2e03; } + html.theme--documenter-dark .message.is-danger { + background-color: #fef6f6; } + html.theme--documenter-dark .message.is-danger .message-header { + background-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .message.is-danger .message-body { + border-color: #9e1b0d; + color: #7a170c; } + html.theme--documenter-dark .message-header { + align-items: center; + background-color: #fff; + border-radius: 0.4em 0.4em 0 0; + color: rgba(0, 0, 0, 0.7); + display: flex; + font-weight: 700; + justify-content: space-between; + line-height: 1.25; + padding: 0.75em 1em; + position: relative; } + html.theme--documenter-dark .message-header .delete { + flex-grow: 0; + flex-shrink: 0; + margin-left: 0.75em; } + html.theme--documenter-dark .message-header + .message-body { + border-width: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + html.theme--documenter-dark .message-body { + border-color: #5e6d6f; + border-radius: 0.4em; + border-style: solid; + border-width: 0 0 0 4px; + color: #fff; + padding: 1.25em 1.5em; } + html.theme--documenter-dark .message-body code, + html.theme--documenter-dark .message-body pre { + background-color: white; } + html.theme--documenter-dark .message-body pre code { + background-color: transparent; } + html.theme--documenter-dark .modal { + align-items: center; + display: none; + flex-direction: column; + justify-content: center; + overflow: hidden; + position: fixed; + z-index: 40; } + html.theme--documenter-dark .modal.is-active { + display: flex; } + html.theme--documenter-dark .modal-background { + background-color: rgba(10, 10, 10, 0.86); } + html.theme--documenter-dark .modal-content, + html.theme--documenter-dark .modal-card { + margin: 0 20px; + max-height: calc(100vh - 160px); + overflow: auto; + position: relative; + width: 100%; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .modal-content, + html.theme--documenter-dark .modal-card { + margin: 0 auto; + max-height: calc(100vh - 40px); + width: 640px; } } + html.theme--documenter-dark .modal-close { + background: none; + height: 40px; + position: fixed; + right: 20px; + top: 20px; + width: 40px; } + html.theme--documenter-dark .modal-card { + display: flex; + flex-direction: column; + max-height: calc(100vh - 40px); + overflow: hidden; + -ms-overflow-y: visible; } + html.theme--documenter-dark .modal-card-head, + html.theme--documenter-dark .modal-card-foot { + align-items: center; + background-color: #282f2f; + display: flex; + flex-shrink: 0; + justify-content: flex-start; + padding: 20px; + position: relative; } + html.theme--documenter-dark .modal-card-head { + border-bottom: 1px solid #5e6d6f; + border-top-left-radius: 8px; + border-top-right-radius: 8px; } + html.theme--documenter-dark .modal-card-title { + color: #f2f2f2; + flex-grow: 1; + flex-shrink: 0; + font-size: 1.5rem; + line-height: 1; } + html.theme--documenter-dark .modal-card-foot { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + border-top: 1px solid #5e6d6f; } + html.theme--documenter-dark .modal-card-foot .button:not(:last-child) { + margin-right: 0.5em; } + html.theme--documenter-dark .modal-card-body { + -webkit-overflow-scrolling: touch; + background-color: white; + flex-grow: 1; + flex-shrink: 1; + overflow: auto; + padding: 20px; } + html.theme--documenter-dark .navbar { + background-color: #375a7f; + min-height: 4rem; + position: relative; + z-index: 30; } + html.theme--documenter-dark .navbar.is-white { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link { + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-white .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-white .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after { + border-color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-burger { + color: #0a0a0a; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-white .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-white .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link { + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-white .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-white .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-white .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-white .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-white .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after { + border-color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #f2f2f2; + color: #0a0a0a; } + html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active { + background-color: white; + color: #0a0a0a; } } + html.theme--documenter-dark .navbar.is-black { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link { + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-black .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-black .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active { + background-color: black; + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after { + border-color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-burger { + color: white; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-black .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-black .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link { + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-black .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-black .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-black .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-black .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-black .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active { + background-color: black; + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after { + border-color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link { + background-color: black; + color: white; } + html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active { + background-color: #0a0a0a; + color: white; } } + html.theme--documenter-dark .navbar.is-light { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link { + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-light .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-light .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active { + background-color: #dde4e6; + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after { + border-color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-burger { + color: #282f2f; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-light .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-light .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link { + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-light .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-light .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-light .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-light .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-light .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active { + background-color: #dde4e6; + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after { + border-color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #dde4e6; + color: #282f2f; } + html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active { + background-color: #ecf0f1; + color: #282f2f; } } + html.theme--documenter-dark .navbar.is-dark, html.theme--documenter-dark .content kbd.navbar { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-brand > .navbar-item, html.theme--documenter-dark .content kbd.navbar .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link, + html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link { + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .content kbd.navbar .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-dark .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .content kbd.navbar .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-dark .navbar-brand > a.navbar-item.is-active, html.theme--documenter-dark .content kbd.navbar .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active, + html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active { + background-color: #1d2122; + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after, html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after { + border-color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-burger, html.theme--documenter-dark .content kbd.navbar .navbar-burger { + color: #ecf0f1; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-dark .navbar-start > .navbar-item, html.theme--documenter-dark .content kbd.navbar .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link, + html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-dark .navbar-end > .navbar-item, + html.theme--documenter-dark .content kbd.navbar .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link, + html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link { + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .content kbd.navbar .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-dark .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .content kbd.navbar .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-dark .navbar-start > a.navbar-item.is-active, html.theme--documenter-dark .content kbd.navbar .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus, + html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover, + html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-dark .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .content kbd.navbar .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-dark .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .content kbd.navbar .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-dark .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .content kbd.navbar .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus, + html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover, + html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active, + html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active { + background-color: #1d2122; + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after, html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after, + html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after { + border-color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link, html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link, + html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #1d2122; + color: #ecf0f1; } + html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active, html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active { + background-color: #282f2f; + color: #ecf0f1; } } + html.theme--documenter-dark .navbar.is-primary, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-brand > .navbar-item, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-primary .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-primary .navbar-brand > a.navbar-item.is-active, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active { + background-color: #2f4d6d; + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-burger, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-primary .navbar-start > .navbar-item, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-primary .navbar-end > .navbar-item, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-primary .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-primary .navbar-start > a.navbar-item.is-active, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-primary .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-primary .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-primary .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active { + background-color: #2f4d6d; + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link, + html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #2f4d6d; + color: #fff; } + html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active { + background-color: #375a7f; + color: #fff; } } + html.theme--documenter-dark .navbar.is-link { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-link .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-link .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active { + background-color: #17a689; + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-link .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-link .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-link .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-link .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-link .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-link .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-link .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active { + background-color: #17a689; + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #17a689; + color: #fff; } + html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active { + background-color: #1abc9c; + color: #fff; } } + html.theme--documenter-dark .navbar.is-info { + background-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-info .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-info .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active { + background-color: #023d64; + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-info .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-info .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-info .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-info .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-info .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-info .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-info .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active { + background-color: #023d64; + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #023d64; + color: #fff; } + html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active { + background-color: #024c7d; + color: #fff; } } + html.theme--documenter-dark .navbar.is-success { + background-color: #008438; + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-success .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-success .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active { + background-color: #006b2d; + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-success .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-success .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-success .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-success .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-success .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-success .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-success .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active { + background-color: #006b2d; + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #006b2d; + color: #fff; } + html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active { + background-color: #008438; + color: #fff; } } + html.theme--documenter-dark .navbar.is-warning { + background-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-warning .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-warning .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active { + background-color: #946e00; + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-warning .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-warning .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-warning .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-warning .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-warning .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-warning .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-warning .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active { + background-color: #946e00; + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #946e00; + color: #fff; } + html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active { + background-color: #ad8100; + color: #fff; } } + html.theme--documenter-dark .navbar.is-danger { + background-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-brand > .navbar-item, + html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-brand > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-danger .navbar-brand > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-danger .navbar-brand > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus, + html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover, + html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active { + background-color: #86170b; + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar.is-danger .navbar-start > .navbar-item, + html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link, + html.theme--documenter-dark .navbar.is-danger .navbar-end > .navbar-item, + html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link { + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-start > a.navbar-item:focus, html.theme--documenter-dark .navbar.is-danger .navbar-start > a.navbar-item:hover, html.theme--documenter-dark .navbar.is-danger .navbar-start > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus, + html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover, + html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active, + html.theme--documenter-dark .navbar.is-danger .navbar-end > a.navbar-item:focus, + html.theme--documenter-dark .navbar.is-danger .navbar-end > a.navbar-item:hover, + html.theme--documenter-dark .navbar.is-danger .navbar-end > a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus, + html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover, + html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active { + background-color: #86170b; + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after, + html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after { + border-color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link, + html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link, + html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #86170b; + color: #fff; } + html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active { + background-color: #9e1b0d; + color: #fff; } } + html.theme--documenter-dark .navbar > .container { + align-items: stretch; + display: flex; + min-height: 4rem; + width: 100%; } + html.theme--documenter-dark .navbar.has-shadow { + box-shadow: 0 2px 0 0 #282f2f; } + html.theme--documenter-dark .navbar.is-fixed-bottom, html.theme--documenter-dark .navbar.is-fixed-top { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + html.theme--documenter-dark .navbar.is-fixed-bottom { + bottom: 0; } + html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow { + box-shadow: 0 -2px 0 0 #282f2f; } + html.theme--documenter-dark .navbar.is-fixed-top { + top: 0; } + html.theme--documenter-dark html.has-navbar-fixed-top, + html.theme--documenter-dark body.has-navbar-fixed-top { + padding-top: 4rem; } + html.theme--documenter-dark html.has-navbar-fixed-bottom, + html.theme--documenter-dark body.has-navbar-fixed-bottom { + padding-bottom: 4rem; } + html.theme--documenter-dark .navbar-brand, + html.theme--documenter-dark .navbar-tabs { + align-items: stretch; + display: flex; + flex-shrink: 0; + min-height: 4rem; } + html.theme--documenter-dark .navbar-brand a.navbar-item:focus, html.theme--documenter-dark .navbar-brand a.navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .navbar-tabs { + -webkit-overflow-scrolling: touch; + max-width: 100vw; + overflow-x: auto; + overflow-y: hidden; } + html.theme--documenter-dark .navbar-burger { + color: #fff; + cursor: pointer; + display: block; + height: 4rem; + position: relative; + width: 4rem; + margin-left: auto; } + html.theme--documenter-dark .navbar-burger span { + background-color: currentColor; + display: block; + height: 1px; + left: calc(50% - 8px); + position: absolute; + transform-origin: center; + transition-duration: 86ms; + transition-property: background-color, opacity, transform; + transition-timing-function: ease-out; + width: 16px; } + html.theme--documenter-dark .navbar-burger span:nth-child(1) { + top: calc(50% - 6px); } + html.theme--documenter-dark .navbar-burger span:nth-child(2) { + top: calc(50% - 1px); } + html.theme--documenter-dark .navbar-burger span:nth-child(3) { + top: calc(50% + 4px); } + html.theme--documenter-dark .navbar-burger:hover { + background-color: rgba(0, 0, 0, 0.05); } + html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1) { + transform: translateY(5px) rotate(45deg); } + html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2) { + opacity: 0; } + html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3) { + transform: translateY(-5px) rotate(-45deg); } + html.theme--documenter-dark .navbar-menu { + display: none; } + html.theme--documenter-dark .navbar-item, + html.theme--documenter-dark .navbar-link { + color: #fff; + display: block; + line-height: 1.5; + padding: 0.5rem 0.75rem; + position: relative; } + html.theme--documenter-dark .navbar-item .icon:only-child, + html.theme--documenter-dark .navbar-link .icon:only-child { + margin-left: -0.25rem; + margin-right: -0.25rem; } + html.theme--documenter-dark a.navbar-item, + html.theme--documenter-dark .navbar-link { + cursor: pointer; } + html.theme--documenter-dark a.navbar-item:focus, html.theme--documenter-dark a.navbar-item:focus-within, html.theme--documenter-dark a.navbar-item:hover, html.theme--documenter-dark a.navbar-item.is-active, + html.theme--documenter-dark .navbar-link:focus, + html.theme--documenter-dark .navbar-link:focus-within, + html.theme--documenter-dark .navbar-link:hover, + html.theme--documenter-dark .navbar-link.is-active { + background-color: transparent; + color: #1abc9c; } + html.theme--documenter-dark .navbar-item { + display: block; + flex-grow: 0; + flex-shrink: 0; } + html.theme--documenter-dark .navbar-item img { + max-height: 1.75rem; } + html.theme--documenter-dark .navbar-item.has-dropdown { + padding: 0; } + html.theme--documenter-dark .navbar-item.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .navbar-item.is-tab { + border-bottom: 1px solid transparent; + min-height: 4rem; + padding-bottom: calc(0.5rem - 1px); } + html.theme--documenter-dark .navbar-item.is-tab:focus, html.theme--documenter-dark .navbar-item.is-tab:hover { + background-color: transparent; + border-bottom-color: #1abc9c; } + html.theme--documenter-dark .navbar-item.is-tab.is-active { + background-color: transparent; + border-bottom-color: #1abc9c; + border-bottom-style: solid; + border-bottom-width: 3px; + color: #1abc9c; + padding-bottom: calc(0.5rem - 3px); } + html.theme--documenter-dark .navbar-content { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .navbar-link:not(.is-arrowless) { + padding-right: 2.5em; } + html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after { + border-color: #fff; + margin-top: -0.375em; + right: 1.125em; } + html.theme--documenter-dark .navbar-dropdown { + font-size: 0.875rem; + padding-bottom: 0.5rem; + padding-top: 0.5rem; } + html.theme--documenter-dark .navbar-dropdown .navbar-item { + padding-left: 1.5rem; + padding-right: 1.5rem; } + html.theme--documenter-dark .navbar-divider { + background-color: rgba(0, 0, 0, 0.2); + border: none; + display: none; + height: 2px; + margin: 0.5rem 0; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .navbar > .container { + display: block; } + html.theme--documenter-dark .navbar-brand .navbar-item, + html.theme--documenter-dark .navbar-tabs .navbar-item { + align-items: center; + display: flex; } + html.theme--documenter-dark .navbar-link::after { + display: none; } + html.theme--documenter-dark .navbar-menu { + background-color: #375a7f; + box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1); + padding: 0.5rem 0; } + html.theme--documenter-dark .navbar-menu.is-active { + display: block; } + html.theme--documenter-dark .navbar.is-fixed-bottom-touch, html.theme--documenter-dark .navbar.is-fixed-top-touch { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + html.theme--documenter-dark .navbar.is-fixed-bottom-touch { + bottom: 0; } + html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow { + box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .navbar.is-fixed-top-touch { + top: 0; } + html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu, html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu { + -webkit-overflow-scrolling: touch; + max-height: calc(100vh - 4rem); + overflow: auto; } + html.theme--documenter-dark html.has-navbar-fixed-top-touch, + html.theme--documenter-dark body.has-navbar-fixed-top-touch { + padding-top: 4rem; } + html.theme--documenter-dark html.has-navbar-fixed-bottom-touch, + html.theme--documenter-dark body.has-navbar-fixed-bottom-touch { + padding-bottom: 4rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .navbar, + html.theme--documenter-dark .navbar-menu, + html.theme--documenter-dark .navbar-start, + html.theme--documenter-dark .navbar-end { + align-items: stretch; + display: flex; } + html.theme--documenter-dark .navbar { + min-height: 4rem; } + html.theme--documenter-dark .navbar.is-spaced { + padding: 1rem 2rem; } + html.theme--documenter-dark .navbar.is-spaced .navbar-start, + html.theme--documenter-dark .navbar.is-spaced .navbar-end { + align-items: center; } + html.theme--documenter-dark .navbar.is-spaced a.navbar-item, + html.theme--documenter-dark .navbar.is-spaced .navbar-link { + border-radius: 0.4em; } + html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus, html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover, html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active, + html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus, + html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover, + html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active { + background-color: transparent !important; } + html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link, html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link, html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link, html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link { + background-color: transparent !important; } + html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus, html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover { + background-color: transparent; + color: #dbdee0; } + html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active { + background-color: transparent; + color: #1abc9c; } + html.theme--documenter-dark .navbar-burger { + display: none; } + html.theme--documenter-dark .navbar-item, + html.theme--documenter-dark .navbar-link { + align-items: center; + display: flex; } + html.theme--documenter-dark .navbar-item { + display: flex; } + html.theme--documenter-dark .navbar-item.has-dropdown { + align-items: stretch; } + html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after { + transform: rotate(135deg) translate(0.25em, -0.25em); } + html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown { + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px 8px 0 0; + border-top: none; + bottom: 100%; + box-shadow: 0 -8px 8px rgba(10, 10, 10, 0.1); + top: auto; } + html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown { + display: block; } + .navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed, .navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed, .navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed, .navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown, html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed { + opacity: 1; + pointer-events: auto; + transform: translateY(0); } + html.theme--documenter-dark .navbar-menu { + flex-grow: 1; + flex-shrink: 0; } + html.theme--documenter-dark .navbar-start { + justify-content: flex-start; + margin-right: auto; } + html.theme--documenter-dark .navbar-end { + justify-content: flex-end; + margin-left: auto; } + html.theme--documenter-dark .navbar-dropdown { + background-color: #375a7f; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + border-top: 1px solid rgba(0, 0, 0, 0.2); + box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1); + display: none; + font-size: 0.875rem; + left: 0; + min-width: 100%; + position: absolute; + top: 100%; + z-index: 20; } + html.theme--documenter-dark .navbar-dropdown .navbar-item { + padding: 0.375rem 1rem; + white-space: nowrap; } + html.theme--documenter-dark .navbar-dropdown a.navbar-item { + padding-right: 3rem; } + html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus, html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover { + background-color: transparent; + color: #dbdee0; } + html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active { + background-color: transparent; + color: #1abc9c; } + .navbar.is-spaced html.theme--documenter-dark .navbar-dropdown, html.theme--documenter-dark .navbar-dropdown.is-boxed { + border-radius: 8px; + border-top: none; + box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + display: block; + opacity: 0; + pointer-events: none; + top: calc(100% + (-4px)); + transform: translateY(-5px); + transition-duration: 86ms; + transition-property: opacity, transform; } + html.theme--documenter-dark .navbar-dropdown.is-right { + left: auto; + right: 0; } + html.theme--documenter-dark .navbar-divider { + display: block; } + html.theme--documenter-dark .navbar > .container .navbar-brand, + html.theme--documenter-dark .container > .navbar .navbar-brand { + margin-left: -.75rem; } + html.theme--documenter-dark .navbar > .container .navbar-menu, + html.theme--documenter-dark .container > .navbar .navbar-menu { + margin-right: -.75rem; } + html.theme--documenter-dark .navbar.is-fixed-bottom-desktop, html.theme--documenter-dark .navbar.is-fixed-top-desktop { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + html.theme--documenter-dark .navbar.is-fixed-bottom-desktop { + bottom: 0; } + html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow { + box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .navbar.is-fixed-top-desktop { + top: 0; } + html.theme--documenter-dark html.has-navbar-fixed-top-desktop, + html.theme--documenter-dark body.has-navbar-fixed-top-desktop { + padding-top: 4rem; } + html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop, + html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop { + padding-bottom: 4rem; } + html.theme--documenter-dark html.has-spaced-navbar-fixed-top, + html.theme--documenter-dark body.has-spaced-navbar-fixed-top { + padding-top: 6rem; } + html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom, + html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom { + padding-bottom: 6rem; } + html.theme--documenter-dark a.navbar-item.is-active, + html.theme--documenter-dark .navbar-link.is-active { + color: #1abc9c; } + html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover), + html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover) { + background-color: transparent; } + html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link, html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link, html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link { + background-color: transparent; } } + html.theme--documenter-dark .hero.is-fullheight-with-navbar { + min-height: calc(100vh - 4rem); } + html.theme--documenter-dark .pagination { + font-size: 15px; + margin: -0.25rem; } + html.theme--documenter-dark .pagination.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.pagination { + font-size: 0.85em; } + html.theme--documenter-dark .pagination.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .pagination.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .pagination.is-rounded .pagination-previous, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.pagination .pagination-previous, + html.theme--documenter-dark .pagination.is-rounded .pagination-next, + html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.pagination .pagination-next { + padding-left: 1em; + padding-right: 1em; + border-radius: 290486px; } + html.theme--documenter-dark .pagination.is-rounded .pagination-link, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.pagination .pagination-link { + border-radius: 290486px; } + html.theme--documenter-dark .pagination, + html.theme--documenter-dark .pagination-list { + align-items: center; + display: flex; + justify-content: center; + text-align: center; } + html.theme--documenter-dark .pagination-previous, + html.theme--documenter-dark .pagination-next, + html.theme--documenter-dark .pagination-link, + html.theme--documenter-dark .pagination-ellipsis { + font-size: 1em; + justify-content: center; + margin: 0.25rem; + padding-left: 0.5em; + padding-right: 0.5em; + text-align: center; } + html.theme--documenter-dark .pagination-previous, + html.theme--documenter-dark .pagination-next, + html.theme--documenter-dark .pagination-link { + border-color: #5e6d6f; + color: #1abc9c; + min-width: 2.25em; } + html.theme--documenter-dark .pagination-previous:hover, + html.theme--documenter-dark .pagination-next:hover, + html.theme--documenter-dark .pagination-link:hover { + border-color: #8c9b9d; + color: #1dd2af; } + html.theme--documenter-dark .pagination-previous:focus, + html.theme--documenter-dark .pagination-next:focus, + html.theme--documenter-dark .pagination-link:focus { + border-color: #8c9b9d; } + html.theme--documenter-dark .pagination-previous:active, + html.theme--documenter-dark .pagination-next:active, + html.theme--documenter-dark .pagination-link:active { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2); } + html.theme--documenter-dark .pagination-previous[disabled], + html.theme--documenter-dark .pagination-next[disabled], + html.theme--documenter-dark .pagination-link[disabled] { + background-color: #dbdee0; + border-color: #dbdee0; + box-shadow: none; + color: #5e6d6f; + opacity: 0.5; } + html.theme--documenter-dark .pagination-previous, + html.theme--documenter-dark .pagination-next { + padding-left: 0.75em; + padding-right: 0.75em; + white-space: nowrap; } + html.theme--documenter-dark .pagination-link.is-current { + background-color: #1abc9c; + border-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .pagination-ellipsis { + color: #8c9b9d; + pointer-events: none; } + html.theme--documenter-dark .pagination-list { + flex-wrap: wrap; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .pagination { + flex-wrap: wrap; } + html.theme--documenter-dark .pagination-previous, + html.theme--documenter-dark .pagination-next { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .pagination-list li { + flex-grow: 1; + flex-shrink: 1; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .pagination-list { + flex-grow: 1; + flex-shrink: 1; + justify-content: flex-start; + order: 1; } + html.theme--documenter-dark .pagination-previous { + order: 2; } + html.theme--documenter-dark .pagination-next { + order: 3; } + html.theme--documenter-dark .pagination { + justify-content: space-between; } + html.theme--documenter-dark .pagination.is-centered .pagination-previous { + order: 1; } + html.theme--documenter-dark .pagination.is-centered .pagination-list { + justify-content: center; + order: 2; } + html.theme--documenter-dark .pagination.is-centered .pagination-next { + order: 3; } + html.theme--documenter-dark .pagination.is-right .pagination-previous { + order: 1; } + html.theme--documenter-dark .pagination.is-right .pagination-next { + order: 2; } + html.theme--documenter-dark .pagination.is-right .pagination-list { + justify-content: flex-end; + order: 3; } } + html.theme--documenter-dark .panel { + font-size: 15px; } + html.theme--documenter-dark .panel:not(:last-child) { + margin-bottom: 1.5rem; } + html.theme--documenter-dark .panel-heading, + html.theme--documenter-dark .panel-tabs, + html.theme--documenter-dark .panel-block { + border-bottom: 1px solid #5e6d6f; + border-left: 1px solid #5e6d6f; + border-right: 1px solid #5e6d6f; } + html.theme--documenter-dark .panel-heading:first-child, + html.theme--documenter-dark .panel-tabs:first-child, + html.theme--documenter-dark .panel-block:first-child { + border-top: 1px solid #5e6d6f; } + html.theme--documenter-dark .panel-heading { + background-color: #282f2f; + border-radius: 0.4em 0.4em 0 0; + color: #f2f2f2; + font-size: 1.25em; + font-weight: 300; + line-height: 1.25; + padding: 0.5em 0.75em; } + html.theme--documenter-dark .panel-tabs { + align-items: flex-end; + display: flex; + font-size: 0.875em; + justify-content: center; } + html.theme--documenter-dark .panel-tabs a { + border-bottom: 1px solid #5e6d6f; + margin-bottom: -1px; + padding: 0.5em; } + html.theme--documenter-dark .panel-tabs a.is-active { + border-bottom-color: #343c3d; + color: #17a689; } + html.theme--documenter-dark .panel-list a { + color: #fff; } + html.theme--documenter-dark .panel-list a:hover { + color: #1abc9c; } + html.theme--documenter-dark .panel-block { + align-items: center; + color: #f2f2f2; + display: flex; + justify-content: flex-start; + padding: 0.5em 0.75em; } + html.theme--documenter-dark .panel-block input[type="checkbox"] { + margin-right: 0.75em; } + html.theme--documenter-dark .panel-block > .control { + flex-grow: 1; + flex-shrink: 1; + width: 100%; } + html.theme--documenter-dark .panel-block.is-wrapped { + flex-wrap: wrap; } + html.theme--documenter-dark .panel-block.is-active { + border-left-color: #1abc9c; + color: #17a689; } + html.theme--documenter-dark .panel-block.is-active .panel-icon { + color: #1abc9c; } + html.theme--documenter-dark a.panel-block, + html.theme--documenter-dark label.panel-block { + cursor: pointer; } + html.theme--documenter-dark a.panel-block:hover, + html.theme--documenter-dark label.panel-block:hover { + background-color: #282f2f; } + html.theme--documenter-dark .panel-icon { + display: inline-block; + font-size: 14px; + height: 1em; + line-height: 1em; + text-align: center; + vertical-align: top; + width: 1em; + color: white; + margin-right: 0.75em; } + html.theme--documenter-dark .panel-icon .fa { + font-size: inherit; + line-height: inherit; } + html.theme--documenter-dark .tabs { + -webkit-overflow-scrolling: touch; + align-items: stretch; + display: flex; + font-size: 15px; + justify-content: space-between; + overflow: hidden; + overflow-x: auto; + white-space: nowrap; } + html.theme--documenter-dark .tabs a { + align-items: center; + border-bottom-color: #5e6d6f; + border-bottom-style: solid; + border-bottom-width: 1px; + color: #fff; + display: flex; + justify-content: center; + margin-bottom: -1px; + padding: 0.5em 1em; + vertical-align: top; } + html.theme--documenter-dark .tabs a:hover { + border-bottom-color: #f2f2f2; + color: #f2f2f2; } + html.theme--documenter-dark .tabs li { + display: block; } + html.theme--documenter-dark .tabs li.is-active a { + border-bottom-color: #1abc9c; + color: #1abc9c; } + html.theme--documenter-dark .tabs ul { + align-items: center; + border-bottom-color: #5e6d6f; + border-bottom-style: solid; + border-bottom-width: 1px; + display: flex; + flex-grow: 1; + flex-shrink: 0; + justify-content: flex-start; } + html.theme--documenter-dark .tabs ul.is-left { + padding-right: 0.75em; } + html.theme--documenter-dark .tabs ul.is-center { + flex: none; + justify-content: center; + padding-left: 0.75em; + padding-right: 0.75em; } + html.theme--documenter-dark .tabs ul.is-right { + justify-content: flex-end; + padding-left: 0.75em; } + html.theme--documenter-dark .tabs .icon:first-child { + margin-right: 0.5em; } + html.theme--documenter-dark .tabs .icon:last-child { + margin-left: 0.5em; } + html.theme--documenter-dark .tabs.is-centered ul { + justify-content: center; } + html.theme--documenter-dark .tabs.is-right ul { + justify-content: flex-end; } + html.theme--documenter-dark .tabs.is-boxed a { + border: 1px solid transparent; + border-radius: 0.4em 0.4em 0 0; } + html.theme--documenter-dark .tabs.is-boxed a:hover { + background-color: #282f2f; + border-bottom-color: #5e6d6f; } + html.theme--documenter-dark .tabs.is-boxed li.is-active a { + background-color: white; + border-color: #5e6d6f; + border-bottom-color: transparent !important; } + html.theme--documenter-dark .tabs.is-fullwidth li { + flex-grow: 1; + flex-shrink: 0; } + html.theme--documenter-dark .tabs.is-toggle a { + border-color: #5e6d6f; + border-style: solid; + border-width: 1px; + margin-bottom: 0; + position: relative; } + html.theme--documenter-dark .tabs.is-toggle a:hover { + background-color: #282f2f; + border-color: #8c9b9d; + z-index: 2; } + html.theme--documenter-dark .tabs.is-toggle li + li { + margin-left: -1px; } + html.theme--documenter-dark .tabs.is-toggle li:first-child a { + border-radius: 0.4em 0 0 0.4em; } + html.theme--documenter-dark .tabs.is-toggle li:last-child a { + border-radius: 0 0.4em 0.4em 0; } + html.theme--documenter-dark .tabs.is-toggle li.is-active a { + background-color: #1abc9c; + border-color: #1abc9c; + color: #fff; + z-index: 1; } + html.theme--documenter-dark .tabs.is-toggle ul { + border-bottom: none; } + html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a { + border-bottom-left-radius: 290486px; + border-top-left-radius: 290486px; + padding-left: 1.25em; } + html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a { + border-bottom-right-radius: 290486px; + border-top-right-radius: 290486px; + padding-right: 1.25em; } + html.theme--documenter-dark .tabs.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.tabs { + font-size: 0.85em; } + html.theme--documenter-dark .tabs.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .tabs.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .column { + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + padding: 0.75rem; } + .columns.is-mobile > html.theme--documenter-dark .column.is-narrow { + flex: none; } + .columns.is-mobile > html.theme--documenter-dark .column.is-full { + flex: none; + width: 100%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-three-quarters { + flex: none; + width: 75%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-two-thirds { + flex: none; + width: 66.6666%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-half { + flex: none; + width: 50%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-one-third { + flex: none; + width: 33.3333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-one-quarter { + flex: none; + width: 25%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-one-fifth { + flex: none; + width: 20%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-two-fifths { + flex: none; + width: 40%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-three-fifths { + flex: none; + width: 60%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-four-fifths { + flex: none; + width: 80%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-three-quarters { + margin-left: 75%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-two-thirds { + margin-left: 66.6666%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-half { + margin-left: 50%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-one-third { + margin-left: 33.3333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-one-quarter { + margin-left: 25%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-one-fifth { + margin-left: 20%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-two-fifths { + margin-left: 40%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-three-fifths { + margin-left: 60%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-four-fifths { + margin-left: 80%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-0 { + flex: none; + width: 0%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-0 { + margin-left: 0%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-1 { + flex: none; + width: 8.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-1 { + margin-left: 8.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-2 { + flex: none; + width: 16.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-2 { + margin-left: 16.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-3 { + flex: none; + width: 25%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-3 { + margin-left: 25%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-4 { + flex: none; + width: 33.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-4 { + margin-left: 33.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-5 { + flex: none; + width: 41.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-5 { + margin-left: 41.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-6 { + flex: none; + width: 50%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-6 { + margin-left: 50%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-7 { + flex: none; + width: 58.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-7 { + margin-left: 58.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-8 { + flex: none; + width: 66.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-8 { + margin-left: 66.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-9 { + flex: none; + width: 75%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-9 { + margin-left: 75%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-10 { + flex: none; + width: 83.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-10 { + margin-left: 83.3333333333%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-11 { + flex: none; + width: 91.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-11 { + margin-left: 91.6666666667%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-12 { + flex: none; + width: 100%; } + .columns.is-mobile > html.theme--documenter-dark .column.is-offset-12 { + margin-left: 100%; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .column.is-narrow-mobile { + flex: none; } + html.theme--documenter-dark .column.is-full-mobile { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters-mobile { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds-mobile { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half-mobile { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third-mobile { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter-mobile { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth-mobile { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths-mobile { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths-mobile { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths-mobile { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters-mobile { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds-mobile { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half-mobile { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third-mobile { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter-mobile { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth-mobile { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths-mobile { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths-mobile { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths-mobile { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0-mobile { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0-mobile { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1-mobile { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1-mobile { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2-mobile { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2-mobile { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3-mobile { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3-mobile { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4-mobile { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4-mobile { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5-mobile { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5-mobile { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6-mobile { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6-mobile { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7-mobile { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7-mobile { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8-mobile { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8-mobile { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9-mobile { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9-mobile { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10-mobile { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10-mobile { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11-mobile { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11-mobile { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12-mobile { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12-mobile { + margin-left: 100%; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .column.is-narrow, html.theme--documenter-dark .column.is-narrow-tablet { + flex: none; } + html.theme--documenter-dark .column.is-full, html.theme--documenter-dark .column.is-full-tablet { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters, html.theme--documenter-dark .column.is-three-quarters-tablet { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds, html.theme--documenter-dark .column.is-two-thirds-tablet { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half, html.theme--documenter-dark .column.is-half-tablet { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third, html.theme--documenter-dark .column.is-one-third-tablet { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter, html.theme--documenter-dark .column.is-one-quarter-tablet { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth, html.theme--documenter-dark .column.is-one-fifth-tablet { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths, html.theme--documenter-dark .column.is-two-fifths-tablet { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths, html.theme--documenter-dark .column.is-three-fifths-tablet { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths, html.theme--documenter-dark .column.is-four-fifths-tablet { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters, html.theme--documenter-dark .column.is-offset-three-quarters-tablet { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds, html.theme--documenter-dark .column.is-offset-two-thirds-tablet { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half, html.theme--documenter-dark .column.is-offset-half-tablet { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third, html.theme--documenter-dark .column.is-offset-one-third-tablet { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter, html.theme--documenter-dark .column.is-offset-one-quarter-tablet { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth, html.theme--documenter-dark .column.is-offset-one-fifth-tablet { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths, html.theme--documenter-dark .column.is-offset-two-fifths-tablet { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths, html.theme--documenter-dark .column.is-offset-three-fifths-tablet { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths, html.theme--documenter-dark .column.is-offset-four-fifths-tablet { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0, html.theme--documenter-dark .column.is-0-tablet { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0, html.theme--documenter-dark .column.is-offset-0-tablet { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1, html.theme--documenter-dark .column.is-1-tablet { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1, html.theme--documenter-dark .column.is-offset-1-tablet { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2, html.theme--documenter-dark .column.is-2-tablet { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2, html.theme--documenter-dark .column.is-offset-2-tablet { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3, html.theme--documenter-dark .column.is-3-tablet { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3, html.theme--documenter-dark .column.is-offset-3-tablet { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4, html.theme--documenter-dark .column.is-4-tablet { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4, html.theme--documenter-dark .column.is-offset-4-tablet { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5, html.theme--documenter-dark .column.is-5-tablet { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5, html.theme--documenter-dark .column.is-offset-5-tablet { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6, html.theme--documenter-dark .column.is-6-tablet { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6, html.theme--documenter-dark .column.is-offset-6-tablet { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7, html.theme--documenter-dark .column.is-7-tablet { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7, html.theme--documenter-dark .column.is-offset-7-tablet { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8, html.theme--documenter-dark .column.is-8-tablet { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8, html.theme--documenter-dark .column.is-offset-8-tablet { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9, html.theme--documenter-dark .column.is-9-tablet { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9, html.theme--documenter-dark .column.is-offset-9-tablet { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10, html.theme--documenter-dark .column.is-10-tablet { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10, html.theme--documenter-dark .column.is-offset-10-tablet { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11, html.theme--documenter-dark .column.is-11-tablet { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11, html.theme--documenter-dark .column.is-offset-11-tablet { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12, html.theme--documenter-dark .column.is-12-tablet { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12, html.theme--documenter-dark .column.is-offset-12-tablet { + margin-left: 100%; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .column.is-narrow-touch { + flex: none; } + html.theme--documenter-dark .column.is-full-touch { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters-touch { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds-touch { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half-touch { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third-touch { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter-touch { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth-touch { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths-touch { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths-touch { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths-touch { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters-touch { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds-touch { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half-touch { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third-touch { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter-touch { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth-touch { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths-touch { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths-touch { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths-touch { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0-touch { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0-touch { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1-touch { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1-touch { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2-touch { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2-touch { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3-touch { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3-touch { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4-touch { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4-touch { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5-touch { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5-touch { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6-touch { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6-touch { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7-touch { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7-touch { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8-touch { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8-touch { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9-touch { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9-touch { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10-touch { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10-touch { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11-touch { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11-touch { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12-touch { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12-touch { + margin-left: 100%; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .column.is-narrow-desktop { + flex: none; } + html.theme--documenter-dark .column.is-full-desktop { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters-desktop { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds-desktop { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half-desktop { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third-desktop { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter-desktop { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth-desktop { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths-desktop { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths-desktop { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths-desktop { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters-desktop { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds-desktop { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half-desktop { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third-desktop { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter-desktop { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth-desktop { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths-desktop { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths-desktop { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths-desktop { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0-desktop { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0-desktop { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1-desktop { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1-desktop { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2-desktop { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2-desktop { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3-desktop { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3-desktop { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4-desktop { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4-desktop { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5-desktop { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5-desktop { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6-desktop { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6-desktop { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7-desktop { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7-desktop { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8-desktop { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8-desktop { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9-desktop { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9-desktop { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10-desktop { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10-desktop { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11-desktop { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11-desktop { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12-desktop { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12-desktop { + margin-left: 100%; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .column.is-narrow-widescreen { + flex: none; } + html.theme--documenter-dark .column.is-full-widescreen { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters-widescreen { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds-widescreen { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half-widescreen { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third-widescreen { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter-widescreen { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth-widescreen { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths-widescreen { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths-widescreen { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths-widescreen { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters-widescreen { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds-widescreen { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half-widescreen { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third-widescreen { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter-widescreen { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth-widescreen { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths-widescreen { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths-widescreen { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths-widescreen { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0-widescreen { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0-widescreen { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1-widescreen { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1-widescreen { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2-widescreen { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2-widescreen { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3-widescreen { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3-widescreen { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4-widescreen { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4-widescreen { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5-widescreen { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5-widescreen { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6-widescreen { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6-widescreen { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7-widescreen { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7-widescreen { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8-widescreen { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8-widescreen { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9-widescreen { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9-widescreen { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10-widescreen { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10-widescreen { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11-widescreen { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11-widescreen { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12-widescreen { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12-widescreen { + margin-left: 100%; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .column.is-narrow-fullhd { + flex: none; } + html.theme--documenter-dark .column.is-full-fullhd { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-three-quarters-fullhd { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-two-thirds-fullhd { + flex: none; + width: 66.6666%; } + html.theme--documenter-dark .column.is-half-fullhd { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-one-third-fullhd { + flex: none; + width: 33.3333%; } + html.theme--documenter-dark .column.is-one-quarter-fullhd { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-one-fifth-fullhd { + flex: none; + width: 20%; } + html.theme--documenter-dark .column.is-two-fifths-fullhd { + flex: none; + width: 40%; } + html.theme--documenter-dark .column.is-three-fifths-fullhd { + flex: none; + width: 60%; } + html.theme--documenter-dark .column.is-four-fifths-fullhd { + flex: none; + width: 80%; } + html.theme--documenter-dark .column.is-offset-three-quarters-fullhd { + margin-left: 75%; } + html.theme--documenter-dark .column.is-offset-two-thirds-fullhd { + margin-left: 66.6666%; } + html.theme--documenter-dark .column.is-offset-half-fullhd { + margin-left: 50%; } + html.theme--documenter-dark .column.is-offset-one-third-fullhd { + margin-left: 33.3333%; } + html.theme--documenter-dark .column.is-offset-one-quarter-fullhd { + margin-left: 25%; } + html.theme--documenter-dark .column.is-offset-one-fifth-fullhd { + margin-left: 20%; } + html.theme--documenter-dark .column.is-offset-two-fifths-fullhd { + margin-left: 40%; } + html.theme--documenter-dark .column.is-offset-three-fifths-fullhd { + margin-left: 60%; } + html.theme--documenter-dark .column.is-offset-four-fifths-fullhd { + margin-left: 80%; } + html.theme--documenter-dark .column.is-0-fullhd { + flex: none; + width: 0%; } + html.theme--documenter-dark .column.is-offset-0-fullhd { + margin-left: 0%; } + html.theme--documenter-dark .column.is-1-fullhd { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .column.is-offset-1-fullhd { + margin-left: 8.3333333333%; } + html.theme--documenter-dark .column.is-2-fullhd { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .column.is-offset-2-fullhd { + margin-left: 16.6666666667%; } + html.theme--documenter-dark .column.is-3-fullhd { + flex: none; + width: 25%; } + html.theme--documenter-dark .column.is-offset-3-fullhd { + margin-left: 25%; } + html.theme--documenter-dark .column.is-4-fullhd { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .column.is-offset-4-fullhd { + margin-left: 33.3333333333%; } + html.theme--documenter-dark .column.is-5-fullhd { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .column.is-offset-5-fullhd { + margin-left: 41.6666666667%; } + html.theme--documenter-dark .column.is-6-fullhd { + flex: none; + width: 50%; } + html.theme--documenter-dark .column.is-offset-6-fullhd { + margin-left: 50%; } + html.theme--documenter-dark .column.is-7-fullhd { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .column.is-offset-7-fullhd { + margin-left: 58.3333333333%; } + html.theme--documenter-dark .column.is-8-fullhd { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .column.is-offset-8-fullhd { + margin-left: 66.6666666667%; } + html.theme--documenter-dark .column.is-9-fullhd { + flex: none; + width: 75%; } + html.theme--documenter-dark .column.is-offset-9-fullhd { + margin-left: 75%; } + html.theme--documenter-dark .column.is-10-fullhd { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .column.is-offset-10-fullhd { + margin-left: 83.3333333333%; } + html.theme--documenter-dark .column.is-11-fullhd { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .column.is-offset-11-fullhd { + margin-left: 91.6666666667%; } + html.theme--documenter-dark .column.is-12-fullhd { + flex: none; + width: 100%; } + html.theme--documenter-dark .column.is-offset-12-fullhd { + margin-left: 100%; } } + html.theme--documenter-dark .columns { + margin-left: -0.75rem; + margin-right: -0.75rem; + margin-top: -0.75rem; } + html.theme--documenter-dark .columns:last-child { + margin-bottom: -0.75rem; } + html.theme--documenter-dark .columns:not(:last-child) { + margin-bottom: calc(1.5rem - 0.75rem); } + html.theme--documenter-dark .columns.is-centered { + justify-content: center; } + html.theme--documenter-dark .columns.is-gapless { + margin-left: 0; + margin-right: 0; + margin-top: 0; } + html.theme--documenter-dark .columns.is-gapless > .column { + margin: 0; + padding: 0 !important; } + html.theme--documenter-dark .columns.is-gapless:not(:last-child) { + margin-bottom: 1.5rem; } + html.theme--documenter-dark .columns.is-gapless:last-child { + margin-bottom: 0; } + html.theme--documenter-dark .columns.is-mobile { + display: flex; } + html.theme--documenter-dark .columns.is-multiline { + flex-wrap: wrap; } + html.theme--documenter-dark .columns.is-vcentered { + align-items: center; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns:not(.is-desktop) { + display: flex; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-desktop { + display: flex; } } + html.theme--documenter-dark .columns.is-variable { + --columnGap: 0.75rem; + margin-left: calc(-1 * var(--columnGap)); + margin-right: calc(-1 * var(--columnGap)); } + html.theme--documenter-dark .columns.is-variable .column { + padding-left: var(--columnGap); + padding-right: var(--columnGap); } + html.theme--documenter-dark .columns.is-variable.is-0 { + --columnGap: 0rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-0-mobile { + --columnGap: 0rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-0-tablet { + --columnGap: 0rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-0-tablet-only { + --columnGap: 0rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-0-touch { + --columnGap: 0rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-0-desktop { + --columnGap: 0rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-0-desktop-only { + --columnGap: 0rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-0-widescreen { + --columnGap: 0rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only { + --columnGap: 0rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-0-fullhd { + --columnGap: 0rem; } } + html.theme--documenter-dark .columns.is-variable.is-1 { + --columnGap: 0.25rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-1-mobile { + --columnGap: 0.25rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-1-tablet { + --columnGap: 0.25rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-1-tablet-only { + --columnGap: 0.25rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-1-touch { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-1-desktop { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-1-desktop-only { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-1-widescreen { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-1-fullhd { + --columnGap: 0.25rem; } } + html.theme--documenter-dark .columns.is-variable.is-2 { + --columnGap: 0.5rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-2-mobile { + --columnGap: 0.5rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-2-tablet { + --columnGap: 0.5rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-2-tablet-only { + --columnGap: 0.5rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-2-touch { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-2-desktop { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-2-desktop-only { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-2-widescreen { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-2-fullhd { + --columnGap: 0.5rem; } } + html.theme--documenter-dark .columns.is-variable.is-3 { + --columnGap: 0.75rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-3-mobile { + --columnGap: 0.75rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-3-tablet { + --columnGap: 0.75rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-3-tablet-only { + --columnGap: 0.75rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-3-touch { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-3-desktop { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-3-desktop-only { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-3-widescreen { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-3-fullhd { + --columnGap: 0.75rem; } } + html.theme--documenter-dark .columns.is-variable.is-4 { + --columnGap: 1rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-4-mobile { + --columnGap: 1rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-4-tablet { + --columnGap: 1rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-4-tablet-only { + --columnGap: 1rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-4-touch { + --columnGap: 1rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-4-desktop { + --columnGap: 1rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-4-desktop-only { + --columnGap: 1rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-4-widescreen { + --columnGap: 1rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only { + --columnGap: 1rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-4-fullhd { + --columnGap: 1rem; } } + html.theme--documenter-dark .columns.is-variable.is-5 { + --columnGap: 1.25rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-5-mobile { + --columnGap: 1.25rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-5-tablet { + --columnGap: 1.25rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-5-tablet-only { + --columnGap: 1.25rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-5-touch { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-5-desktop { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-5-desktop-only { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-5-widescreen { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-5-fullhd { + --columnGap: 1.25rem; } } + html.theme--documenter-dark .columns.is-variable.is-6 { + --columnGap: 1.5rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-6-mobile { + --columnGap: 1.5rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-6-tablet { + --columnGap: 1.5rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-6-tablet-only { + --columnGap: 1.5rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-6-touch { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-6-desktop { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-6-desktop-only { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-6-widescreen { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-6-fullhd { + --columnGap: 1.5rem; } } + html.theme--documenter-dark .columns.is-variable.is-7 { + --columnGap: 1.75rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-7-mobile { + --columnGap: 1.75rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-7-tablet { + --columnGap: 1.75rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-7-tablet-only { + --columnGap: 1.75rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-7-touch { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-7-desktop { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-7-desktop-only { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-7-widescreen { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-7-fullhd { + --columnGap: 1.75rem; } } + html.theme--documenter-dark .columns.is-variable.is-8 { + --columnGap: 2rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .columns.is-variable.is-8-mobile { + --columnGap: 2rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .columns.is-variable.is-8-tablet { + --columnGap: 2rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-8-tablet-only { + --columnGap: 2rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .columns.is-variable.is-8-touch { + --columnGap: 2rem; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .columns.is-variable.is-8-desktop { + --columnGap: 2rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + html.theme--documenter-dark .columns.is-variable.is-8-desktop-only { + --columnGap: 2rem; } } + @media screen and (min-width: 1216px) { + html.theme--documenter-dark .columns.is-variable.is-8-widescreen { + --columnGap: 2rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only { + --columnGap: 2rem; } } + @media screen and (min-width: 1408px) { + html.theme--documenter-dark .columns.is-variable.is-8-fullhd { + --columnGap: 2rem; } } + html.theme--documenter-dark .tile { + align-items: stretch; + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + min-height: min-content; } + html.theme--documenter-dark .tile.is-ancestor { + margin-left: -0.75rem; + margin-right: -0.75rem; + margin-top: -0.75rem; } + html.theme--documenter-dark .tile.is-ancestor:last-child { + margin-bottom: -0.75rem; } + html.theme--documenter-dark .tile.is-ancestor:not(:last-child) { + margin-bottom: 0.75rem; } + html.theme--documenter-dark .tile.is-child { + margin: 0 !important; } + html.theme--documenter-dark .tile.is-parent { + padding: 0.75rem; } + html.theme--documenter-dark .tile.is-vertical { + flex-direction: column; } + html.theme--documenter-dark .tile.is-vertical > .tile.is-child:not(:last-child) { + margin-bottom: 1.5rem !important; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .tile:not(.is-child) { + display: flex; } + html.theme--documenter-dark .tile.is-1 { + flex: none; + width: 8.3333333333%; } + html.theme--documenter-dark .tile.is-2 { + flex: none; + width: 16.6666666667%; } + html.theme--documenter-dark .tile.is-3 { + flex: none; + width: 25%; } + html.theme--documenter-dark .tile.is-4 { + flex: none; + width: 33.3333333333%; } + html.theme--documenter-dark .tile.is-5 { + flex: none; + width: 41.6666666667%; } + html.theme--documenter-dark .tile.is-6 { + flex: none; + width: 50%; } + html.theme--documenter-dark .tile.is-7 { + flex: none; + width: 58.3333333333%; } + html.theme--documenter-dark .tile.is-8 { + flex: none; + width: 66.6666666667%; } + html.theme--documenter-dark .tile.is-9 { + flex: none; + width: 75%; } + html.theme--documenter-dark .tile.is-10 { + flex: none; + width: 83.3333333333%; } + html.theme--documenter-dark .tile.is-11 { + flex: none; + width: 91.6666666667%; } + html.theme--documenter-dark .tile.is-12 { + flex: none; + width: 100%; } } + html.theme--documenter-dark .hero { + align-items: stretch; + display: flex; + flex-direction: column; + justify-content: space-between; } + html.theme--documenter-dark .hero .navbar { + background: none; } + html.theme--documenter-dark .hero .tabs ul { + border-bottom: none; } + html.theme--documenter-dark .hero.is-white { + background-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-white strong { + color: inherit; } + html.theme--documenter-dark .hero.is-white .title { + color: #0a0a0a; } + html.theme--documenter-dark .hero.is-white .subtitle { + color: rgba(10, 10, 10, 0.9); } + html.theme--documenter-dark .hero.is-white .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-white .subtitle strong { + color: #0a0a0a; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-white .navbar-menu { + background-color: white; } } + html.theme--documenter-dark .hero.is-white .navbar-item, + html.theme--documenter-dark .hero.is-white .navbar-link { + color: rgba(10, 10, 10, 0.7); } + html.theme--documenter-dark .hero.is-white a.navbar-item:hover, html.theme--documenter-dark .hero.is-white a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-white .navbar-link:hover, + html.theme--documenter-dark .hero.is-white .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + html.theme--documenter-dark .hero.is-white .tabs a { + color: #0a0a0a; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-white .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-white .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-white .tabs.is-boxed a, html.theme--documenter-dark .hero.is-white .tabs.is-toggle a { + color: #0a0a0a; } + html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .hero.is-white.is-bold { + background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); } } + html.theme--documenter-dark .hero.is-black { + background-color: #0a0a0a; + color: white; } + html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-black strong { + color: inherit; } + html.theme--documenter-dark .hero.is-black .title { + color: white; } + html.theme--documenter-dark .hero.is-black .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-black .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-black .subtitle strong { + color: white; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-black .navbar-menu { + background-color: #0a0a0a; } } + html.theme--documenter-dark .hero.is-black .navbar-item, + html.theme--documenter-dark .hero.is-black .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-black a.navbar-item:hover, html.theme--documenter-dark .hero.is-black a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-black .navbar-link:hover, + html.theme--documenter-dark .hero.is-black .navbar-link.is-active { + background-color: black; + color: white; } + html.theme--documenter-dark .hero.is-black .tabs a { + color: white; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-black .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-black .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-black .tabs.is-boxed a, html.theme--documenter-dark .hero.is-black .tabs.is-toggle a { + color: white; } + html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover { + background-color: white; + border-color: white; + color: #0a0a0a; } + html.theme--documenter-dark .hero.is-black.is-bold { + background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu { + background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } } + html.theme--documenter-dark .hero.is-light { + background-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-light strong { + color: inherit; } + html.theme--documenter-dark .hero.is-light .title { + color: #282f2f; } + html.theme--documenter-dark .hero.is-light .subtitle { + color: rgba(40, 47, 47, 0.9); } + html.theme--documenter-dark .hero.is-light .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-light .subtitle strong { + color: #282f2f; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-light .navbar-menu { + background-color: #ecf0f1; } } + html.theme--documenter-dark .hero.is-light .navbar-item, + html.theme--documenter-dark .hero.is-light .navbar-link { + color: rgba(40, 47, 47, 0.7); } + html.theme--documenter-dark .hero.is-light a.navbar-item:hover, html.theme--documenter-dark .hero.is-light a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-light .navbar-link:hover, + html.theme--documenter-dark .hero.is-light .navbar-link.is-active { + background-color: #dde4e6; + color: #282f2f; } + html.theme--documenter-dark .hero.is-light .tabs a { + color: #282f2f; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-light .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-light .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-light .tabs.is-boxed a, html.theme--documenter-dark .hero.is-light .tabs.is-toggle a { + color: #282f2f; } + html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover { + background-color: #282f2f; + border-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .hero.is-light.is-bold { + background-image: linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%); } } + html.theme--documenter-dark .hero.is-dark, html.theme--documenter-dark .content kbd.hero { + background-color: #282f2f; + color: #ecf0f1; } + html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-dark strong, + html.theme--documenter-dark .content kbd.hero strong { + color: inherit; } + html.theme--documenter-dark .hero.is-dark .title, html.theme--documenter-dark .content kbd.hero .title { + color: #ecf0f1; } + html.theme--documenter-dark .hero.is-dark .subtitle, html.theme--documenter-dark .content kbd.hero .subtitle { + color: rgba(236, 240, 241, 0.9); } + html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button), html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-dark .subtitle strong, + html.theme--documenter-dark .content kbd.hero .subtitle strong { + color: #ecf0f1; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-dark .navbar-menu, html.theme--documenter-dark .content kbd.hero .navbar-menu { + background-color: #282f2f; } } + html.theme--documenter-dark .hero.is-dark .navbar-item, html.theme--documenter-dark .content kbd.hero .navbar-item, + html.theme--documenter-dark .hero.is-dark .navbar-link, + html.theme--documenter-dark .content kbd.hero .navbar-link { + color: rgba(236, 240, 241, 0.7); } + html.theme--documenter-dark .hero.is-dark a.navbar-item:hover, html.theme--documenter-dark .content kbd.hero a.navbar-item:hover, html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active, html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-dark .navbar-link:hover, + html.theme--documenter-dark .content kbd.hero .navbar-link:hover, + html.theme--documenter-dark .hero.is-dark .navbar-link.is-active, + html.theme--documenter-dark .content kbd.hero .navbar-link.is-active { + background-color: #1d2122; + color: #ecf0f1; } + html.theme--documenter-dark .hero.is-dark .tabs a, html.theme--documenter-dark .content kbd.hero .tabs a { + color: #ecf0f1; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-dark .tabs a:hover, html.theme--documenter-dark .content kbd.hero .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-dark .tabs li.is-active a, html.theme--documenter-dark .content kbd.hero .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a, html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a, html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a, html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a { + color: #ecf0f1; } + html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover, html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover, html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a, html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a, html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover { + background-color: #ecf0f1; + border-color: #ecf0f1; + color: #282f2f; } + html.theme--documenter-dark .hero.is-dark.is-bold, html.theme--documenter-dark .content kbd.hero.is-bold { + background-image: linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu, html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%); } } + html.theme--documenter-dark .hero.is-primary, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink { + background-color: #375a7f; + color: #fff; } + html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-primary strong, + html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink strong { + color: inherit; } + html.theme--documenter-dark .hero.is-primary .title, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .title { + color: #fff; } + html.theme--documenter-dark .hero.is-primary .subtitle, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button), html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-primary .subtitle strong, + html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-primary .navbar-menu, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar-menu { + background-color: #375a7f; } } + html.theme--documenter-dark .hero.is-primary .navbar-item, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar-item, + html.theme--documenter-dark .hero.is-primary .navbar-link, + html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-primary a.navbar-item:hover, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink a.navbar-item:hover, html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-primary .navbar-link:hover, + html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar-link:hover, + html.theme--documenter-dark .hero.is-primary .navbar-link.is-active, + html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar-link.is-active { + background-color: #2f4d6d; + color: #fff; } + html.theme--documenter-dark .hero.is-primary .tabs a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-primary .tabs a:hover, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-primary .tabs li.is-active a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed a, html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #375a7f; } + html.theme--documenter-dark .hero.is-primary.is-bold, html.theme--documenter-dark .docstring > section > a.hero.is-bold.docs-sourcelink { + background-image: linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu, html.theme--documenter-dark .docstring > section > a.hero.is-bold.docs-sourcelink .navbar-menu { + background-image: linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%); } } + html.theme--documenter-dark .hero.is-link { + background-color: #1abc9c; + color: #fff; } + html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-link strong { + color: inherit; } + html.theme--documenter-dark .hero.is-link .title { + color: #fff; } + html.theme--documenter-dark .hero.is-link .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-link .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-link .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-link .navbar-menu { + background-color: #1abc9c; } } + html.theme--documenter-dark .hero.is-link .navbar-item, + html.theme--documenter-dark .hero.is-link .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-link a.navbar-item:hover, html.theme--documenter-dark .hero.is-link a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-link .navbar-link:hover, + html.theme--documenter-dark .hero.is-link .navbar-link.is-active { + background-color: #17a689; + color: #fff; } + html.theme--documenter-dark .hero.is-link .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-link .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-link .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-link .tabs.is-boxed a, html.theme--documenter-dark .hero.is-link .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #1abc9c; } + html.theme--documenter-dark .hero.is-link.is-bold { + background-image: linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%); } } + html.theme--documenter-dark .hero.is-info { + background-color: #024c7d; + color: #fff; } + html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-info strong { + color: inherit; } + html.theme--documenter-dark .hero.is-info .title { + color: #fff; } + html.theme--documenter-dark .hero.is-info .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-info .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-info .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-info .navbar-menu { + background-color: #024c7d; } } + html.theme--documenter-dark .hero.is-info .navbar-item, + html.theme--documenter-dark .hero.is-info .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-info a.navbar-item:hover, html.theme--documenter-dark .hero.is-info a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-info .navbar-link:hover, + html.theme--documenter-dark .hero.is-info .navbar-link.is-active { + background-color: #023d64; + color: #fff; } + html.theme--documenter-dark .hero.is-info .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-info .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-info .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-info .tabs.is-boxed a, html.theme--documenter-dark .hero.is-info .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #024c7d; } + html.theme--documenter-dark .hero.is-info.is-bold { + background-image: linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%); } } + html.theme--documenter-dark .hero.is-success { + background-color: #008438; + color: #fff; } + html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-success strong { + color: inherit; } + html.theme--documenter-dark .hero.is-success .title { + color: #fff; } + html.theme--documenter-dark .hero.is-success .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-success .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-success .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-success .navbar-menu { + background-color: #008438; } } + html.theme--documenter-dark .hero.is-success .navbar-item, + html.theme--documenter-dark .hero.is-success .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-success a.navbar-item:hover, html.theme--documenter-dark .hero.is-success a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-success .navbar-link:hover, + html.theme--documenter-dark .hero.is-success .navbar-link.is-active { + background-color: #006b2d; + color: #fff; } + html.theme--documenter-dark .hero.is-success .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-success .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-success .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-success .tabs.is-boxed a, html.theme--documenter-dark .hero.is-success .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #008438; } + html.theme--documenter-dark .hero.is-success.is-bold { + background-image: linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%); } } + html.theme--documenter-dark .hero.is-warning { + background-color: #ad8100; + color: #fff; } + html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-warning strong { + color: inherit; } + html.theme--documenter-dark .hero.is-warning .title { + color: #fff; } + html.theme--documenter-dark .hero.is-warning .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-warning .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-warning .navbar-menu { + background-color: #ad8100; } } + html.theme--documenter-dark .hero.is-warning .navbar-item, + html.theme--documenter-dark .hero.is-warning .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-warning a.navbar-item:hover, html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-warning .navbar-link:hover, + html.theme--documenter-dark .hero.is-warning .navbar-link.is-active { + background-color: #946e00; + color: #fff; } + html.theme--documenter-dark .hero.is-warning .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-warning .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-warning .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a, html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #ad8100; } + html.theme--documenter-dark .hero.is-warning.is-bold { + background-image: linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%); } } + html.theme--documenter-dark .hero.is-danger { + background-color: #9e1b0d; + color: #fff; } + html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + html.theme--documenter-dark .hero.is-danger strong { + color: inherit; } + html.theme--documenter-dark .hero.is-danger .title { + color: #fff; } + html.theme--documenter-dark .hero.is-danger .subtitle { + color: rgba(255, 255, 255, 0.9); } + html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button), + html.theme--documenter-dark .hero.is-danger .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .hero.is-danger .navbar-menu { + background-color: #9e1b0d; } } + html.theme--documenter-dark .hero.is-danger .navbar-item, + html.theme--documenter-dark .hero.is-danger .navbar-link { + color: rgba(255, 255, 255, 0.7); } + html.theme--documenter-dark .hero.is-danger a.navbar-item:hover, html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active, + html.theme--documenter-dark .hero.is-danger .navbar-link:hover, + html.theme--documenter-dark .hero.is-danger .navbar-link.is-active { + background-color: #86170b; + color: #fff; } + html.theme--documenter-dark .hero.is-danger .tabs a { + color: #fff; + opacity: 0.9; } + html.theme--documenter-dark .hero.is-danger .tabs a:hover { + opacity: 1; } + html.theme--documenter-dark .hero.is-danger .tabs li.is-active a { + opacity: 1; } + html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a, html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a { + color: #fff; } + html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover, html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a, html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover, html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a, html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #9e1b0d; } + html.theme--documenter-dark .hero.is-danger.is-bold { + background-image: linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%); } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%); } } + html.theme--documenter-dark .hero.is-small .hero-body, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.hero .hero-body { + padding-bottom: 1.5rem; + padding-top: 1.5rem; } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .hero.is-medium .hero-body { + padding-bottom: 9rem; + padding-top: 9rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .hero.is-large .hero-body { + padding-bottom: 18rem; + padding-top: 18rem; } } + html.theme--documenter-dark .hero.is-halfheight .hero-body, html.theme--documenter-dark .hero.is-fullheight .hero-body, html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body { + align-items: center; + display: flex; } + html.theme--documenter-dark .hero.is-halfheight .hero-body > .container, html.theme--documenter-dark .hero.is-fullheight .hero-body > .container, html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body > .container { + flex-grow: 1; + flex-shrink: 1; } + html.theme--documenter-dark .hero.is-halfheight { + min-height: 50vh; } + html.theme--documenter-dark .hero.is-fullheight { + min-height: 100vh; } + html.theme--documenter-dark .hero-video { + overflow: hidden; } + html.theme--documenter-dark .hero-video video { + left: 50%; + min-height: 100%; + min-width: 100%; + position: absolute; + top: 50%; + transform: translate3d(-50%, -50%, 0); } + html.theme--documenter-dark .hero-video.is-transparent { + opacity: 0.3; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero-video { + display: none; } } + html.theme--documenter-dark .hero-buttons { + margin-top: 1.5rem; } + @media screen and (max-width: 768px) { + html.theme--documenter-dark .hero-buttons .button { + display: flex; } + html.theme--documenter-dark .hero-buttons .button:not(:last-child) { + margin-bottom: 0.75rem; } } + @media screen and (min-width: 769px), print { + html.theme--documenter-dark .hero-buttons { + display: flex; + justify-content: center; } + html.theme--documenter-dark .hero-buttons .button:not(:last-child) { + margin-right: 1.5rem; } } + html.theme--documenter-dark .hero-head, + html.theme--documenter-dark .hero-foot { + flex-grow: 0; + flex-shrink: 0; } + html.theme--documenter-dark .hero-body { + flex-grow: 1; + flex-shrink: 0; + padding: 3rem 1.5rem; } + html.theme--documenter-dark .section { + padding: 3rem 1.5rem; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark .section.is-medium { + padding: 9rem 1.5rem; } + html.theme--documenter-dark .section.is-large { + padding: 18rem 1.5rem; } } + html.theme--documenter-dark .footer { + background-color: #282f2f; + padding: 3rem 1.5rem 6rem; } + html.theme--documenter-dark hr { + height: 1px; } + html.theme--documenter-dark h6 { + text-transform: uppercase; + letter-spacing: 0.5px; } + html.theme--documenter-dark .hero { + background-color: #343c3d; } + html.theme--documenter-dark a { + transition: all 200ms ease; } + html.theme--documenter-dark .button { + transition: all 200ms ease; + border-width: 1px; + color: white; } + html.theme--documenter-dark .button.is-active, html.theme--documenter-dark .button.is-focused, html.theme--documenter-dark .button:active, html.theme--documenter-dark .button:focus { + box-shadow: 0 0 0 2px rgba(140, 155, 157, 0.5); } + html.theme--documenter-dark .button.is-white.is-hovered, html.theme--documenter-dark .button.is-white:hover { + background-color: white; } + html.theme--documenter-dark .button.is-white.is-active, html.theme--documenter-dark .button.is-white.is-focused, html.theme--documenter-dark .button.is-white:active, html.theme--documenter-dark .button.is-white:focus { + border-color: white; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5); } + html.theme--documenter-dark .button.is-black.is-hovered, html.theme--documenter-dark .button.is-black:hover { + background-color: #1d1d1d; } + html.theme--documenter-dark .button.is-black.is-active, html.theme--documenter-dark .button.is-black.is-focused, html.theme--documenter-dark .button.is-black:active, html.theme--documenter-dark .button.is-black:focus { + border-color: #0a0a0a; + box-shadow: 0 0 0 2px rgba(10, 10, 10, 0.5); } + html.theme--documenter-dark .button.is-light.is-hovered, html.theme--documenter-dark .button.is-light:hover { + background-color: white; } + html.theme--documenter-dark .button.is-light.is-active, html.theme--documenter-dark .button.is-light.is-focused, html.theme--documenter-dark .button.is-light:active, html.theme--documenter-dark .button.is-light:focus { + border-color: #ecf0f1; + box-shadow: 0 0 0 2px rgba(236, 240, 241, 0.5); } + html.theme--documenter-dark .button.is-dark.is-hovered, html.theme--documenter-dark .content kbd.button.is-hovered, html.theme--documenter-dark .button.is-dark:hover, html.theme--documenter-dark .content kbd.button:hover { + background-color: #3a4344; } + html.theme--documenter-dark .button.is-dark.is-active, html.theme--documenter-dark .content kbd.button.is-active, html.theme--documenter-dark .button.is-dark.is-focused, html.theme--documenter-dark .content kbd.button.is-focused, html.theme--documenter-dark .button.is-dark:active, html.theme--documenter-dark .content kbd.button:active, html.theme--documenter-dark .button.is-dark:focus, html.theme--documenter-dark .content kbd.button:focus { + border-color: #282f2f; + box-shadow: 0 0 0 2px rgba(40, 47, 47, 0.5); } + html.theme--documenter-dark .button.is-primary.is-hovered, html.theme--documenter-dark .docstring > section > a.button.is-hovered.docs-sourcelink, html.theme--documenter-dark .button.is-primary:hover, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:hover { + background-color: #436d9a; } + html.theme--documenter-dark .button.is-primary.is-active, html.theme--documenter-dark .docstring > section > a.button.is-active.docs-sourcelink, html.theme--documenter-dark .button.is-primary.is-focused, html.theme--documenter-dark .docstring > section > a.button.is-focused.docs-sourcelink, html.theme--documenter-dark .button.is-primary:active, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:active, html.theme--documenter-dark .button.is-primary:focus, html.theme--documenter-dark .docstring > section > a.button.docs-sourcelink:focus { + border-color: #375a7f; + box-shadow: 0 0 0 2px rgba(55, 90, 127, 0.5); } + html.theme--documenter-dark .button.is-link.is-hovered, html.theme--documenter-dark .button.is-link:hover { + background-color: #1fdeb8; } + html.theme--documenter-dark .button.is-link.is-active, html.theme--documenter-dark .button.is-link.is-focused, html.theme--documenter-dark .button.is-link:active, html.theme--documenter-dark .button.is-link:focus { + border-color: #1abc9c; + box-shadow: 0 0 0 2px rgba(26, 188, 156, 0.5); } + html.theme--documenter-dark .button.is-info.is-hovered, html.theme--documenter-dark .button.is-info:hover { + background-color: #0363a3; } + html.theme--documenter-dark .button.is-info.is-active, html.theme--documenter-dark .button.is-info.is-focused, html.theme--documenter-dark .button.is-info:active, html.theme--documenter-dark .button.is-info:focus { + border-color: #024c7d; + box-shadow: 0 0 0 2px rgba(2, 76, 125, 0.5); } + html.theme--documenter-dark .button.is-success.is-hovered, html.theme--documenter-dark .button.is-success:hover { + background-color: #00aa48; } + html.theme--documenter-dark .button.is-success.is-active, html.theme--documenter-dark .button.is-success.is-focused, html.theme--documenter-dark .button.is-success:active, html.theme--documenter-dark .button.is-success:focus { + border-color: #008438; + box-shadow: 0 0 0 2px rgba(0, 132, 56, 0.5); } + html.theme--documenter-dark .button.is-warning.is-hovered, html.theme--documenter-dark .button.is-warning:hover { + background-color: #d39e00; } + html.theme--documenter-dark .button.is-warning.is-active, html.theme--documenter-dark .button.is-warning.is-focused, html.theme--documenter-dark .button.is-warning:active, html.theme--documenter-dark .button.is-warning:focus { + border-color: #ad8100; + box-shadow: 0 0 0 2px rgba(173, 129, 0, 0.5); } + html.theme--documenter-dark .button.is-danger.is-hovered, html.theme--documenter-dark .button.is-danger:hover { + background-color: #c12110; } + html.theme--documenter-dark .button.is-danger.is-active, html.theme--documenter-dark .button.is-danger.is-focused, html.theme--documenter-dark .button.is-danger:active, html.theme--documenter-dark .button.is-danger:focus { + border-color: #9e1b0d; + box-shadow: 0 0 0 2px rgba(158, 27, 13, 0.5); } + html.theme--documenter-dark .label { + color: #dbdee0; } + html.theme--documenter-dark .button, + html.theme--documenter-dark .control.has-icons-left .icon, + html.theme--documenter-dark .control.has-icons-right .icon, + html.theme--documenter-dark .input, + html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark .pagination-ellipsis, + html.theme--documenter-dark .pagination-link, + html.theme--documenter-dark .pagination-next, + html.theme--documenter-dark .pagination-previous, + html.theme--documenter-dark .select, + html.theme--documenter-dark .select select, + html.theme--documenter-dark .textarea { + height: 2.5em; } + html.theme--documenter-dark .input, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark .textarea { + transition: all 200ms ease; + box-shadow: none; + border-width: 1px; + padding-left: 1em; + padding-right: 1em; } + html.theme--documenter-dark .select:after, + html.theme--documenter-dark .select select { + border-width: 1px; } + html.theme--documenter-dark .control.has-addons .button, + html.theme--documenter-dark .control.has-addons .input, + html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search > input, + html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search > input, + html.theme--documenter-dark .control.has-addons .select { + margin-right: -1px; } + html.theme--documenter-dark .notification { + background-color: #343c3d; } + html.theme--documenter-dark .card { + box-shadow: none; + border: 1px solid #343c3d; + background-color: #282f2f; + border-radius: 0.4em; } + html.theme--documenter-dark .card .card-image img { + border-radius: 0.4em 0.4em 0 0; } + html.theme--documenter-dark .card .card-header { + box-shadow: none; + background-color: rgba(18, 18, 18, 0.2); + border-radius: 0.4em 0.4em 0 0; } + html.theme--documenter-dark .card .card-footer { + background-color: rgba(18, 18, 18, 0.2); } + html.theme--documenter-dark .card .card-footer, + html.theme--documenter-dark .card .card-footer-item { + border-width: 1px; + border-color: #343c3d; } + html.theme--documenter-dark .notification.is-white a:not(.button) { + color: #0a0a0a; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-black a:not(.button) { + color: white; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-light a:not(.button) { + color: #282f2f; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-dark a:not(.button), html.theme--documenter-dark .content kbd.notification a:not(.button) { + color: #ecf0f1; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-primary a:not(.button), html.theme--documenter-dark .docstring > section > a.notification.docs-sourcelink a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-link a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-info a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-success a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-warning a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .notification.is-danger a:not(.button) { + color: #fff; + text-decoration: underline; } + html.theme--documenter-dark .tag, html.theme--documenter-dark .content kbd, html.theme--documenter-dark .docstring > section > a.docs-sourcelink { + border-radius: 0.4em; } + html.theme--documenter-dark .menu-list a { + transition: all 300ms ease; } + html.theme--documenter-dark .modal-card-body { + background-color: #282f2f; } + html.theme--documenter-dark .modal-card-foot, + html.theme--documenter-dark .modal-card-head { + border-color: #343c3d; } + html.theme--documenter-dark .message-header { + font-weight: 700; + background-color: #343c3d; + color: white; } + html.theme--documenter-dark .message-body { + border-width: 1px; + border-color: #343c3d; } + html.theme--documenter-dark .navbar { + border-radius: 0.4em; } + html.theme--documenter-dark .navbar.is-transparent { + background: none; } + html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active, html.theme--documenter-dark .docstring > section > a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active { + background-color: #1abc9c; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark .navbar .navbar-menu { + background-color: #375a7f; + border-radius: 0 0 0.4em 0.4em; } } + html.theme--documenter-dark .hero .navbar, + html.theme--documenter-dark body > .navbar { + border-radius: 0; } + html.theme--documenter-dark .pagination-link, + html.theme--documenter-dark .pagination-next, + html.theme--documenter-dark .pagination-previous { + border-width: 1px; } + html.theme--documenter-dark .panel-block, + html.theme--documenter-dark .panel-heading, + html.theme--documenter-dark .panel-tabs { + border-width: 1px; } + html.theme--documenter-dark .panel-block:first-child, + html.theme--documenter-dark .panel-heading:first-child, + html.theme--documenter-dark .panel-tabs:first-child { + border-top-width: 1px; } + html.theme--documenter-dark .panel-heading { + font-weight: 700; } + html.theme--documenter-dark .panel-tabs a { + border-width: 1px; + margin-bottom: -1px; } + html.theme--documenter-dark .panel-tabs a.is-active { + border-bottom-color: #17a689; } + html.theme--documenter-dark .panel-block:hover { + color: #1dd2af; } + html.theme--documenter-dark .panel-block:hover .panel-icon { + color: #1dd2af; } + html.theme--documenter-dark .panel-block.is-active .panel-icon { + color: #17a689; } + html.theme--documenter-dark .tabs a { + border-bottom-width: 1px; + margin-bottom: -1px; } + html.theme--documenter-dark .tabs ul { + border-bottom-width: 1px; } + html.theme--documenter-dark .tabs.is-boxed a { + border-width: 1px; } + html.theme--documenter-dark .tabs.is-boxed li.is-active a { + background-color: #1f2424; } + html.theme--documenter-dark .tabs.is-toggle li a { + border-width: 1px; + margin-bottom: 0; } + html.theme--documenter-dark .tabs.is-toggle li + li { + margin-left: -1px; } + html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover, html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover, html.theme--documenter-dark .docstring > section > a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover { + background-color: transparent; } + html.theme--documenter-dark h1 .docs-heading-anchor, html.theme--documenter-dark h1 .docs-heading-anchor:hover, html.theme--documenter-dark h1 .docs-heading-anchor:visited, html.theme--documenter-dark h2 .docs-heading-anchor, html.theme--documenter-dark h2 .docs-heading-anchor:hover, html.theme--documenter-dark h2 .docs-heading-anchor:visited, html.theme--documenter-dark h3 .docs-heading-anchor, html.theme--documenter-dark h3 .docs-heading-anchor:hover, html.theme--documenter-dark h3 .docs-heading-anchor:visited, html.theme--documenter-dark h4 .docs-heading-anchor, html.theme--documenter-dark h4 .docs-heading-anchor:hover, html.theme--documenter-dark h4 .docs-heading-anchor:visited, html.theme--documenter-dark h5 .docs-heading-anchor, html.theme--documenter-dark h5 .docs-heading-anchor:hover, html.theme--documenter-dark h5 .docs-heading-anchor:visited, html.theme--documenter-dark h6 .docs-heading-anchor, html.theme--documenter-dark h6 .docs-heading-anchor:hover, html.theme--documenter-dark h6 .docs-heading-anchor:visited { + color: #f2f2f2; } + html.theme--documenter-dark h1 .docs-heading-anchor-permalink, html.theme--documenter-dark h2 .docs-heading-anchor-permalink, html.theme--documenter-dark h3 .docs-heading-anchor-permalink, html.theme--documenter-dark h4 .docs-heading-anchor-permalink, html.theme--documenter-dark h5 .docs-heading-anchor-permalink, html.theme--documenter-dark h6 .docs-heading-anchor-permalink { + visibility: hidden; + vertical-align: middle; + margin-left: 0.5em; + font-size: 0.7rem; } + html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before, html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before, html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before, html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before, html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before, html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0c1"; } + html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink, html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink, html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink, html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink, html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink, html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink { + visibility: visible; } + html.theme--documenter-dark .docs-light-only { + display: none !important; } + html.theme--documenter-dark pre { + position: relative; + overflow: hidden; } + html.theme--documenter-dark pre code, html.theme--documenter-dark pre code.hljs { + padding: 0 0.75rem !important; + overflow: auto; + display: block; } + html.theme--documenter-dark pre code:first-of-type, html.theme--documenter-dark pre code.hljs:first-of-type { + padding-top: 0.5rem !important; } + html.theme--documenter-dark pre code:last-of-type, html.theme--documenter-dark pre code.hljs:last-of-type { + padding-bottom: 0.5rem !important; } + html.theme--documenter-dark pre .copy-button { + opacity: 0.2; + transition: opacity 0.2s; + position: absolute; + right: 0em; + top: 0em; + padding: 0.5em; + width: 2.5em; + height: 2.5em; + background: transparent; + border: none; + font-family: "Font Awesome 5 Free"; + color: #fff; + cursor: pointer; + text-align: center; } + html.theme--documenter-dark pre .copy-button:focus, html.theme--documenter-dark pre .copy-button:hover { + opacity: 1; + background: rgba(255, 255, 255, 0.1); + color: #1abc9c; } + html.theme--documenter-dark pre .copy-button.success { + color: #259a12; + opacity: 1; } + html.theme--documenter-dark pre .copy-button.error { + color: #cb3c33; + opacity: 1; } + html.theme--documenter-dark pre:hover .copy-button { + opacity: 1; } + html.theme--documenter-dark .admonition { + background-color: #282f2f; + border-style: solid; + border-width: 1px; + border-color: #5e6d6f; + border-radius: 0.4em; + font-size: 15px; } + html.theme--documenter-dark .admonition strong { + color: currentColor; } + html.theme--documenter-dark .admonition.is-small, html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input.admonition { + font-size: 0.85em; } + html.theme--documenter-dark .admonition.is-medium { + font-size: 1.25rem; } + html.theme--documenter-dark .admonition.is-large { + font-size: 1.5rem; } + html.theme--documenter-dark .admonition.is-default { + background-color: #282f2f; + border-color: #5e6d6f; } + html.theme--documenter-dark .admonition.is-default > .admonition-header { + background-color: #5e6d6f; } + html.theme--documenter-dark .admonition.is-info { + background-color: #282f2f; + border-color: #024c7d; } + html.theme--documenter-dark .admonition.is-info > .admonition-header { + background-color: #024c7d; } + html.theme--documenter-dark .admonition.is-success { + background-color: #282f2f; + border-color: #008438; } + html.theme--documenter-dark .admonition.is-success > .admonition-header { + background-color: #008438; } + html.theme--documenter-dark .admonition.is-warning { + background-color: #282f2f; + border-color: #ad8100; } + html.theme--documenter-dark .admonition.is-warning > .admonition-header { + background-color: #ad8100; } + html.theme--documenter-dark .admonition.is-danger { + background-color: #282f2f; + border-color: #9e1b0d; } + html.theme--documenter-dark .admonition.is-danger > .admonition-header { + background-color: #9e1b0d; } + html.theme--documenter-dark .admonition.is-compat { + background-color: #282f2f; + border-color: #137886; } + html.theme--documenter-dark .admonition.is-compat > .admonition-header { + background-color: #137886; } + html.theme--documenter-dark .admonition-header { + background-color: #5e6d6f; + align-items: center; + font-weight: 700; + justify-content: space-between; + line-height: 1.25; + padding: 0.5rem 0.75rem; + position: relative; } + html.theme--documenter-dark .admonition-header:before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + margin-right: 0.75rem; + content: "\f06a"; } + html.theme--documenter-dark .admonition-body { + color: #fff; + padding: 0.5rem 0.75rem; } + html.theme--documenter-dark .admonition-body pre { + background-color: #282f2f; } + html.theme--documenter-dark .admonition-body code { + background-color: rgba(255, 255, 255, 0.05); } + html.theme--documenter-dark .docstring { + margin-bottom: 1em; + background-color: transparent; + border: 1px solid #5e6d6f; + box-shadow: none; + max-width: 100%; } + html.theme--documenter-dark .docstring > header { + display: flex; + flex-grow: 1; + align-items: stretch; + padding: 0.5rem 0.75rem; + background-color: #282f2f; + box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1); + box-shadow: none; + border-bottom: 1px solid #5e6d6f; } + html.theme--documenter-dark .docstring > header code { + background-color: transparent; } + html.theme--documenter-dark .docstring > header .docstring-binding { + margin-right: 0.3em; } + html.theme--documenter-dark .docstring > header .docstring-category { + margin-left: 0.3em; } + html.theme--documenter-dark .docstring > section { + position: relative; + padding: 0.75rem 0.75rem; + border-bottom: 1px solid #5e6d6f; } + html.theme--documenter-dark .docstring > section:last-child { + border-bottom: none; } + html.theme--documenter-dark .docstring > section > a.docs-sourcelink { + transition: opacity 0.3s; + opacity: 0; + position: absolute; + right: 0.375rem; + bottom: 0.375rem; } + html.theme--documenter-dark .docstring > section > a.docs-sourcelink:focus { + opacity: 1 !important; } + html.theme--documenter-dark .docstring:hover > section > a.docs-sourcelink { + opacity: 0.2; } + html.theme--documenter-dark .docstring:focus-within > section > a.docs-sourcelink { + opacity: 0.2; } + html.theme--documenter-dark .docstring > section:hover a.docs-sourcelink { + opacity: 1; } + html.theme--documenter-dark .documenter-example-output { + background-color: #1f2424; } + html.theme--documenter-dark .outdated-warning-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + z-index: 999; + background-color: #282f2f; + border-bottom: 3px solid #9e1b0d; + padding: 10px 35px; + text-align: center; + font-size: 15px; } + html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer { + position: absolute; + top: calc(50% - 10px); + right: 18px; + cursor: pointer; + width: 12px; } + html.theme--documenter-dark .outdated-warning-overlay a { + color: #1abc9c; } + html.theme--documenter-dark .outdated-warning-overlay a:hover { + color: #1dd2af; } + html.theme--documenter-dark .content pre { + border: 1px solid #5e6d6f; } + html.theme--documenter-dark .content code { + font-weight: inherit; } + html.theme--documenter-dark .content a code { + color: #1abc9c; } + html.theme--documenter-dark .content h1 code, html.theme--documenter-dark .content h2 code, html.theme--documenter-dark .content h3 code, html.theme--documenter-dark .content h4 code, html.theme--documenter-dark .content h5 code, html.theme--documenter-dark .content h6 code { + color: #f2f2f2; } + html.theme--documenter-dark .content table { + display: block; + width: initial; + max-width: 100%; + overflow-x: auto; } + html.theme--documenter-dark .content blockquote > ul:first-child, html.theme--documenter-dark .content blockquote > ol:first-child, html.theme--documenter-dark .content .admonition-body > ul:first-child, html.theme--documenter-dark .content .admonition-body > ol:first-child { + margin-top: 0; } + html.theme--documenter-dark pre, html.theme--documenter-dark code { + font-variant-ligatures: no-contextual; } + html.theme--documenter-dark .breadcrumb a.is-disabled { + cursor: default; + pointer-events: none; } + html.theme--documenter-dark .breadcrumb a.is-disabled, html.theme--documenter-dark .breadcrumb a.is-disabled:hover { + color: #f2f2f2; } + html.theme--documenter-dark .hljs { + background: initial !important; } + html.theme--documenter-dark .katex .katex-mathml { + top: 0; + right: 0; } + html.theme--documenter-dark .katex-display, html.theme--documenter-dark mjx-container, html.theme--documenter-dark .MathJax_Display { + margin: 0.5em 0 !important; } + html.theme--documenter-dark html { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: auto; } + html.theme--documenter-dark li.no-marker { + list-style: none; } + html.theme--documenter-dark #documenter .docs-main > article { + overflow-wrap: break-word; } + html.theme--documenter-dark #documenter .docs-main > article .math-container { + overflow-x: auto; + overflow-y: hidden; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark #documenter .docs-main { + max-width: 52rem; + margin-left: 20rem; + padding-right: 1rem; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark #documenter .docs-main { + width: 100%; } + html.theme--documenter-dark #documenter .docs-main > article { + max-width: 52rem; + margin-left: auto; + margin-right: auto; + margin-bottom: 1rem; + padding: 0 1rem; } + html.theme--documenter-dark #documenter .docs-main > header, html.theme--documenter-dark #documenter .docs-main > nav { + max-width: 100%; + width: 100%; + margin: 0; } } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar { + background-color: #1f2424; + border-bottom: 1px solid #5e6d6f; + z-index: 2; + min-height: 4rem; + margin-bottom: 1rem; + display: flex; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb { + flex-grow: 1; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right { + display: flex; + white-space: nowrap; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon, html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label, html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button { + display: inline-block; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label { + padding: 0; + margin-left: 0.3em; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-settings-button { + margin: auto 0 auto 1rem; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button { + font-size: 1.5rem; + margin: auto 0 auto 1rem; } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar > * { + margin: auto 0; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark #documenter .docs-main header.docs-navbar { + position: sticky; + top: 0; + padding: 0 1rem; + /* For Headroom.js */ + transition-property: top, box-shadow; + -webkit-transition-property: top, box-shadow; + /* Safari */ + transition-duration: 0.3s; + -webkit-transition-duration: 0.3s; + /* Safari */ } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top { + box-shadow: 0.2rem 0rem 0.4rem #171717; + transition-duration: 0.7s; + -webkit-transition-duration: 0.7s; + /* Safari */ } + html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom { + top: -4.5rem; + transition-duration: 0.7s; + -webkit-transition-duration: 0.7s; + /* Safari */ } } + html.theme--documenter-dark #documenter .docs-main section.footnotes { + border-top: 1px solid #5e6d6f; } + html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child, html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring > section > a.docs-sourcelink:first-child, html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child, html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child { + margin-right: 1em; + margin-bottom: 0.4em; } + html.theme--documenter-dark #documenter .docs-main .docs-footer { + display: flex; + flex-wrap: wrap; + margin-left: 0; + margin-right: 0; + border-top: 1px solid #5e6d6f; + padding-top: 1rem; + padding-bottom: 1rem; } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark #documenter .docs-main .docs-footer { + padding-left: 1rem; + padding-right: 1rem; } } + html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage, html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage { + flex-grow: 1; } + html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage { + text-align: right; } + html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break { + flex-basis: 100%; + height: 0; } + html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message { + font-size: 0.8em; + margin: 0.5em auto 0 auto; + text-align: center; } + html.theme--documenter-dark #documenter .docs-sidebar { + display: flex; + flex-direction: column; + color: #fff; + background-color: #282f2f; + border-right: 1px solid #5e6d6f; + padding: 0; + flex: 0 0 18rem; + z-index: 5; + font-size: 15px; + position: fixed; + left: -18rem; + width: 18rem; + height: 100%; + transition: left 0.3s; + /* Setting up a nicer theme style for the scrollbar */ } + html.theme--documenter-dark #documenter .docs-sidebar.visible { + left: 0; + box-shadow: 0.4rem 0rem 0.8rem #171717; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark #documenter .docs-sidebar.visible { + box-shadow: none; } } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark #documenter .docs-sidebar { + left: 0; + top: 0; } } + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo { + margin-top: 1rem; + padding: 0 1rem; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-logo > img { + max-height: 6rem; + margin: auto; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name { + flex-shrink: 0; + font-size: 1.5rem; + font-weight: 700; + text-align: center; + white-space: nowrap; + overflow: hidden; + padding: 0.5rem 0; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit { + max-width: 16.2rem; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a, html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover { + color: #fff; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector { + border-top: 1px solid #5e6d6f; + display: none; + padding: 0.5rem; } + html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible { + display: flex; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu { + flex-grow: 1; + user-select: none; + border-top: 1px solid #5e6d6f; + padding-bottom: 1.5rem; + /* Managing collapsible submenus */ } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu > li > .tocitem { + font-weight: bold; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu > li li { + font-size: 14.25px; + margin-left: 1em; + border-left: 1px solid #5e6d6f; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle { + display: none; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed { + display: none; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked ~ ul.collapsed { + display: block; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem { + display: flex; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label { + flex-grow: 2; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron { + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + font-size: 11.25px; + margin-left: 1rem; + margin-top: auto; + margin-bottom: auto; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f054"; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked ~ label.tocitem .docs-chevron::before { + content: "\f078"; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem { + display: block; + padding: 0.5rem 0.5rem; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem, html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover { + color: #fff; + background: #282f2f; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover, html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover { + color: #fff; + background-color: #32393a; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active { + border-top: 1px solid #5e6d6f; + border-bottom: 1px solid #5e6d6f; + background-color: #1f2424; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem, html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover { + background-color: #1f2424; + color: #fff; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover { + background-color: #32393a; + color: #fff; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu > li.is-active:first-child { + border-top: none; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal { + margin: 0 0.5rem 0.5rem; + border-top: 1px solid #5e6d6f; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li { + font-size: 12.75px; + border-left: none; + margin-left: 0; + margin-top: 0.5rem; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem { + width: 100%; + padding: 0; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before { + content: "⚬"; + margin-right: 0.4em; } + html.theme--documenter-dark #documenter .docs-sidebar form.docs-search { + margin: auto; + margin-top: 0.5rem; + margin-bottom: 0.5rem; } + html.theme--documenter-dark #documenter .docs-sidebar form.docs-search > input { + width: 14.4rem; } + @media screen and (min-width: 1056px) { + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu { + overflow-y: auto; + -webkit-overflow-scroll: touch; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar { + width: .3rem; + background: none; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb { + border-radius: 5px 0px 0px 5px; + background: #3b4445; } + html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover { + background: #4e5a5c; } } + @media screen and (max-width: 1055px) { + html.theme--documenter-dark #documenter .docs-sidebar { + overflow-y: auto; + -webkit-overflow-scroll: touch; } + html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar { + width: .3rem; + background: none; } + html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb { + border-radius: 5px 0px 0px 5px; + background: #3b4445; } + html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover { + background: #4e5a5c; } } + html.theme--documenter-dark #documenter .docs-main #documenter-search-info { + margin-bottom: 1rem; } + html.theme--documenter-dark #documenter .docs-main #documenter-search-results { + list-style-type: circle; + list-style-position: outside; } + html.theme--documenter-dark #documenter .docs-main #documenter-search-results li { + margin-left: 2rem; } + html.theme--documenter-dark #documenter .docs-main #documenter-search-results .docs-highlight { + background-color: yellow; } + html.theme--documenter-dark { + background-color: #1f2424; + font-size: 16px; + min-width: 300px; + overflow-x: auto; + overflow-y: scroll; + text-rendering: optimizeLegibility; + text-size-adjust: 100%; } + html.theme--documenter-dark .ansi span.sgr1 { + font-weight: bolder; } + html.theme--documenter-dark .ansi span.sgr2 { + font-weight: lighter; } + html.theme--documenter-dark .ansi span.sgr3 { + font-style: italic; } + html.theme--documenter-dark .ansi span.sgr4 { + text-decoration: underline; } + html.theme--documenter-dark .ansi span.sgr7 { + color: #1f2424; + background-color: #fff; } + html.theme--documenter-dark .ansi span.sgr8 { + color: transparent; } + html.theme--documenter-dark .ansi span.sgr8 span { + color: transparent; } + html.theme--documenter-dark .ansi span.sgr9 { + text-decoration: line-through; } + html.theme--documenter-dark .ansi span.sgr30 { + color: #242424; } + html.theme--documenter-dark .ansi span.sgr31 { + color: #f6705f; } + html.theme--documenter-dark .ansi span.sgr32 { + color: #4fb43a; } + html.theme--documenter-dark .ansi span.sgr33 { + color: #f4c72f; } + html.theme--documenter-dark .ansi span.sgr34 { + color: #7587f0; } + html.theme--documenter-dark .ansi span.sgr35 { + color: #bc89d3; } + html.theme--documenter-dark .ansi span.sgr36 { + color: #49b6ca; } + html.theme--documenter-dark .ansi span.sgr37 { + color: #b3bdbe; } + html.theme--documenter-dark .ansi span.sgr40 { + background-color: #242424; } + html.theme--documenter-dark .ansi span.sgr41 { + background-color: #f6705f; } + html.theme--documenter-dark .ansi span.sgr42 { + background-color: #4fb43a; } + html.theme--documenter-dark .ansi span.sgr43 { + background-color: #f4c72f; } + html.theme--documenter-dark .ansi span.sgr44 { + background-color: #7587f0; } + html.theme--documenter-dark .ansi span.sgr45 { + background-color: #bc89d3; } + html.theme--documenter-dark .ansi span.sgr46 { + background-color: #49b6ca; } + html.theme--documenter-dark .ansi span.sgr47 { + background-color: #b3bdbe; } + html.theme--documenter-dark .ansi span.sgr90 { + color: #92a0a2; } + html.theme--documenter-dark .ansi span.sgr91 { + color: #ff8674; } + html.theme--documenter-dark .ansi span.sgr92 { + color: #79d462; } + html.theme--documenter-dark .ansi span.sgr93 { + color: #ffe76b; } + html.theme--documenter-dark .ansi span.sgr94 { + color: #8a98ff; } + html.theme--documenter-dark .ansi span.sgr95 { + color: #d2a4e6; } + html.theme--documenter-dark .ansi span.sgr96 { + color: #6bc8db; } + html.theme--documenter-dark .ansi span.sgr97 { + color: #ecf0f1; } + html.theme--documenter-dark .ansi span.sgr100 { + background-color: #92a0a2; } + html.theme--documenter-dark .ansi span.sgr101 { + background-color: #ff8674; } + html.theme--documenter-dark .ansi span.sgr102 { + background-color: #79d462; } + html.theme--documenter-dark .ansi span.sgr103 { + background-color: #ffe76b; } + html.theme--documenter-dark .ansi span.sgr104 { + background-color: #8a98ff; } + html.theme--documenter-dark .ansi span.sgr105 { + background-color: #d2a4e6; } + html.theme--documenter-dark .ansi span.sgr106 { + background-color: #6bc8db; } + html.theme--documenter-dark .ansi span.sgr107 { + background-color: #ecf0f1; } + html.theme--documenter-dark code.language-julia-repl > span.hljs-meta { + color: #4fb43a; + font-weight: bolder; } + html.theme--documenter-dark .hljs { + background: #2b2b2b; + color: #f8f8f2; } + html.theme--documenter-dark .hljs-comment, + html.theme--documenter-dark .hljs-quote { + color: #d4d0ab; } + html.theme--documenter-dark .hljs-variable, + html.theme--documenter-dark .hljs-template-variable, + html.theme--documenter-dark .hljs-tag, + html.theme--documenter-dark .hljs-name, + html.theme--documenter-dark .hljs-selector-id, + html.theme--documenter-dark .hljs-selector-class, + html.theme--documenter-dark .hljs-regexp, + html.theme--documenter-dark .hljs-deletion { + color: #ffa07a; } + html.theme--documenter-dark .hljs-number, + html.theme--documenter-dark .hljs-built_in, + html.theme--documenter-dark .hljs-literal, + html.theme--documenter-dark .hljs-type, + html.theme--documenter-dark .hljs-params, + html.theme--documenter-dark .hljs-meta, + html.theme--documenter-dark .hljs-link { + color: #f5ab35; } + html.theme--documenter-dark .hljs-attribute { + color: #ffd700; } + html.theme--documenter-dark .hljs-string, + html.theme--documenter-dark .hljs-symbol, + html.theme--documenter-dark .hljs-bullet, + html.theme--documenter-dark .hljs-addition { + color: #abe338; } + html.theme--documenter-dark .hljs-title, + html.theme--documenter-dark .hljs-section { + color: #00e0e0; } + html.theme--documenter-dark .hljs-keyword, + html.theme--documenter-dark .hljs-selector-tag { + color: #dcc6e0; } + html.theme--documenter-dark .hljs-emphasis { + font-style: italic; } + html.theme--documenter-dark .hljs-strong { + font-weight: bold; } + @media screen and (-ms-high-contrast: active) { + html.theme--documenter-dark .hljs-addition, + html.theme--documenter-dark .hljs-attribute, + html.theme--documenter-dark .hljs-built_in, + html.theme--documenter-dark .hljs-bullet, + html.theme--documenter-dark .hljs-comment, + html.theme--documenter-dark .hljs-link, + html.theme--documenter-dark .hljs-literal, + html.theme--documenter-dark .hljs-meta, + html.theme--documenter-dark .hljs-number, + html.theme--documenter-dark .hljs-params, + html.theme--documenter-dark .hljs-string, + html.theme--documenter-dark .hljs-symbol, + html.theme--documenter-dark .hljs-type, + html.theme--documenter-dark .hljs-quote { + color: highlight; } + html.theme--documenter-dark .hljs-keyword, + html.theme--documenter-dark .hljs-selector-tag { + font-weight: bold; } } + html.theme--documenter-dark .hljs-subst { + color: #f8f8f2; } diff --git a/previews/PR2003/assets/themes/documenter-light.css b/previews/PR2003/assets/themes/documenter-light.css new file mode 100644 index 0000000000..9595d5b8ee --- /dev/null +++ b/previews/PR2003/assets/themes/documenter-light.css @@ -0,0 +1,7738 @@ +@charset "UTF-8"; +/* Font Awesome 5 mixin. Can be included in any rule that should render Font Awesome icons. */ +@keyframes spinAround { + from { + transform: rotate(0deg); } + to { + transform: rotate(359deg); } } + +.tabs, .pagination-previous, +.pagination-next, +.pagination-link, +.pagination-ellipsis, .breadcrumb, .file, .button, .is-unselectable, .modal-close, .delete { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +.navbar-link:not(.is-arrowless)::after, .select:not(.is-multiple):not(.is-loading)::after { + border: 3px solid transparent; + border-radius: 2px; + border-right: 0; + border-top: 0; + content: " "; + display: block; + height: 0.625em; + margin-top: -0.4375em; + pointer-events: none; + position: absolute; + top: 50%; + transform: rotate(-45deg); + transform-origin: center; + width: 0.625em; } + +.admonition:not(:last-child), .tabs:not(:last-child), .message:not(:last-child), .list:not(:last-child), .level:not(:last-child), .breadcrumb:not(:last-child), .highlight:not(:last-child), .block:not(:last-child), .title:not(:last-child), +.subtitle:not(:last-child), .table-container:not(:last-child), .table:not(:last-child), .progress:not(:last-child), .notification:not(:last-child), .content:not(:last-child), .box:not(:last-child) { + margin-bottom: 1.5rem; } + +.modal-close, .delete { + -moz-appearance: none; + -webkit-appearance: none; + background-color: rgba(10, 10, 10, 0.2); + border: none; + border-radius: 290486px; + cursor: pointer; + pointer-events: auto; + display: inline-block; + flex-grow: 0; + flex-shrink: 0; + font-size: 0; + height: 20px; + max-height: 20px; + max-width: 20px; + min-height: 20px; + min-width: 20px; + outline: none; + position: relative; + vertical-align: top; + width: 20px; } + .modal-close::before, .delete::before, .modal-close::after, .delete::after { + background-color: white; + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; } + .modal-close::before, .delete::before { + height: 2px; + width: 50%; } + .modal-close::after, .delete::after { + height: 50%; + width: 2px; } + .modal-close:hover, .delete:hover, .modal-close:focus, .delete:focus { + background-color: rgba(10, 10, 10, 0.3); } + .modal-close:active, .delete:active { + background-color: rgba(10, 10, 10, 0.4); } + .is-small.modal-close, #documenter .docs-sidebar form.docs-search > input.modal-close, .is-small.delete, #documenter .docs-sidebar form.docs-search > input.delete { + height: 16px; + max-height: 16px; + max-width: 16px; + min-height: 16px; + min-width: 16px; + width: 16px; } + .is-medium.modal-close, .is-medium.delete { + height: 24px; + max-height: 24px; + max-width: 24px; + min-height: 24px; + min-width: 24px; + width: 24px; } + .is-large.modal-close, .is-large.delete { + height: 32px; + max-height: 32px; + max-width: 32px; + min-height: 32px; + min-width: 32px; + width: 32px; } + +.control.is-loading::after, .select.is-loading::after, .loader, .button.is-loading::after { + animation: spinAround 500ms infinite linear; + border: 2px solid #dbdbdb; + border-radius: 290486px; + border-right-color: transparent; + border-top-color: transparent; + content: ""; + display: block; + height: 1em; + position: relative; + width: 1em; } + +.hero-video, .modal-background, .modal, .image.is-square img, #documenter .docs-sidebar .docs-logo > img.is-square img, +.image.is-square .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-square .has-ratio, .image.is-1by1 img, #documenter .docs-sidebar .docs-logo > img.is-1by1 img, +.image.is-1by1 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-1by1 .has-ratio, .image.is-5by4 img, #documenter .docs-sidebar .docs-logo > img.is-5by4 img, +.image.is-5by4 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-5by4 .has-ratio, .image.is-4by3 img, #documenter .docs-sidebar .docs-logo > img.is-4by3 img, +.image.is-4by3 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-4by3 .has-ratio, .image.is-3by2 img, #documenter .docs-sidebar .docs-logo > img.is-3by2 img, +.image.is-3by2 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-3by2 .has-ratio, .image.is-5by3 img, #documenter .docs-sidebar .docs-logo > img.is-5by3 img, +.image.is-5by3 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-5by3 .has-ratio, .image.is-16by9 img, #documenter .docs-sidebar .docs-logo > img.is-16by9 img, +.image.is-16by9 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-16by9 .has-ratio, .image.is-2by1 img, #documenter .docs-sidebar .docs-logo > img.is-2by1 img, +.image.is-2by1 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-2by1 .has-ratio, .image.is-3by1 img, #documenter .docs-sidebar .docs-logo > img.is-3by1 img, +.image.is-3by1 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-3by1 .has-ratio, .image.is-4by5 img, #documenter .docs-sidebar .docs-logo > img.is-4by5 img, +.image.is-4by5 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-4by5 .has-ratio, .image.is-3by4 img, #documenter .docs-sidebar .docs-logo > img.is-3by4 img, +.image.is-3by4 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-3by4 .has-ratio, .image.is-2by3 img, #documenter .docs-sidebar .docs-logo > img.is-2by3 img, +.image.is-2by3 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-2by3 .has-ratio, .image.is-3by5 img, #documenter .docs-sidebar .docs-logo > img.is-3by5 img, +.image.is-3by5 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-3by5 .has-ratio, .image.is-9by16 img, #documenter .docs-sidebar .docs-logo > img.is-9by16 img, +.image.is-9by16 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-9by16 .has-ratio, .image.is-1by2 img, #documenter .docs-sidebar .docs-logo > img.is-1by2 img, +.image.is-1by2 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-1by2 .has-ratio, .image.is-1by3 img, #documenter .docs-sidebar .docs-logo > img.is-1by3 img, +.image.is-1by3 .has-ratio, +#documenter .docs-sidebar .docs-logo > img.is-1by3 .has-ratio, .is-overlay { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; } + +.pagination-previous, +.pagination-next, +.pagination-link, +.pagination-ellipsis, .file-cta, +.file-name, .select select, .textarea, .input, #documenter .docs-sidebar form.docs-search > input, .button { + -moz-appearance: none; + -webkit-appearance: none; + align-items: center; + border: 1px solid transparent; + border-radius: 4px; + box-shadow: none; + display: inline-flex; + font-size: 1rem; + height: 2.25em; + justify-content: flex-start; + line-height: 1.5; + padding-bottom: calc(0.375em - 1px); + padding-left: calc(0.625em - 1px); + padding-right: calc(0.625em - 1px); + padding-top: calc(0.375em - 1px); + position: relative; + vertical-align: top; } + .pagination-previous:focus, + .pagination-next:focus, + .pagination-link:focus, + .pagination-ellipsis:focus, .file-cta:focus, + .file-name:focus, .select select:focus, .textarea:focus, .input:focus, #documenter .docs-sidebar form.docs-search > input:focus, .button:focus, .is-focused.pagination-previous, + .is-focused.pagination-next, + .is-focused.pagination-link, + .is-focused.pagination-ellipsis, .is-focused.file-cta, + .is-focused.file-name, .select select.is-focused, .is-focused.textarea, .is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-focused.button, .pagination-previous:active, + .pagination-next:active, + .pagination-link:active, + .pagination-ellipsis:active, .file-cta:active, + .file-name:active, .select select:active, .textarea:active, .input:active, #documenter .docs-sidebar form.docs-search > input:active, .button:active, .is-active.pagination-previous, + .is-active.pagination-next, + .is-active.pagination-link, + .is-active.pagination-ellipsis, .is-active.file-cta, + .is-active.file-name, .select select.is-active, .is-active.textarea, .is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active, .is-active.button { + outline: none; } + .pagination-previous[disabled], + .pagination-next[disabled], + .pagination-link[disabled], + .pagination-ellipsis[disabled], .file-cta[disabled], + .file-name[disabled], .select select[disabled], .textarea[disabled], .input[disabled], #documenter .docs-sidebar form.docs-search > input[disabled], .button[disabled], fieldset[disabled] .pagination-previous, + fieldset[disabled] .pagination-next, + fieldset[disabled] .pagination-link, + fieldset[disabled] .pagination-ellipsis, fieldset[disabled] .file-cta, + fieldset[disabled] .file-name, fieldset[disabled] .select select, .select fieldset[disabled] select, fieldset[disabled] .textarea, fieldset[disabled] .input, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input, fieldset[disabled] .button { + cursor: not-allowed; } + +/*! minireset.css v0.0.4 | MIT License | github.com/jgthms/minireset.css */ +html, +body, +p, +ol, +ul, +li, +dl, +dt, +dd, +blockquote, +figure, +fieldset, +legend, +textarea, +pre, +iframe, +hr, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + padding: 0; } + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: 100%; + font-weight: normal; } + +ul { + list-style: none; } + +button, +input, +select, +textarea { + margin: 0; } + +html { + box-sizing: border-box; } + +*, *::before, *::after { + box-sizing: inherit; } + +img, +embed, +iframe, +object, +video { + height: auto; + max-width: 100%; } + +audio { + max-width: 100%; } + +iframe { + border: 0; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + td:not([align]), + th:not([align]) { + text-align: left; } + +html { + background-color: white; + font-size: 16px; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + min-width: 300px; + overflow-x: auto; + overflow-y: scroll; + text-rendering: optimizeLegibility; + text-size-adjust: 100%; } + +article, +aside, +figure, +footer, +header, +hgroup, +section { + display: block; } + +body, +button, +input, +select, +textarea { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif; } + +code, +pre { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: auto; + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace; } + +body { + color: #222222; + font-size: 1em; + font-weight: 400; + line-height: 1.5; } + +a { + color: #2e63b8; + cursor: pointer; + text-decoration: none; } + a strong { + color: currentColor; } + a:hover { + color: #363636; } + +code { + background-color: rgba(0, 0, 0, 0.05); + color: #000000; + font-size: 0.875em; + font-weight: normal; + padding: 0.1em; } + +hr { + background-color: whitesmoke; + border: none; + display: block; + height: 2px; + margin: 1.5rem 0; } + +img { + height: auto; + max-width: 100%; } + +input[type="checkbox"], +input[type="radio"] { + vertical-align: baseline; } + +small { + font-size: 0.875em; } + +span { + font-style: inherit; + font-weight: inherit; } + +strong { + color: #222222; + font-weight: 700; } + +fieldset { + border: none; } + +pre { + -webkit-overflow-scrolling: touch; + background-color: whitesmoke; + color: #222222; + font-size: 0.875em; + overflow-x: auto; + padding: 1.25rem 1.5rem; + white-space: pre; + word-wrap: normal; } + pre code { + background-color: transparent; + color: currentColor; + font-size: 1em; + padding: 0; } + +table td, +table th { + vertical-align: top; } + table td:not([align]), + table th:not([align]) { + text-align: left; } + +table th { + color: #222222; } + +.is-clearfix::after { + clear: both; + content: " "; + display: table; } + +.is-pulled-left { + float: left !important; } + +.is-pulled-right { + float: right !important; } + +.is-clipped { + overflow: hidden !important; } + +.is-size-1 { + font-size: 3rem !important; } + +.is-size-2 { + font-size: 2.5rem !important; } + +.is-size-3 { + font-size: 2rem !important; } + +.is-size-4 { + font-size: 1.5rem !important; } + +.is-size-5 { + font-size: 1.25rem !important; } + +.is-size-6 { + font-size: 1rem !important; } + +.is-size-7, .docstring > section > a.docs-sourcelink { + font-size: 0.75rem !important; } + +@media screen and (max-width: 768px) { + .is-size-1-mobile { + font-size: 3rem !important; } + .is-size-2-mobile { + font-size: 2.5rem !important; } + .is-size-3-mobile { + font-size: 2rem !important; } + .is-size-4-mobile { + font-size: 1.5rem !important; } + .is-size-5-mobile { + font-size: 1.25rem !important; } + .is-size-6-mobile { + font-size: 1rem !important; } + .is-size-7-mobile { + font-size: 0.75rem !important; } } + +@media screen and (min-width: 769px), print { + .is-size-1-tablet { + font-size: 3rem !important; } + .is-size-2-tablet { + font-size: 2.5rem !important; } + .is-size-3-tablet { + font-size: 2rem !important; } + .is-size-4-tablet { + font-size: 1.5rem !important; } + .is-size-5-tablet { + font-size: 1.25rem !important; } + .is-size-6-tablet { + font-size: 1rem !important; } + .is-size-7-tablet { + font-size: 0.75rem !important; } } + +@media screen and (max-width: 1055px) { + .is-size-1-touch { + font-size: 3rem !important; } + .is-size-2-touch { + font-size: 2.5rem !important; } + .is-size-3-touch { + font-size: 2rem !important; } + .is-size-4-touch { + font-size: 1.5rem !important; } + .is-size-5-touch { + font-size: 1.25rem !important; } + .is-size-6-touch { + font-size: 1rem !important; } + .is-size-7-touch { + font-size: 0.75rem !important; } } + +@media screen and (min-width: 1056px) { + .is-size-1-desktop { + font-size: 3rem !important; } + .is-size-2-desktop { + font-size: 2.5rem !important; } + .is-size-3-desktop { + font-size: 2rem !important; } + .is-size-4-desktop { + font-size: 1.5rem !important; } + .is-size-5-desktop { + font-size: 1.25rem !important; } + .is-size-6-desktop { + font-size: 1rem !important; } + .is-size-7-desktop { + font-size: 0.75rem !important; } } + +@media screen and (min-width: 1216px) { + .is-size-1-widescreen { + font-size: 3rem !important; } + .is-size-2-widescreen { + font-size: 2.5rem !important; } + .is-size-3-widescreen { + font-size: 2rem !important; } + .is-size-4-widescreen { + font-size: 1.5rem !important; } + .is-size-5-widescreen { + font-size: 1.25rem !important; } + .is-size-6-widescreen { + font-size: 1rem !important; } + .is-size-7-widescreen { + font-size: 0.75rem !important; } } + +@media screen and (min-width: 1408px) { + .is-size-1-fullhd { + font-size: 3rem !important; } + .is-size-2-fullhd { + font-size: 2.5rem !important; } + .is-size-3-fullhd { + font-size: 2rem !important; } + .is-size-4-fullhd { + font-size: 1.5rem !important; } + .is-size-5-fullhd { + font-size: 1.25rem !important; } + .is-size-6-fullhd { + font-size: 1rem !important; } + .is-size-7-fullhd { + font-size: 0.75rem !important; } } + +.has-text-centered { + text-align: center !important; } + +.has-text-justified { + text-align: justify !important; } + +.has-text-left { + text-align: left !important; } + +.has-text-right { + text-align: right !important; } + +@media screen and (max-width: 768px) { + .has-text-centered-mobile { + text-align: center !important; } } + +@media screen and (min-width: 769px), print { + .has-text-centered-tablet { + text-align: center !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-centered-tablet-only { + text-align: center !important; } } + +@media screen and (max-width: 1055px) { + .has-text-centered-touch { + text-align: center !important; } } + +@media screen and (min-width: 1056px) { + .has-text-centered-desktop { + text-align: center !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-centered-desktop-only { + text-align: center !important; } } + +@media screen and (min-width: 1216px) { + .has-text-centered-widescreen { + text-align: center !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-centered-widescreen-only { + text-align: center !important; } } + +@media screen and (min-width: 1408px) { + .has-text-centered-fullhd { + text-align: center !important; } } + +@media screen and (max-width: 768px) { + .has-text-justified-mobile { + text-align: justify !important; } } + +@media screen and (min-width: 769px), print { + .has-text-justified-tablet { + text-align: justify !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-justified-tablet-only { + text-align: justify !important; } } + +@media screen and (max-width: 1055px) { + .has-text-justified-touch { + text-align: justify !important; } } + +@media screen and (min-width: 1056px) { + .has-text-justified-desktop { + text-align: justify !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-justified-desktop-only { + text-align: justify !important; } } + +@media screen and (min-width: 1216px) { + .has-text-justified-widescreen { + text-align: justify !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-justified-widescreen-only { + text-align: justify !important; } } + +@media screen and (min-width: 1408px) { + .has-text-justified-fullhd { + text-align: justify !important; } } + +@media screen and (max-width: 768px) { + .has-text-left-mobile { + text-align: left !important; } } + +@media screen and (min-width: 769px), print { + .has-text-left-tablet { + text-align: left !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-left-tablet-only { + text-align: left !important; } } + +@media screen and (max-width: 1055px) { + .has-text-left-touch { + text-align: left !important; } } + +@media screen and (min-width: 1056px) { + .has-text-left-desktop { + text-align: left !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-left-desktop-only { + text-align: left !important; } } + +@media screen and (min-width: 1216px) { + .has-text-left-widescreen { + text-align: left !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-left-widescreen-only { + text-align: left !important; } } + +@media screen and (min-width: 1408px) { + .has-text-left-fullhd { + text-align: left !important; } } + +@media screen and (max-width: 768px) { + .has-text-right-mobile { + text-align: right !important; } } + +@media screen and (min-width: 769px), print { + .has-text-right-tablet { + text-align: right !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .has-text-right-tablet-only { + text-align: right !important; } } + +@media screen and (max-width: 1055px) { + .has-text-right-touch { + text-align: right !important; } } + +@media screen and (min-width: 1056px) { + .has-text-right-desktop { + text-align: right !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .has-text-right-desktop-only { + text-align: right !important; } } + +@media screen and (min-width: 1216px) { + .has-text-right-widescreen { + text-align: right !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .has-text-right-widescreen-only { + text-align: right !important; } } + +@media screen and (min-width: 1408px) { + .has-text-right-fullhd { + text-align: right !important; } } + +.is-capitalized { + text-transform: capitalize !important; } + +.is-lowercase { + text-transform: lowercase !important; } + +.is-uppercase { + text-transform: uppercase !important; } + +.is-italic { + font-style: italic !important; } + +.has-text-white { + color: white !important; } + +a.has-text-white:hover, a.has-text-white:focus { + color: #e6e6e6 !important; } + +.has-background-white { + background-color: white !important; } + +.has-text-black { + color: #0a0a0a !important; } + +a.has-text-black:hover, a.has-text-black:focus { + color: black !important; } + +.has-background-black { + background-color: #0a0a0a !important; } + +.has-text-light { + color: whitesmoke !important; } + +a.has-text-light:hover, a.has-text-light:focus { + color: #dbdbdb !important; } + +.has-background-light { + background-color: whitesmoke !important; } + +.has-text-dark { + color: #363636 !important; } + +a.has-text-dark:hover, a.has-text-dark:focus { + color: #1c1c1c !important; } + +.has-background-dark { + background-color: #363636 !important; } + +.has-text-primary { + color: #4eb5de !important; } + +a.has-text-primary:hover, a.has-text-primary:focus { + color: #27a1d2 !important; } + +.has-background-primary { + background-color: #4eb5de !important; } + +.has-text-link { + color: #2e63b8 !important; } + +a.has-text-link:hover, a.has-text-link:focus { + color: #244d8f !important; } + +.has-background-link { + background-color: #2e63b8 !important; } + +.has-text-info { + color: #209cee !important; } + +a.has-text-info:hover, a.has-text-info:focus { + color: #1081cb !important; } + +.has-background-info { + background-color: #209cee !important; } + +.has-text-success { + color: #22c35b !important; } + +a.has-text-success:hover, a.has-text-success:focus { + color: #1a9847 !important; } + +.has-background-success { + background-color: #22c35b !important; } + +.has-text-warning { + color: #ffdd57 !important; } + +a.has-text-warning:hover, a.has-text-warning:focus { + color: #ffd324 !important; } + +.has-background-warning { + background-color: #ffdd57 !important; } + +.has-text-danger { + color: #da0b00 !important; } + +a.has-text-danger:hover, a.has-text-danger:focus { + color: #a70800 !important; } + +.has-background-danger { + background-color: #da0b00 !important; } + +.has-text-black-bis { + color: #121212 !important; } + +.has-background-black-bis { + background-color: #121212 !important; } + +.has-text-black-ter { + color: #242424 !important; } + +.has-background-black-ter { + background-color: #242424 !important; } + +.has-text-grey-darker { + color: #363636 !important; } + +.has-background-grey-darker { + background-color: #363636 !important; } + +.has-text-grey-dark { + color: #4a4a4a !important; } + +.has-background-grey-dark { + background-color: #4a4a4a !important; } + +.has-text-grey { + color: #6b6b6b !important; } + +.has-background-grey { + background-color: #6b6b6b !important; } + +.has-text-grey-light { + color: #b5b5b5 !important; } + +.has-background-grey-light { + background-color: #b5b5b5 !important; } + +.has-text-grey-lighter { + color: #dbdbdb !important; } + +.has-background-grey-lighter { + background-color: #dbdbdb !important; } + +.has-text-white-ter { + color: whitesmoke !important; } + +.has-background-white-ter { + background-color: whitesmoke !important; } + +.has-text-white-bis { + color: #fafafa !important; } + +.has-background-white-bis { + background-color: #fafafa !important; } + +.has-text-weight-light { + font-weight: 300 !important; } + +.has-text-weight-normal { + font-weight: 400 !important; } + +.has-text-weight-medium { + font-weight: 500 !important; } + +.has-text-weight-semibold { + font-weight: 600 !important; } + +.has-text-weight-bold { + font-weight: 700 !important; } + +.is-family-primary { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-secondary { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-sans-serif { + font-family: "Lato Medium", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "Helvetica", "Arial", sans-serif !important; } + +.is-family-monospace { + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace !important; } + +.is-family-code { + font-family: "JuliaMono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "DejaVu Sans Mono", monospace !important; } + +.is-block { + display: block !important; } + +@media screen and (max-width: 768px) { + .is-block-mobile { + display: block !important; } } + +@media screen and (min-width: 769px), print { + .is-block-tablet { + display: block !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-block-tablet-only { + display: block !important; } } + +@media screen and (max-width: 1055px) { + .is-block-touch { + display: block !important; } } + +@media screen and (min-width: 1056px) { + .is-block-desktop { + display: block !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-block-desktop-only { + display: block !important; } } + +@media screen and (min-width: 1216px) { + .is-block-widescreen { + display: block !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-block-widescreen-only { + display: block !important; } } + +@media screen and (min-width: 1408px) { + .is-block-fullhd { + display: block !important; } } + +.is-flex { + display: flex !important; } + +@media screen and (max-width: 768px) { + .is-flex-mobile { + display: flex !important; } } + +@media screen and (min-width: 769px), print { + .is-flex-tablet { + display: flex !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-flex-tablet-only { + display: flex !important; } } + +@media screen and (max-width: 1055px) { + .is-flex-touch { + display: flex !important; } } + +@media screen and (min-width: 1056px) { + .is-flex-desktop { + display: flex !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-flex-desktop-only { + display: flex !important; } } + +@media screen and (min-width: 1216px) { + .is-flex-widescreen { + display: flex !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-flex-widescreen-only { + display: flex !important; } } + +@media screen and (min-width: 1408px) { + .is-flex-fullhd { + display: flex !important; } } + +.is-inline { + display: inline !important; } + +@media screen and (max-width: 768px) { + .is-inline-mobile { + display: inline !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-tablet { + display: inline !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-tablet-only { + display: inline !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-touch { + display: inline !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-desktop { + display: inline !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-desktop-only { + display: inline !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-widescreen { + display: inline !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-widescreen-only { + display: inline !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-fullhd { + display: inline !important; } } + +.is-inline-block { + display: inline-block !important; } + +@media screen and (max-width: 768px) { + .is-inline-block-mobile { + display: inline-block !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-block-tablet { + display: inline-block !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-block-tablet-only { + display: inline-block !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-block-touch { + display: inline-block !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-block-desktop { + display: inline-block !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-block-desktop-only { + display: inline-block !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-block-widescreen { + display: inline-block !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-block-widescreen-only { + display: inline-block !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-block-fullhd { + display: inline-block !important; } } + +.is-inline-flex { + display: inline-flex !important; } + +@media screen and (max-width: 768px) { + .is-inline-flex-mobile { + display: inline-flex !important; } } + +@media screen and (min-width: 769px), print { + .is-inline-flex-tablet { + display: inline-flex !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-inline-flex-tablet-only { + display: inline-flex !important; } } + +@media screen and (max-width: 1055px) { + .is-inline-flex-touch { + display: inline-flex !important; } } + +@media screen and (min-width: 1056px) { + .is-inline-flex-desktop { + display: inline-flex !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-inline-flex-desktop-only { + display: inline-flex !important; } } + +@media screen and (min-width: 1216px) { + .is-inline-flex-widescreen { + display: inline-flex !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-inline-flex-widescreen-only { + display: inline-flex !important; } } + +@media screen and (min-width: 1408px) { + .is-inline-flex-fullhd { + display: inline-flex !important; } } + +.is-hidden { + display: none !important; } + +.is-sr-only { + border: none !important; + clip: rect(0, 0, 0, 0) !important; + height: 0.01em !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + white-space: nowrap !important; + width: 0.01em !important; } + +@media screen and (max-width: 768px) { + .is-hidden-mobile { + display: none !important; } } + +@media screen and (min-width: 769px), print { + .is-hidden-tablet { + display: none !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-hidden-tablet-only { + display: none !important; } } + +@media screen and (max-width: 1055px) { + .is-hidden-touch { + display: none !important; } } + +@media screen and (min-width: 1056px) { + .is-hidden-desktop { + display: none !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-hidden-desktop-only { + display: none !important; } } + +@media screen and (min-width: 1216px) { + .is-hidden-widescreen { + display: none !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-hidden-widescreen-only { + display: none !important; } } + +@media screen and (min-width: 1408px) { + .is-hidden-fullhd { + display: none !important; } } + +.is-invisible { + visibility: hidden !important; } + +@media screen and (max-width: 768px) { + .is-invisible-mobile { + visibility: hidden !important; } } + +@media screen and (min-width: 769px), print { + .is-invisible-tablet { + visibility: hidden !important; } } + +@media screen and (min-width: 769px) and (max-width: 1055px) { + .is-invisible-tablet-only { + visibility: hidden !important; } } + +@media screen and (max-width: 1055px) { + .is-invisible-touch { + visibility: hidden !important; } } + +@media screen and (min-width: 1056px) { + .is-invisible-desktop { + visibility: hidden !important; } } + +@media screen and (min-width: 1056px) and (max-width: 1215px) { + .is-invisible-desktop-only { + visibility: hidden !important; } } + +@media screen and (min-width: 1216px) { + .is-invisible-widescreen { + visibility: hidden !important; } } + +@media screen and (min-width: 1216px) and (max-width: 1407px) { + .is-invisible-widescreen-only { + visibility: hidden !important; } } + +@media screen and (min-width: 1408px) { + .is-invisible-fullhd { + visibility: hidden !important; } } + +.is-marginless { + margin: 0 !important; } + +.is-paddingless { + padding: 0 !important; } + +.is-radiusless { + border-radius: 0 !important; } + +.is-shadowless { + box-shadow: none !important; } + +.is-relative { + position: relative !important; } + +.box { + background-color: white; + border-radius: 6px; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + color: #222222; + display: block; + padding: 1.25rem; } + +a.box:hover, a.box:focus { + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px #2e63b8; } + +a.box:active { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #2e63b8; } + +.button { + background-color: white; + border-color: #dbdbdb; + border-width: 1px; + color: #363636; + cursor: pointer; + justify-content: center; + padding-bottom: calc(0.375em - 1px); + padding-left: 0.75em; + padding-right: 0.75em; + padding-top: calc(0.375em - 1px); + text-align: center; + white-space: nowrap; } + .button strong { + color: inherit; } + .button .icon, .button .icon.is-small, .button #documenter .docs-sidebar form.docs-search > input.icon, #documenter .docs-sidebar .button form.docs-search > input.icon, .button .icon.is-medium, .button .icon.is-large { + height: 1.5em; + width: 1.5em; } + .button .icon:first-child:not(:last-child) { + margin-left: calc(-0.375em - 1px); + margin-right: 0.1875em; } + .button .icon:last-child:not(:first-child) { + margin-left: 0.1875em; + margin-right: calc(-0.375em - 1px); } + .button .icon:first-child:last-child { + margin-left: calc(-0.375em - 1px); + margin-right: calc(-0.375em - 1px); } + .button:hover, .button.is-hovered { + border-color: #b5b5b5; + color: #363636; } + .button:focus, .button.is-focused { + border-color: #3c5dcd; + color: #363636; } + .button:focus:not(:active), .button.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(46, 99, 184, 0.25); } + .button:active, .button.is-active { + border-color: #4a4a4a; + color: #363636; } + .button.is-text { + background-color: transparent; + border-color: transparent; + color: #222222; + text-decoration: underline; } + .button.is-text:hover, .button.is-text.is-hovered, .button.is-text:focus, .button.is-text.is-focused { + background-color: whitesmoke; + color: #222222; } + .button.is-text:active, .button.is-text.is-active { + background-color: #e8e8e8; + color: #222222; } + .button.is-text[disabled], fieldset[disabled] .button.is-text { + background-color: transparent; + border-color: transparent; + box-shadow: none; } + .button.is-white { + background-color: white; + border-color: transparent; + color: #0a0a0a; } + .button.is-white:hover, .button.is-white.is-hovered { + background-color: #f9f9f9; + border-color: transparent; + color: #0a0a0a; } + .button.is-white:focus, .button.is-white.is-focused { + border-color: transparent; + color: #0a0a0a; } + .button.is-white:focus:not(:active), .button.is-white.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + .button.is-white:active, .button.is-white.is-active { + background-color: #f2f2f2; + border-color: transparent; + color: #0a0a0a; } + .button.is-white[disabled], fieldset[disabled] .button.is-white { + background-color: white; + border-color: transparent; + box-shadow: none; } + .button.is-white.is-inverted { + background-color: #0a0a0a; + color: white; } + .button.is-white.is-inverted:hover, .button.is-white.is-inverted.is-hovered { + background-color: black; } + .button.is-white.is-inverted[disabled], fieldset[disabled] .button.is-white.is-inverted { + background-color: #0a0a0a; + border-color: transparent; + box-shadow: none; + color: white; } + .button.is-white.is-loading::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + .button.is-white.is-outlined { + background-color: transparent; + border-color: white; + color: white; } + .button.is-white.is-outlined:hover, .button.is-white.is-outlined.is-hovered, .button.is-white.is-outlined:focus, .button.is-white.is-outlined.is-focused { + background-color: white; + border-color: white; + color: #0a0a0a; } + .button.is-white.is-outlined.is-loading::after { + border-color: transparent transparent white white !important; } + .button.is-white.is-outlined.is-loading:hover::after, .button.is-white.is-outlined.is-loading.is-hovered::after, .button.is-white.is-outlined.is-loading:focus::after, .button.is-white.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + .button.is-white.is-outlined[disabled], fieldset[disabled] .button.is-white.is-outlined { + background-color: transparent; + border-color: white; + box-shadow: none; + color: white; } + .button.is-white.is-inverted.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + color: #0a0a0a; } + .button.is-white.is-inverted.is-outlined:hover, .button.is-white.is-inverted.is-outlined.is-hovered, .button.is-white.is-inverted.is-outlined:focus, .button.is-white.is-inverted.is-outlined.is-focused { + background-color: #0a0a0a; + color: white; } + .button.is-white.is-inverted.is-outlined.is-loading:hover::after, .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-white.is-inverted.is-outlined.is-loading:focus::after, .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent white white !important; } + .button.is-white.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-white.is-inverted.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + box-shadow: none; + color: #0a0a0a; } + .button.is-black { + background-color: #0a0a0a; + border-color: transparent; + color: white; } + .button.is-black:hover, .button.is-black.is-hovered { + background-color: #040404; + border-color: transparent; + color: white; } + .button.is-black:focus, .button.is-black.is-focused { + border-color: transparent; + color: white; } + .button.is-black:focus:not(:active), .button.is-black.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + .button.is-black:active, .button.is-black.is-active { + background-color: black; + border-color: transparent; + color: white; } + .button.is-black[disabled], fieldset[disabled] .button.is-black { + background-color: #0a0a0a; + border-color: transparent; + box-shadow: none; } + .button.is-black.is-inverted { + background-color: white; + color: #0a0a0a; } + .button.is-black.is-inverted:hover, .button.is-black.is-inverted.is-hovered { + background-color: #f2f2f2; } + .button.is-black.is-inverted[disabled], fieldset[disabled] .button.is-black.is-inverted { + background-color: white; + border-color: transparent; + box-shadow: none; + color: #0a0a0a; } + .button.is-black.is-loading::after { + border-color: transparent transparent white white !important; } + .button.is-black.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + color: #0a0a0a; } + .button.is-black.is-outlined:hover, .button.is-black.is-outlined.is-hovered, .button.is-black.is-outlined:focus, .button.is-black.is-outlined.is-focused { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + .button.is-black.is-outlined.is-loading::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + .button.is-black.is-outlined.is-loading:hover::after, .button.is-black.is-outlined.is-loading.is-hovered::after, .button.is-black.is-outlined.is-loading:focus::after, .button.is-black.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent white white !important; } + .button.is-black.is-outlined[disabled], fieldset[disabled] .button.is-black.is-outlined { + background-color: transparent; + border-color: #0a0a0a; + box-shadow: none; + color: #0a0a0a; } + .button.is-black.is-inverted.is-outlined { + background-color: transparent; + border-color: white; + color: white; } + .button.is-black.is-inverted.is-outlined:hover, .button.is-black.is-inverted.is-outlined.is-hovered, .button.is-black.is-inverted.is-outlined:focus, .button.is-black.is-inverted.is-outlined.is-focused { + background-color: white; + color: #0a0a0a; } + .button.is-black.is-inverted.is-outlined.is-loading:hover::after, .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-black.is-inverted.is-outlined.is-loading:focus::after, .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #0a0a0a #0a0a0a !important; } + .button.is-black.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-black.is-inverted.is-outlined { + background-color: transparent; + border-color: white; + box-shadow: none; + color: white; } + .button.is-light { + background-color: whitesmoke; + border-color: transparent; + color: #363636; } + .button.is-light:hover, .button.is-light.is-hovered { + background-color: #eeeeee; + border-color: transparent; + color: #363636; } + .button.is-light:focus, .button.is-light.is-focused { + border-color: transparent; + color: #363636; } + .button.is-light:focus:not(:active), .button.is-light.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } + .button.is-light:active, .button.is-light.is-active { + background-color: #e8e8e8; + border-color: transparent; + color: #363636; } + .button.is-light[disabled], fieldset[disabled] .button.is-light { + background-color: whitesmoke; + border-color: transparent; + box-shadow: none; } + .button.is-light.is-inverted { + background-color: #363636; + color: whitesmoke; } + .button.is-light.is-inverted:hover, .button.is-light.is-inverted.is-hovered { + background-color: #292929; } + .button.is-light.is-inverted[disabled], fieldset[disabled] .button.is-light.is-inverted { + background-color: #363636; + border-color: transparent; + box-shadow: none; + color: whitesmoke; } + .button.is-light.is-loading::after { + border-color: transparent transparent #363636 #363636 !important; } + .button.is-light.is-outlined { + background-color: transparent; + border-color: whitesmoke; + color: whitesmoke; } + .button.is-light.is-outlined:hover, .button.is-light.is-outlined.is-hovered, .button.is-light.is-outlined:focus, .button.is-light.is-outlined.is-focused { + background-color: whitesmoke; + border-color: whitesmoke; + color: #363636; } + .button.is-light.is-outlined.is-loading::after { + border-color: transparent transparent whitesmoke whitesmoke !important; } + .button.is-light.is-outlined.is-loading:hover::after, .button.is-light.is-outlined.is-loading.is-hovered::after, .button.is-light.is-outlined.is-loading:focus::after, .button.is-light.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #363636 #363636 !important; } + .button.is-light.is-outlined[disabled], fieldset[disabled] .button.is-light.is-outlined { + background-color: transparent; + border-color: whitesmoke; + box-shadow: none; + color: whitesmoke; } + .button.is-light.is-inverted.is-outlined { + background-color: transparent; + border-color: #363636; + color: #363636; } + .button.is-light.is-inverted.is-outlined:hover, .button.is-light.is-inverted.is-outlined.is-hovered, .button.is-light.is-inverted.is-outlined:focus, .button.is-light.is-inverted.is-outlined.is-focused { + background-color: #363636; + color: whitesmoke; } + .button.is-light.is-inverted.is-outlined.is-loading:hover::after, .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-light.is-inverted.is-outlined.is-loading:focus::after, .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent whitesmoke whitesmoke !important; } + .button.is-light.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-light.is-inverted.is-outlined { + background-color: transparent; + border-color: #363636; + box-shadow: none; + color: #363636; } + .button.is-dark, .content kbd.button { + background-color: #363636; + border-color: transparent; + color: whitesmoke; } + .button.is-dark:hover, .content kbd.button:hover, .button.is-dark.is-hovered, .content kbd.button.is-hovered { + background-color: #2f2f2f; + border-color: transparent; + color: whitesmoke; } + .button.is-dark:focus, .content kbd.button:focus, .button.is-dark.is-focused, .content kbd.button.is-focused { + border-color: transparent; + color: whitesmoke; } + .button.is-dark:focus:not(:active), .content kbd.button:focus:not(:active), .button.is-dark.is-focused:not(:active), .content kbd.button.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } + .button.is-dark:active, .content kbd.button:active, .button.is-dark.is-active, .content kbd.button.is-active { + background-color: #292929; + border-color: transparent; + color: whitesmoke; } + .button.is-dark[disabled], .content kbd.button[disabled], fieldset[disabled] .button.is-dark, fieldset[disabled] .content kbd.button, .content fieldset[disabled] kbd.button { + background-color: #363636; + border-color: transparent; + box-shadow: none; } + .button.is-dark.is-inverted, .content kbd.button.is-inverted { + background-color: whitesmoke; + color: #363636; } + .button.is-dark.is-inverted:hover, .content kbd.button.is-inverted:hover, .button.is-dark.is-inverted.is-hovered, .content kbd.button.is-inverted.is-hovered { + background-color: #e8e8e8; } + .button.is-dark.is-inverted[disabled], .content kbd.button.is-inverted[disabled], fieldset[disabled] .button.is-dark.is-inverted, fieldset[disabled] .content kbd.button.is-inverted, .content fieldset[disabled] kbd.button.is-inverted { + background-color: whitesmoke; + border-color: transparent; + box-shadow: none; + color: #363636; } + .button.is-dark.is-loading::after, .content kbd.button.is-loading::after { + border-color: transparent transparent whitesmoke whitesmoke !important; } + .button.is-dark.is-outlined, .content kbd.button.is-outlined { + background-color: transparent; + border-color: #363636; + color: #363636; } + .button.is-dark.is-outlined:hover, .content kbd.button.is-outlined:hover, .button.is-dark.is-outlined.is-hovered, .content kbd.button.is-outlined.is-hovered, .button.is-dark.is-outlined:focus, .content kbd.button.is-outlined:focus, .button.is-dark.is-outlined.is-focused, .content kbd.button.is-outlined.is-focused { + background-color: #363636; + border-color: #363636; + color: whitesmoke; } + .button.is-dark.is-outlined.is-loading::after, .content kbd.button.is-outlined.is-loading::after { + border-color: transparent transparent #363636 #363636 !important; } + .button.is-dark.is-outlined.is-loading:hover::after, .content kbd.button.is-outlined.is-loading:hover::after, .button.is-dark.is-outlined.is-loading.is-hovered::after, .content kbd.button.is-outlined.is-loading.is-hovered::after, .button.is-dark.is-outlined.is-loading:focus::after, .content kbd.button.is-outlined.is-loading:focus::after, .button.is-dark.is-outlined.is-loading.is-focused::after, .content kbd.button.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent whitesmoke whitesmoke !important; } + .button.is-dark.is-outlined[disabled], .content kbd.button.is-outlined[disabled], fieldset[disabled] .button.is-dark.is-outlined, fieldset[disabled] .content kbd.button.is-outlined, .content fieldset[disabled] kbd.button.is-outlined { + background-color: transparent; + border-color: #363636; + box-shadow: none; + color: #363636; } + .button.is-dark.is-inverted.is-outlined, .content kbd.button.is-inverted.is-outlined { + background-color: transparent; + border-color: whitesmoke; + color: whitesmoke; } + .button.is-dark.is-inverted.is-outlined:hover, .content kbd.button.is-inverted.is-outlined:hover, .button.is-dark.is-inverted.is-outlined.is-hovered, .content kbd.button.is-inverted.is-outlined.is-hovered, .button.is-dark.is-inverted.is-outlined:focus, .content kbd.button.is-inverted.is-outlined:focus, .button.is-dark.is-inverted.is-outlined.is-focused, .content kbd.button.is-inverted.is-outlined.is-focused { + background-color: whitesmoke; + color: #363636; } + .button.is-dark.is-inverted.is-outlined.is-loading:hover::after, .content kbd.button.is-inverted.is-outlined.is-loading:hover::after, .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after, .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-dark.is-inverted.is-outlined.is-loading:focus::after, .content kbd.button.is-inverted.is-outlined.is-loading:focus::after, .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after, .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #363636 #363636 !important; } + .button.is-dark.is-inverted.is-outlined[disabled], .content kbd.button.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-dark.is-inverted.is-outlined, fieldset[disabled] .content kbd.button.is-inverted.is-outlined, .content fieldset[disabled] kbd.button.is-inverted.is-outlined { + background-color: transparent; + border-color: whitesmoke; + box-shadow: none; + color: whitesmoke; } + .button.is-primary, .docstring > section > a.button.docs-sourcelink { + background-color: #4eb5de; + border-color: transparent; + color: #fff; } + .button.is-primary:hover, .docstring > section > a.button.docs-sourcelink:hover, .button.is-primary.is-hovered, .docstring > section > a.button.is-hovered.docs-sourcelink { + background-color: #43b1dc; + border-color: transparent; + color: #fff; } + .button.is-primary:focus, .docstring > section > a.button.docs-sourcelink:focus, .button.is-primary.is-focused, .docstring > section > a.button.is-focused.docs-sourcelink { + border-color: transparent; + color: #fff; } + .button.is-primary:focus:not(:active), .docstring > section > a.button.docs-sourcelink:focus:not(:active), .button.is-primary.is-focused:not(:active), .docstring > section > a.button.is-focused.docs-sourcelink:not(:active) { + box-shadow: 0 0 0 0.125em rgba(78, 181, 222, 0.25); } + .button.is-primary:active, .docstring > section > a.button.docs-sourcelink:active, .button.is-primary.is-active, .docstring > section > a.button.is-active.docs-sourcelink { + background-color: #39acda; + border-color: transparent; + color: #fff; } + .button.is-primary[disabled], .docstring > section > a.button.docs-sourcelink[disabled], fieldset[disabled] .button.is-primary, fieldset[disabled] .docstring > section > a.button.docs-sourcelink { + background-color: #4eb5de; + border-color: transparent; + box-shadow: none; } + .button.is-primary.is-inverted, .docstring > section > a.button.is-inverted.docs-sourcelink { + background-color: #fff; + color: #4eb5de; } + .button.is-primary.is-inverted:hover, .docstring > section > a.button.is-inverted.docs-sourcelink:hover, .button.is-primary.is-inverted.is-hovered, .docstring > section > a.button.is-inverted.is-hovered.docs-sourcelink { + background-color: #f2f2f2; } + .button.is-primary.is-inverted[disabled], .docstring > section > a.button.is-inverted.docs-sourcelink[disabled], fieldset[disabled] .button.is-primary.is-inverted, fieldset[disabled] .docstring > section > a.button.is-inverted.docs-sourcelink { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #4eb5de; } + .button.is-primary.is-loading::after, .docstring > section > a.button.is-loading.docs-sourcelink::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-primary.is-outlined, .docstring > section > a.button.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #4eb5de; + color: #4eb5de; } + .button.is-primary.is-outlined:hover, .docstring > section > a.button.is-outlined.docs-sourcelink:hover, .button.is-primary.is-outlined.is-hovered, .docstring > section > a.button.is-outlined.is-hovered.docs-sourcelink, .button.is-primary.is-outlined:focus, .docstring > section > a.button.is-outlined.docs-sourcelink:focus, .button.is-primary.is-outlined.is-focused, .docstring > section > a.button.is-outlined.is-focused.docs-sourcelink { + background-color: #4eb5de; + border-color: #4eb5de; + color: #fff; } + .button.is-primary.is-outlined.is-loading::after, .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink::after { + border-color: transparent transparent #4eb5de #4eb5de !important; } + .button.is-primary.is-outlined.is-loading:hover::after, .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink:hover::after, .button.is-primary.is-outlined.is-loading.is-hovered::after, .docstring > section > a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after, .button.is-primary.is-outlined.is-loading:focus::after, .docstring > section > a.button.is-outlined.is-loading.docs-sourcelink:focus::after, .button.is-primary.is-outlined.is-loading.is-focused::after, .docstring > section > a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-primary.is-outlined[disabled], .docstring > section > a.button.is-outlined.docs-sourcelink[disabled], fieldset[disabled] .button.is-primary.is-outlined, fieldset[disabled] .docstring > section > a.button.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #4eb5de; + box-shadow: none; + color: #4eb5de; } + .button.is-primary.is-inverted.is-outlined, .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #fff; + color: #fff; } + .button.is-primary.is-inverted.is-outlined:hover, .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink:hover, .button.is-primary.is-inverted.is-outlined.is-hovered, .docstring > section > a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink, .button.is-primary.is-inverted.is-outlined:focus, .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink:focus, .button.is-primary.is-inverted.is-outlined.is-focused, .docstring > section > a.button.is-inverted.is-outlined.is-focused.docs-sourcelink { + background-color: #fff; + color: #4eb5de; } + .button.is-primary.is-inverted.is-outlined.is-loading:hover::after, .docstring > section > a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after, .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after, .docstring > section > a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after, .button.is-primary.is-inverted.is-outlined.is-loading:focus::after, .docstring > section > a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after, .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after, .docstring > section > a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after { + border-color: transparent transparent #4eb5de #4eb5de !important; } + .button.is-primary.is-inverted.is-outlined[disabled], .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink[disabled], fieldset[disabled] .button.is-primary.is-inverted.is-outlined, fieldset[disabled] .docstring > section > a.button.is-inverted.is-outlined.docs-sourcelink { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + .button.is-link { + background-color: #2e63b8; + border-color: transparent; + color: #fff; } + .button.is-link:hover, .button.is-link.is-hovered { + background-color: #2b5eae; + border-color: transparent; + color: #fff; } + .button.is-link:focus, .button.is-link.is-focused { + border-color: transparent; + color: #fff; } + .button.is-link:focus:not(:active), .button.is-link.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(46, 99, 184, 0.25); } + .button.is-link:active, .button.is-link.is-active { + background-color: #2958a4; + border-color: transparent; + color: #fff; } + .button.is-link[disabled], fieldset[disabled] .button.is-link { + background-color: #2e63b8; + border-color: transparent; + box-shadow: none; } + .button.is-link.is-inverted { + background-color: #fff; + color: #2e63b8; } + .button.is-link.is-inverted:hover, .button.is-link.is-inverted.is-hovered { + background-color: #f2f2f2; } + .button.is-link.is-inverted[disabled], fieldset[disabled] .button.is-link.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #2e63b8; } + .button.is-link.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-link.is-outlined { + background-color: transparent; + border-color: #2e63b8; + color: #2e63b8; } + .button.is-link.is-outlined:hover, .button.is-link.is-outlined.is-hovered, .button.is-link.is-outlined:focus, .button.is-link.is-outlined.is-focused { + background-color: #2e63b8; + border-color: #2e63b8; + color: #fff; } + .button.is-link.is-outlined.is-loading::after { + border-color: transparent transparent #2e63b8 #2e63b8 !important; } + .button.is-link.is-outlined.is-loading:hover::after, .button.is-link.is-outlined.is-loading.is-hovered::after, .button.is-link.is-outlined.is-loading:focus::after, .button.is-link.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-link.is-outlined[disabled], fieldset[disabled] .button.is-link.is-outlined { + background-color: transparent; + border-color: #2e63b8; + box-shadow: none; + color: #2e63b8; } + .button.is-link.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + .button.is-link.is-inverted.is-outlined:hover, .button.is-link.is-inverted.is-outlined.is-hovered, .button.is-link.is-inverted.is-outlined:focus, .button.is-link.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #2e63b8; } + .button.is-link.is-inverted.is-outlined.is-loading:hover::after, .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-link.is-inverted.is-outlined.is-loading:focus::after, .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #2e63b8 #2e63b8 !important; } + .button.is-link.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-link.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + .button.is-info { + background-color: #209cee; + border-color: transparent; + color: #fff; } + .button.is-info:hover, .button.is-info.is-hovered { + background-color: #1497ed; + border-color: transparent; + color: #fff; } + .button.is-info:focus, .button.is-info.is-focused { + border-color: transparent; + color: #fff; } + .button.is-info:focus:not(:active), .button.is-info.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } + .button.is-info:active, .button.is-info.is-active { + background-color: #1190e3; + border-color: transparent; + color: #fff; } + .button.is-info[disabled], fieldset[disabled] .button.is-info { + background-color: #209cee; + border-color: transparent; + box-shadow: none; } + .button.is-info.is-inverted { + background-color: #fff; + color: #209cee; } + .button.is-info.is-inverted:hover, .button.is-info.is-inverted.is-hovered { + background-color: #f2f2f2; } + .button.is-info.is-inverted[disabled], fieldset[disabled] .button.is-info.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #209cee; } + .button.is-info.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-info.is-outlined { + background-color: transparent; + border-color: #209cee; + color: #209cee; } + .button.is-info.is-outlined:hover, .button.is-info.is-outlined.is-hovered, .button.is-info.is-outlined:focus, .button.is-info.is-outlined.is-focused { + background-color: #209cee; + border-color: #209cee; + color: #fff; } + .button.is-info.is-outlined.is-loading::after { + border-color: transparent transparent #209cee #209cee !important; } + .button.is-info.is-outlined.is-loading:hover::after, .button.is-info.is-outlined.is-loading.is-hovered::after, .button.is-info.is-outlined.is-loading:focus::after, .button.is-info.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-info.is-outlined[disabled], fieldset[disabled] .button.is-info.is-outlined { + background-color: transparent; + border-color: #209cee; + box-shadow: none; + color: #209cee; } + .button.is-info.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + .button.is-info.is-inverted.is-outlined:hover, .button.is-info.is-inverted.is-outlined.is-hovered, .button.is-info.is-inverted.is-outlined:focus, .button.is-info.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #209cee; } + .button.is-info.is-inverted.is-outlined.is-loading:hover::after, .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-info.is-inverted.is-outlined.is-loading:focus::after, .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #209cee #209cee !important; } + .button.is-info.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-info.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + .button.is-success { + background-color: #22c35b; + border-color: transparent; + color: #fff; } + .button.is-success:hover, .button.is-success.is-hovered { + background-color: #20b856; + border-color: transparent; + color: #fff; } + .button.is-success:focus, .button.is-success.is-focused { + border-color: transparent; + color: #fff; } + .button.is-success:focus:not(:active), .button.is-success.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(34, 195, 91, 0.25); } + .button.is-success:active, .button.is-success.is-active { + background-color: #1ead51; + border-color: transparent; + color: #fff; } + .button.is-success[disabled], fieldset[disabled] .button.is-success { + background-color: #22c35b; + border-color: transparent; + box-shadow: none; } + .button.is-success.is-inverted { + background-color: #fff; + color: #22c35b; } + .button.is-success.is-inverted:hover, .button.is-success.is-inverted.is-hovered { + background-color: #f2f2f2; } + .button.is-success.is-inverted[disabled], fieldset[disabled] .button.is-success.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #22c35b; } + .button.is-success.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-success.is-outlined { + background-color: transparent; + border-color: #22c35b; + color: #22c35b; } + .button.is-success.is-outlined:hover, .button.is-success.is-outlined.is-hovered, .button.is-success.is-outlined:focus, .button.is-success.is-outlined.is-focused { + background-color: #22c35b; + border-color: #22c35b; + color: #fff; } + .button.is-success.is-outlined.is-loading::after { + border-color: transparent transparent #22c35b #22c35b !important; } + .button.is-success.is-outlined.is-loading:hover::after, .button.is-success.is-outlined.is-loading.is-hovered::after, .button.is-success.is-outlined.is-loading:focus::after, .button.is-success.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-success.is-outlined[disabled], fieldset[disabled] .button.is-success.is-outlined { + background-color: transparent; + border-color: #22c35b; + box-shadow: none; + color: #22c35b; } + .button.is-success.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + .button.is-success.is-inverted.is-outlined:hover, .button.is-success.is-inverted.is-outlined.is-hovered, .button.is-success.is-inverted.is-outlined:focus, .button.is-success.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #22c35b; } + .button.is-success.is-inverted.is-outlined.is-loading:hover::after, .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-success.is-inverted.is-outlined.is-loading:focus::after, .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #22c35b #22c35b !important; } + .button.is-success.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-success.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + .button.is-warning { + background-color: #ffdd57; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .button.is-warning:hover, .button.is-warning.is-hovered { + background-color: #ffda4a; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .button.is-warning:focus, .button.is-warning.is-focused { + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .button.is-warning:focus:not(:active), .button.is-warning.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } + .button.is-warning:active, .button.is-warning.is-active { + background-color: #ffd83e; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .button.is-warning[disabled], fieldset[disabled] .button.is-warning { + background-color: #ffdd57; + border-color: transparent; + box-shadow: none; } + .button.is-warning.is-inverted { + background-color: rgba(0, 0, 0, 0.7); + color: #ffdd57; } + .button.is-warning.is-inverted:hover, .button.is-warning.is-inverted.is-hovered { + background-color: rgba(0, 0, 0, 0.7); } + .button.is-warning.is-inverted[disabled], fieldset[disabled] .button.is-warning.is-inverted { + background-color: rgba(0, 0, 0, 0.7); + border-color: transparent; + box-shadow: none; + color: #ffdd57; } + .button.is-warning.is-loading::after { + border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; } + .button.is-warning.is-outlined { + background-color: transparent; + border-color: #ffdd57; + color: #ffdd57; } + .button.is-warning.is-outlined:hover, .button.is-warning.is-outlined.is-hovered, .button.is-warning.is-outlined:focus, .button.is-warning.is-outlined.is-focused { + background-color: #ffdd57; + border-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .button.is-warning.is-outlined.is-loading::after { + border-color: transparent transparent #ffdd57 #ffdd57 !important; } + .button.is-warning.is-outlined.is-loading:hover::after, .button.is-warning.is-outlined.is-loading.is-hovered::after, .button.is-warning.is-outlined.is-loading:focus::after, .button.is-warning.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; } + .button.is-warning.is-outlined[disabled], fieldset[disabled] .button.is-warning.is-outlined { + background-color: transparent; + border-color: #ffdd57; + box-shadow: none; + color: #ffdd57; } + .button.is-warning.is-inverted.is-outlined { + background-color: transparent; + border-color: rgba(0, 0, 0, 0.7); + color: rgba(0, 0, 0, 0.7); } + .button.is-warning.is-inverted.is-outlined:hover, .button.is-warning.is-inverted.is-outlined.is-hovered, .button.is-warning.is-inverted.is-outlined:focus, .button.is-warning.is-inverted.is-outlined.is-focused { + background-color: rgba(0, 0, 0, 0.7); + color: #ffdd57; } + .button.is-warning.is-inverted.is-outlined.is-loading:hover::after, .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-warning.is-inverted.is-outlined.is-loading:focus::after, .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #ffdd57 #ffdd57 !important; } + .button.is-warning.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-warning.is-inverted.is-outlined { + background-color: transparent; + border-color: rgba(0, 0, 0, 0.7); + box-shadow: none; + color: rgba(0, 0, 0, 0.7); } + .button.is-danger { + background-color: #da0b00; + border-color: transparent; + color: #fff; } + .button.is-danger:hover, .button.is-danger.is-hovered { + background-color: #cd0a00; + border-color: transparent; + color: #fff; } + .button.is-danger:focus, .button.is-danger.is-focused { + border-color: transparent; + color: #fff; } + .button.is-danger:focus:not(:active), .button.is-danger.is-focused:not(:active) { + box-shadow: 0 0 0 0.125em rgba(218, 11, 0, 0.25); } + .button.is-danger:active, .button.is-danger.is-active { + background-color: #c10a00; + border-color: transparent; + color: #fff; } + .button.is-danger[disabled], fieldset[disabled] .button.is-danger { + background-color: #da0b00; + border-color: transparent; + box-shadow: none; } + .button.is-danger.is-inverted { + background-color: #fff; + color: #da0b00; } + .button.is-danger.is-inverted:hover, .button.is-danger.is-inverted.is-hovered { + background-color: #f2f2f2; } + .button.is-danger.is-inverted[disabled], fieldset[disabled] .button.is-danger.is-inverted { + background-color: #fff; + border-color: transparent; + box-shadow: none; + color: #da0b00; } + .button.is-danger.is-loading::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-danger.is-outlined { + background-color: transparent; + border-color: #da0b00; + color: #da0b00; } + .button.is-danger.is-outlined:hover, .button.is-danger.is-outlined.is-hovered, .button.is-danger.is-outlined:focus, .button.is-danger.is-outlined.is-focused { + background-color: #da0b00; + border-color: #da0b00; + color: #fff; } + .button.is-danger.is-outlined.is-loading::after { + border-color: transparent transparent #da0b00 #da0b00 !important; } + .button.is-danger.is-outlined.is-loading:hover::after, .button.is-danger.is-outlined.is-loading.is-hovered::after, .button.is-danger.is-outlined.is-loading:focus::after, .button.is-danger.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #fff #fff !important; } + .button.is-danger.is-outlined[disabled], fieldset[disabled] .button.is-danger.is-outlined { + background-color: transparent; + border-color: #da0b00; + box-shadow: none; + color: #da0b00; } + .button.is-danger.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + color: #fff; } + .button.is-danger.is-inverted.is-outlined:hover, .button.is-danger.is-inverted.is-outlined.is-hovered, .button.is-danger.is-inverted.is-outlined:focus, .button.is-danger.is-inverted.is-outlined.is-focused { + background-color: #fff; + color: #da0b00; } + .button.is-danger.is-inverted.is-outlined.is-loading:hover::after, .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after, .button.is-danger.is-inverted.is-outlined.is-loading:focus::after, .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after { + border-color: transparent transparent #da0b00 #da0b00 !important; } + .button.is-danger.is-inverted.is-outlined[disabled], fieldset[disabled] .button.is-danger.is-inverted.is-outlined { + background-color: transparent; + border-color: #fff; + box-shadow: none; + color: #fff; } + .button.is-small, #documenter .docs-sidebar form.docs-search > input.button { + border-radius: 2px; + font-size: 0.75rem; } + .button.is-normal { + font-size: 1rem; } + .button.is-medium { + font-size: 1.25rem; } + .button.is-large { + font-size: 1.5rem; } + .button[disabled], fieldset[disabled] .button { + background-color: white; + border-color: #dbdbdb; + box-shadow: none; + opacity: 0.5; } + .button.is-fullwidth { + display: flex; + width: 100%; } + .button.is-loading { + color: transparent !important; + pointer-events: none; } + .button.is-loading::after { + position: absolute; + left: calc(50% - (1em / 2)); + top: calc(50% - (1em / 2)); + position: absolute !important; } + .button.is-static { + background-color: whitesmoke; + border-color: #dbdbdb; + color: #6b6b6b; + box-shadow: none; + pointer-events: none; } + .button.is-rounded, #documenter .docs-sidebar form.docs-search > input.button { + border-radius: 290486px; + padding-left: 1em; + padding-right: 1em; } + +.buttons { + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + .buttons .button { + margin-bottom: 0.5rem; } + .buttons .button:not(:last-child):not(.is-fullwidth) { + margin-right: 0.5rem; } + .buttons:last-child { + margin-bottom: -0.5rem; } + .buttons:not(:last-child) { + margin-bottom: 1rem; } + .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large) { + border-radius: 2px; + font-size: 0.75rem; } + .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large) { + font-size: 1.25rem; } + .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium) { + font-size: 1.5rem; } + .buttons.has-addons .button:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + .buttons.has-addons .button:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + margin-right: -1px; } + .buttons.has-addons .button:last-child { + margin-right: 0; } + .buttons.has-addons .button:hover, .buttons.has-addons .button.is-hovered { + z-index: 2; } + .buttons.has-addons .button:focus, .buttons.has-addons .button.is-focused, .buttons.has-addons .button:active, .buttons.has-addons .button.is-active, .buttons.has-addons .button.is-selected { + z-index: 3; } + .buttons.has-addons .button:focus:hover, .buttons.has-addons .button.is-focused:hover, .buttons.has-addons .button:active:hover, .buttons.has-addons .button.is-active:hover, .buttons.has-addons .button.is-selected:hover { + z-index: 4; } + .buttons.has-addons .button.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + .buttons.is-centered { + justify-content: center; } + .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth) { + margin-left: 0.25rem; + margin-right: 0.25rem; } + .buttons.is-right { + justify-content: flex-end; } + .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth) { + margin-left: 0.25rem; + margin-right: 0.25rem; } + +.container { + flex-grow: 1; + margin: 0 auto; + position: relative; + width: auto; } + @media screen and (min-width: 1056px) { + .container { + max-width: 992px; } + .container.is-fluid { + margin-left: 32px; + margin-right: 32px; + max-width: none; } } + @media screen and (max-width: 1215px) { + .container.is-widescreen { + max-width: 1152px; } } + @media screen and (max-width: 1407px) { + .container.is-fullhd { + max-width: 1344px; } } + @media screen and (min-width: 1216px) { + .container { + max-width: 1152px; } } + @media screen and (min-width: 1408px) { + .container { + max-width: 1344px; } } +.content li + li { + margin-top: 0.25em; } + +.content p:not(:last-child), +.content dl:not(:last-child), +.content ol:not(:last-child), +.content ul:not(:last-child), +.content blockquote:not(:last-child), +.content pre:not(:last-child), +.content table:not(:last-child) { + margin-bottom: 1em; } + +.content h1, +.content h2, +.content h3, +.content h4, +.content h5, +.content h6 { + color: #222222; + font-weight: 600; + line-height: 1.125; } + +.content h1 { + font-size: 2em; + margin-bottom: 0.5em; } + .content h1:not(:first-child) { + margin-top: 1em; } + +.content h2 { + font-size: 1.75em; + margin-bottom: 0.5714em; } + .content h2:not(:first-child) { + margin-top: 1.1428em; } + +.content h3 { + font-size: 1.5em; + margin-bottom: 0.6666em; } + .content h3:not(:first-child) { + margin-top: 1.3333em; } + +.content h4 { + font-size: 1.25em; + margin-bottom: 0.8em; } + +.content h5 { + font-size: 1.125em; + margin-bottom: 0.8888em; } + +.content h6 { + font-size: 1em; + margin-bottom: 1em; } + +.content blockquote { + background-color: whitesmoke; + border-left: 5px solid #dbdbdb; + padding: 1.25em 1.5em; } + +.content ol { + list-style-position: outside; + margin-left: 2em; + margin-top: 1em; } + .content ol:not([type]) { + list-style-type: decimal; } + .content ol.is-lower-alpha:not([type]) { + list-style-type: lower-alpha; } + .content ol.is-lower-roman:not([type]) { + list-style-type: lower-roman; } + .content ol.is-upper-alpha:not([type]) { + list-style-type: upper-alpha; } + .content ol.is-upper-roman:not([type]) { + list-style-type: upper-roman; } + +.content ul { + list-style: disc outside; + margin-left: 2em; + margin-top: 1em; } + .content ul ul { + list-style-type: circle; + margin-top: 0.5em; } + .content ul ul ul { + list-style-type: square; } + +.content dd { + margin-left: 2em; } + +.content figure { + margin-left: 2em; + margin-right: 2em; + text-align: center; } + .content figure:not(:first-child) { + margin-top: 2em; } + .content figure:not(:last-child) { + margin-bottom: 2em; } + .content figure img { + display: inline-block; } + .content figure figcaption { + font-style: italic; } + +.content pre { + -webkit-overflow-scrolling: touch; + overflow-x: auto; + padding: 0; + white-space: pre; + word-wrap: normal; } + +.content sup, +.content sub { + font-size: 75%; } + +.content table { + width: 100%; } + .content table td, + .content table th { + border: 1px solid #dbdbdb; + border-width: 0 0 1px; + padding: 0.5em 0.75em; + vertical-align: top; } + .content table th { + color: #222222; } + .content table th:not([align]) { + text-align: left; } + .content table thead td, + .content table thead th { + border-width: 0 0 2px; + color: #222222; } + .content table tfoot td, + .content table tfoot th { + border-width: 2px 0 0; + color: #222222; } + .content table tbody tr:last-child td, + .content table tbody tr:last-child th { + border-bottom-width: 0; } + +.content .tabs li + li { + margin-top: 0; } + +.content.is-small, #documenter .docs-sidebar form.docs-search > input.content { + font-size: 0.75rem; } + +.content.is-medium { + font-size: 1.25rem; } + +.content.is-large { + font-size: 1.5rem; } + +.icon { + align-items: center; + display: inline-flex; + justify-content: center; + height: 1.5rem; + width: 1.5rem; } + .icon.is-small, #documenter .docs-sidebar form.docs-search > input.icon { + height: 1rem; + width: 1rem; } + .icon.is-medium { + height: 2rem; + width: 2rem; } + .icon.is-large { + height: 3rem; + width: 3rem; } + +.image, #documenter .docs-sidebar .docs-logo > img { + display: block; + position: relative; } + .image img, #documenter .docs-sidebar .docs-logo > img img { + display: block; + height: auto; + width: 100%; } + .image img.is-rounded, #documenter .docs-sidebar .docs-logo > img img.is-rounded { + border-radius: 290486px; } + .image.is-square img, #documenter .docs-sidebar .docs-logo > img.is-square img, + .image.is-square .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-square .has-ratio, .image.is-1by1 img, #documenter .docs-sidebar .docs-logo > img.is-1by1 img, + .image.is-1by1 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-1by1 .has-ratio, .image.is-5by4 img, #documenter .docs-sidebar .docs-logo > img.is-5by4 img, + .image.is-5by4 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-5by4 .has-ratio, .image.is-4by3 img, #documenter .docs-sidebar .docs-logo > img.is-4by3 img, + .image.is-4by3 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-4by3 .has-ratio, .image.is-3by2 img, #documenter .docs-sidebar .docs-logo > img.is-3by2 img, + .image.is-3by2 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-3by2 .has-ratio, .image.is-5by3 img, #documenter .docs-sidebar .docs-logo > img.is-5by3 img, + .image.is-5by3 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-5by3 .has-ratio, .image.is-16by9 img, #documenter .docs-sidebar .docs-logo > img.is-16by9 img, + .image.is-16by9 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-16by9 .has-ratio, .image.is-2by1 img, #documenter .docs-sidebar .docs-logo > img.is-2by1 img, + .image.is-2by1 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-2by1 .has-ratio, .image.is-3by1 img, #documenter .docs-sidebar .docs-logo > img.is-3by1 img, + .image.is-3by1 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-3by1 .has-ratio, .image.is-4by5 img, #documenter .docs-sidebar .docs-logo > img.is-4by5 img, + .image.is-4by5 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-4by5 .has-ratio, .image.is-3by4 img, #documenter .docs-sidebar .docs-logo > img.is-3by4 img, + .image.is-3by4 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-3by4 .has-ratio, .image.is-2by3 img, #documenter .docs-sidebar .docs-logo > img.is-2by3 img, + .image.is-2by3 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-2by3 .has-ratio, .image.is-3by5 img, #documenter .docs-sidebar .docs-logo > img.is-3by5 img, + .image.is-3by5 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-3by5 .has-ratio, .image.is-9by16 img, #documenter .docs-sidebar .docs-logo > img.is-9by16 img, + .image.is-9by16 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-9by16 .has-ratio, .image.is-1by2 img, #documenter .docs-sidebar .docs-logo > img.is-1by2 img, + .image.is-1by2 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-1by2 .has-ratio, .image.is-1by3 img, #documenter .docs-sidebar .docs-logo > img.is-1by3 img, + .image.is-1by3 .has-ratio, + #documenter .docs-sidebar .docs-logo > img.is-1by3 .has-ratio { + height: 100%; + width: 100%; } + .image.is-square, #documenter .docs-sidebar .docs-logo > img.is-square, .image.is-1by1, #documenter .docs-sidebar .docs-logo > img.is-1by1 { + padding-top: 100%; } + .image.is-5by4, #documenter .docs-sidebar .docs-logo > img.is-5by4 { + padding-top: 80%; } + .image.is-4by3, #documenter .docs-sidebar .docs-logo > img.is-4by3 { + padding-top: 75%; } + .image.is-3by2, #documenter .docs-sidebar .docs-logo > img.is-3by2 { + padding-top: 66.6666%; } + .image.is-5by3, #documenter .docs-sidebar .docs-logo > img.is-5by3 { + padding-top: 60%; } + .image.is-16by9, #documenter .docs-sidebar .docs-logo > img.is-16by9 { + padding-top: 56.25%; } + .image.is-2by1, #documenter .docs-sidebar .docs-logo > img.is-2by1 { + padding-top: 50%; } + .image.is-3by1, #documenter .docs-sidebar .docs-logo > img.is-3by1 { + padding-top: 33.3333%; } + .image.is-4by5, #documenter .docs-sidebar .docs-logo > img.is-4by5 { + padding-top: 125%; } + .image.is-3by4, #documenter .docs-sidebar .docs-logo > img.is-3by4 { + padding-top: 133.3333%; } + .image.is-2by3, #documenter .docs-sidebar .docs-logo > img.is-2by3 { + padding-top: 150%; } + .image.is-3by5, #documenter .docs-sidebar .docs-logo > img.is-3by5 { + padding-top: 166.6666%; } + .image.is-9by16, #documenter .docs-sidebar .docs-logo > img.is-9by16 { + padding-top: 177.7777%; } + .image.is-1by2, #documenter .docs-sidebar .docs-logo > img.is-1by2 { + padding-top: 200%; } + .image.is-1by3, #documenter .docs-sidebar .docs-logo > img.is-1by3 { + padding-top: 300%; } + .image.is-16x16, #documenter .docs-sidebar .docs-logo > img.is-16x16 { + height: 16px; + width: 16px; } + .image.is-24x24, #documenter .docs-sidebar .docs-logo > img.is-24x24 { + height: 24px; + width: 24px; } + .image.is-32x32, #documenter .docs-sidebar .docs-logo > img.is-32x32 { + height: 32px; + width: 32px; } + .image.is-48x48, #documenter .docs-sidebar .docs-logo > img.is-48x48 { + height: 48px; + width: 48px; } + .image.is-64x64, #documenter .docs-sidebar .docs-logo > img.is-64x64 { + height: 64px; + width: 64px; } + .image.is-96x96, #documenter .docs-sidebar .docs-logo > img.is-96x96 { + height: 96px; + width: 96px; } + .image.is-128x128, #documenter .docs-sidebar .docs-logo > img.is-128x128 { + height: 128px; + width: 128px; } + +.notification { + background-color: whitesmoke; + border-radius: 4px; + padding: 1.25rem 2.5rem 1.25rem 1.5rem; + position: relative; } + .notification a:not(.button):not(.dropdown-item) { + color: currentColor; + text-decoration: underline; } + .notification strong { + color: currentColor; } + .notification code, + .notification pre { + background: white; } + .notification pre code { + background: transparent; } + .notification > .delete { + position: absolute; + right: 0.5rem; + top: 0.5rem; } + .notification .title, + .notification .subtitle, + .notification .content { + color: currentColor; } + .notification.is-white { + background-color: white; + color: #0a0a0a; } + .notification.is-black { + background-color: #0a0a0a; + color: white; } + .notification.is-light { + background-color: whitesmoke; + color: #363636; } + .notification.is-dark, .content kbd.notification { + background-color: #363636; + color: whitesmoke; } + .notification.is-primary, .docstring > section > a.notification.docs-sourcelink { + background-color: #4eb5de; + color: #fff; } + .notification.is-link { + background-color: #2e63b8; + color: #fff; } + .notification.is-info { + background-color: #209cee; + color: #fff; } + .notification.is-success { + background-color: #22c35b; + color: #fff; } + .notification.is-warning { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .notification.is-danger { + background-color: #da0b00; + color: #fff; } + +.progress { + -moz-appearance: none; + -webkit-appearance: none; + border: none; + border-radius: 290486px; + display: block; + height: 1rem; + overflow: hidden; + padding: 0; + width: 100%; } + .progress::-webkit-progress-bar { + background-color: #dbdbdb; } + .progress::-webkit-progress-value { + background-color: #222222; } + .progress::-moz-progress-bar { + background-color: #222222; } + .progress::-ms-fill { + background-color: #222222; + border: none; } + .progress.is-white::-webkit-progress-value { + background-color: white; } + .progress.is-white::-moz-progress-bar { + background-color: white; } + .progress.is-white::-ms-fill { + background-color: white; } + .progress.is-white:indeterminate { + background-image: linear-gradient(to right, white 30%, #dbdbdb 30%); } + .progress.is-black::-webkit-progress-value { + background-color: #0a0a0a; } + .progress.is-black::-moz-progress-bar { + background-color: #0a0a0a; } + .progress.is-black::-ms-fill { + background-color: #0a0a0a; } + .progress.is-black:indeterminate { + background-image: linear-gradient(to right, #0a0a0a 30%, #dbdbdb 30%); } + .progress.is-light::-webkit-progress-value { + background-color: whitesmoke; } + .progress.is-light::-moz-progress-bar { + background-color: whitesmoke; } + .progress.is-light::-ms-fill { + background-color: whitesmoke; } + .progress.is-light:indeterminate { + background-image: linear-gradient(to right, whitesmoke 30%, #dbdbdb 30%); } + .progress.is-dark::-webkit-progress-value, .content kbd.progress::-webkit-progress-value { + background-color: #363636; } + .progress.is-dark::-moz-progress-bar, .content kbd.progress::-moz-progress-bar { + background-color: #363636; } + .progress.is-dark::-ms-fill, .content kbd.progress::-ms-fill { + background-color: #363636; } + .progress.is-dark:indeterminate, .content kbd.progress:indeterminate { + background-image: linear-gradient(to right, #363636 30%, #dbdbdb 30%); } + .progress.is-primary::-webkit-progress-value, .docstring > section > a.progress.docs-sourcelink::-webkit-progress-value { + background-color: #4eb5de; } + .progress.is-primary::-moz-progress-bar, .docstring > section > a.progress.docs-sourcelink::-moz-progress-bar { + background-color: #4eb5de; } + .progress.is-primary::-ms-fill, .docstring > section > a.progress.docs-sourcelink::-ms-fill { + background-color: #4eb5de; } + .progress.is-primary:indeterminate, .docstring > section > a.progress.docs-sourcelink:indeterminate { + background-image: linear-gradient(to right, #4eb5de 30%, #dbdbdb 30%); } + .progress.is-link::-webkit-progress-value { + background-color: #2e63b8; } + .progress.is-link::-moz-progress-bar { + background-color: #2e63b8; } + .progress.is-link::-ms-fill { + background-color: #2e63b8; } + .progress.is-link:indeterminate { + background-image: linear-gradient(to right, #2e63b8 30%, #dbdbdb 30%); } + .progress.is-info::-webkit-progress-value { + background-color: #209cee; } + .progress.is-info::-moz-progress-bar { + background-color: #209cee; } + .progress.is-info::-ms-fill { + background-color: #209cee; } + .progress.is-info:indeterminate { + background-image: linear-gradient(to right, #209cee 30%, #dbdbdb 30%); } + .progress.is-success::-webkit-progress-value { + background-color: #22c35b; } + .progress.is-success::-moz-progress-bar { + background-color: #22c35b; } + .progress.is-success::-ms-fill { + background-color: #22c35b; } + .progress.is-success:indeterminate { + background-image: linear-gradient(to right, #22c35b 30%, #dbdbdb 30%); } + .progress.is-warning::-webkit-progress-value { + background-color: #ffdd57; } + .progress.is-warning::-moz-progress-bar { + background-color: #ffdd57; } + .progress.is-warning::-ms-fill { + background-color: #ffdd57; } + .progress.is-warning:indeterminate { + background-image: linear-gradient(to right, #ffdd57 30%, #dbdbdb 30%); } + .progress.is-danger::-webkit-progress-value { + background-color: #da0b00; } + .progress.is-danger::-moz-progress-bar { + background-color: #da0b00; } + .progress.is-danger::-ms-fill { + background-color: #da0b00; } + .progress.is-danger:indeterminate { + background-image: linear-gradient(to right, #da0b00 30%, #dbdbdb 30%); } + .progress:indeterminate { + animation-duration: 1.5s; + animation-iteration-count: infinite; + animation-name: moveIndeterminate; + animation-timing-function: linear; + background-color: #dbdbdb; + background-image: linear-gradient(to right, #222222 30%, #dbdbdb 30%); + background-position: top left; + background-repeat: no-repeat; + background-size: 150% 150%; } + .progress:indeterminate::-webkit-progress-bar { + background-color: transparent; } + .progress:indeterminate::-moz-progress-bar { + background-color: transparent; } + .progress.is-small, #documenter .docs-sidebar form.docs-search > input.progress { + height: 0.75rem; } + .progress.is-medium { + height: 1.25rem; } + .progress.is-large { + height: 1.5rem; } + +@keyframes moveIndeterminate { + from { + background-position: 200% 0; } + to { + background-position: -200% 0; } } + +.table { + background-color: white; + color: #363636; } + .table td, + .table th { + border: 1px solid #dbdbdb; + border-width: 0 0 1px; + padding: 0.5em 0.75em; + vertical-align: top; } + .table td.is-white, + .table th.is-white { + background-color: white; + border-color: white; + color: #0a0a0a; } + .table td.is-black, + .table th.is-black { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + .table td.is-light, + .table th.is-light { + background-color: whitesmoke; + border-color: whitesmoke; + color: #363636; } + .table td.is-dark, + .table th.is-dark { + background-color: #363636; + border-color: #363636; + color: whitesmoke; } + .table td.is-primary, + .table th.is-primary { + background-color: #4eb5de; + border-color: #4eb5de; + color: #fff; } + .table td.is-link, + .table th.is-link { + background-color: #2e63b8; + border-color: #2e63b8; + color: #fff; } + .table td.is-info, + .table th.is-info { + background-color: #209cee; + border-color: #209cee; + color: #fff; } + .table td.is-success, + .table th.is-success { + background-color: #22c35b; + border-color: #22c35b; + color: #fff; } + .table td.is-warning, + .table th.is-warning { + background-color: #ffdd57; + border-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .table td.is-danger, + .table th.is-danger { + background-color: #da0b00; + border-color: #da0b00; + color: #fff; } + .table td.is-narrow, + .table th.is-narrow { + white-space: nowrap; + width: 1%; } + .table td.is-selected, + .table th.is-selected { + background-color: #4eb5de; + color: #fff; } + .table td.is-selected a, + .table td.is-selected strong, + .table th.is-selected a, + .table th.is-selected strong { + color: currentColor; } + .table th { + color: #222222; } + .table th:not([align]) { + text-align: left; } + .table tr.is-selected { + background-color: #4eb5de; + color: #fff; } + .table tr.is-selected a, + .table tr.is-selected strong { + color: currentColor; } + .table tr.is-selected td, + .table tr.is-selected th { + border-color: #fff; + color: currentColor; } + .table thead { + background-color: transparent; } + .table thead td, + .table thead th { + border-width: 0 0 2px; + color: #222222; } + .table tfoot { + background-color: transparent; } + .table tfoot td, + .table tfoot th { + border-width: 2px 0 0; + color: #222222; } + .table tbody { + background-color: transparent; } + .table tbody tr:last-child td, + .table tbody tr:last-child th { + border-bottom-width: 0; } + .table.is-bordered td, + .table.is-bordered th { + border-width: 1px; } + .table.is-bordered tr:last-child td, + .table.is-bordered tr:last-child th { + border-bottom-width: 1px; } + .table.is-fullwidth { + width: 100%; } + .table.is-hoverable tbody tr:not(.is-selected):hover { + background-color: #fafafa; } + .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover { + background-color: #fafafa; } + .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even) { + background-color: whitesmoke; } + .table.is-narrow td, + .table.is-narrow th { + padding: 0.25em 0.5em; } + .table.is-striped tbody tr:not(.is-selected):nth-child(even) { + background-color: #fafafa; } + +.table-container { + -webkit-overflow-scrolling: touch; + overflow: auto; + overflow-y: hidden; + max-width: 100%; } + +.tags { + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + .tags .tag, .tags .content kbd, .content .tags kbd, .tags .docstring > section > a.docs-sourcelink { + margin-bottom: 0.5rem; } + .tags .tag:not(:last-child), .tags .content kbd:not(:last-child), .content .tags kbd:not(:last-child), .tags .docstring > section > a.docs-sourcelink:not(:last-child) { + margin-right: 0.5rem; } + .tags:last-child { + margin-bottom: -0.5rem; } + .tags:not(:last-child) { + margin-bottom: 1rem; } + .tags.are-medium .tag:not(.is-normal):not(.is-large), .tags.are-medium .content kbd:not(.is-normal):not(.is-large), .content .tags.are-medium kbd:not(.is-normal):not(.is-large), .tags.are-medium .docstring > section > a.docs-sourcelink:not(.is-normal):not(.is-large) { + font-size: 1rem; } + .tags.are-large .tag:not(.is-normal):not(.is-medium), .tags.are-large .content kbd:not(.is-normal):not(.is-medium), .content .tags.are-large kbd:not(.is-normal):not(.is-medium), .tags.are-large .docstring > section > a.docs-sourcelink:not(.is-normal):not(.is-medium) { + font-size: 1.25rem; } + .tags.is-centered { + justify-content: center; } + .tags.is-centered .tag, .tags.is-centered .content kbd, .content .tags.is-centered kbd, .tags.is-centered .docstring > section > a.docs-sourcelink { + margin-right: 0.25rem; + margin-left: 0.25rem; } + .tags.is-right { + justify-content: flex-end; } + .tags.is-right .tag:not(:first-child), .tags.is-right .content kbd:not(:first-child), .content .tags.is-right kbd:not(:first-child), .tags.is-right .docstring > section > a.docs-sourcelink:not(:first-child) { + margin-left: 0.5rem; } + .tags.is-right .tag:not(:last-child), .tags.is-right .content kbd:not(:last-child), .content .tags.is-right kbd:not(:last-child), .tags.is-right .docstring > section > a.docs-sourcelink:not(:last-child) { + margin-right: 0; } + .tags.has-addons .tag, .tags.has-addons .content kbd, .content .tags.has-addons kbd, .tags.has-addons .docstring > section > a.docs-sourcelink { + margin-right: 0; } + .tags.has-addons .tag:not(:first-child), .tags.has-addons .content kbd:not(:first-child), .content .tags.has-addons kbd:not(:first-child), .tags.has-addons .docstring > section > a.docs-sourcelink:not(:first-child) { + margin-left: 0; + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + .tags.has-addons .tag:not(:last-child), .tags.has-addons .content kbd:not(:last-child), .content .tags.has-addons kbd:not(:last-child), .tags.has-addons .docstring > section > a.docs-sourcelink:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + +.tag:not(body), .content kbd:not(body), .docstring > section > a.docs-sourcelink:not(body) { + align-items: center; + background-color: whitesmoke; + border-radius: 4px; + color: #222222; + display: inline-flex; + font-size: 0.75rem; + height: 2em; + justify-content: center; + line-height: 1.5; + padding-left: 0.75em; + padding-right: 0.75em; + white-space: nowrap; } + .tag:not(body) .delete, .content kbd:not(body) .delete, .docstring > section > a.docs-sourcelink:not(body) .delete { + margin-left: 0.25rem; + margin-right: -0.375rem; } + .tag.is-white:not(body), .content kbd.is-white:not(body), .docstring > section > a.docs-sourcelink.is-white:not(body) { + background-color: white; + color: #0a0a0a; } + .tag.is-black:not(body), .content kbd.is-black:not(body), .docstring > section > a.docs-sourcelink.is-black:not(body) { + background-color: #0a0a0a; + color: white; } + .tag.is-light:not(body), .content kbd.is-light:not(body), .docstring > section > a.docs-sourcelink.is-light:not(body) { + background-color: whitesmoke; + color: #363636; } + .tag.is-dark:not(body), .content kbd:not(body), .docstring > section > a.docs-sourcelink.is-dark:not(body), .content .docstring > section > kbd:not(body) { + background-color: #363636; + color: whitesmoke; } + .tag.is-primary:not(body), .content kbd.is-primary:not(body), .docstring > section > a.docs-sourcelink:not(body) { + background-color: #4eb5de; + color: #fff; } + .tag.is-link:not(body), .content kbd.is-link:not(body), .docstring > section > a.docs-sourcelink.is-link:not(body) { + background-color: #2e63b8; + color: #fff; } + .tag.is-info:not(body), .content kbd.is-info:not(body), .docstring > section > a.docs-sourcelink.is-info:not(body) { + background-color: #209cee; + color: #fff; } + .tag.is-success:not(body), .content kbd.is-success:not(body), .docstring > section > a.docs-sourcelink.is-success:not(body) { + background-color: #22c35b; + color: #fff; } + .tag.is-warning:not(body), .content kbd.is-warning:not(body), .docstring > section > a.docs-sourcelink.is-warning:not(body) { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .tag.is-danger:not(body), .content kbd.is-danger:not(body), .docstring > section > a.docs-sourcelink.is-danger:not(body) { + background-color: #da0b00; + color: #fff; } + .tag.is-normal:not(body), .content kbd.is-normal:not(body), .docstring > section > a.docs-sourcelink.is-normal:not(body) { + font-size: 0.75rem; } + .tag.is-medium:not(body), .content kbd.is-medium:not(body), .docstring > section > a.docs-sourcelink.is-medium:not(body) { + font-size: 1rem; } + .tag.is-large:not(body), .content kbd.is-large:not(body), .docstring > section > a.docs-sourcelink.is-large:not(body) { + font-size: 1.25rem; } + .tag:not(body) .icon:first-child:not(:last-child), .content kbd:not(body) .icon:first-child:not(:last-child), .docstring > section > a.docs-sourcelink:not(body) .icon:first-child:not(:last-child) { + margin-left: -0.375em; + margin-right: 0.1875em; } + .tag:not(body) .icon:last-child:not(:first-child), .content kbd:not(body) .icon:last-child:not(:first-child), .docstring > section > a.docs-sourcelink:not(body) .icon:last-child:not(:first-child) { + margin-left: 0.1875em; + margin-right: -0.375em; } + .tag:not(body) .icon:first-child:last-child, .content kbd:not(body) .icon:first-child:last-child, .docstring > section > a.docs-sourcelink:not(body) .icon:first-child:last-child { + margin-left: -0.375em; + margin-right: -0.375em; } + .tag.is-delete:not(body), .content kbd.is-delete:not(body), .docstring > section > a.docs-sourcelink.is-delete:not(body) { + margin-left: 1px; + padding: 0; + position: relative; + width: 2em; } + .tag.is-delete:not(body)::before, .content kbd.is-delete:not(body)::before, .docstring > section > a.docs-sourcelink.is-delete:not(body)::before, .tag.is-delete:not(body)::after, .content kbd.is-delete:not(body)::after, .docstring > section > a.docs-sourcelink.is-delete:not(body)::after { + background-color: currentColor; + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; } + .tag.is-delete:not(body)::before, .content kbd.is-delete:not(body)::before, .docstring > section > a.docs-sourcelink.is-delete:not(body)::before { + height: 1px; + width: 50%; } + .tag.is-delete:not(body)::after, .content kbd.is-delete:not(body)::after, .docstring > section > a.docs-sourcelink.is-delete:not(body)::after { + height: 50%; + width: 1px; } + .tag.is-delete:not(body):hover, .content kbd.is-delete:not(body):hover, .docstring > section > a.docs-sourcelink.is-delete:not(body):hover, .tag.is-delete:not(body):focus, .content kbd.is-delete:not(body):focus, .docstring > section > a.docs-sourcelink.is-delete:not(body):focus { + background-color: #e8e8e8; } + .tag.is-delete:not(body):active, .content kbd.is-delete:not(body):active, .docstring > section > a.docs-sourcelink.is-delete:not(body):active { + background-color: #dbdbdb; } + .tag.is-rounded:not(body), #documenter .docs-sidebar form.docs-search > input:not(body), .content kbd.is-rounded:not(body), #documenter .docs-sidebar .content form.docs-search > input:not(body), .docstring > section > a.docs-sourcelink.is-rounded:not(body) { + border-radius: 290486px; } + +a.tag:hover, .docstring > section > a.docs-sourcelink:hover { + text-decoration: underline; } + +.title, +.subtitle { + word-break: break-word; } + .title em, + .title span, + .subtitle em, + .subtitle span { + font-weight: inherit; } + .title sub, + .subtitle sub { + font-size: 0.75em; } + .title sup, + .subtitle sup { + font-size: 0.75em; } + .title .tag, .title .content kbd, .content .title kbd, .title .docstring > section > a.docs-sourcelink, + .subtitle .tag, + .subtitle .content kbd, + .content .subtitle kbd, + .subtitle .docstring > section > a.docs-sourcelink { + vertical-align: middle; } + +.title { + color: #363636; + font-size: 2rem; + font-weight: 600; + line-height: 1.125; } + .title strong { + color: inherit; + font-weight: inherit; } + .title + .highlight { + margin-top: -0.75rem; } + .title:not(.is-spaced) + .subtitle { + margin-top: -1.25rem; } + .title.is-1 { + font-size: 3rem; } + .title.is-2 { + font-size: 2.5rem; } + .title.is-3 { + font-size: 2rem; } + .title.is-4 { + font-size: 1.5rem; } + .title.is-5 { + font-size: 1.25rem; } + .title.is-6 { + font-size: 1rem; } + .title.is-7 { + font-size: 0.75rem; } + +.subtitle { + color: #4a4a4a; + font-size: 1.25rem; + font-weight: 400; + line-height: 1.25; } + .subtitle strong { + color: #363636; + font-weight: 600; } + .subtitle:not(.is-spaced) + .title { + margin-top: -1.25rem; } + .subtitle.is-1 { + font-size: 3rem; } + .subtitle.is-2 { + font-size: 2.5rem; } + .subtitle.is-3 { + font-size: 2rem; } + .subtitle.is-4 { + font-size: 1.5rem; } + .subtitle.is-5 { + font-size: 1.25rem; } + .subtitle.is-6 { + font-size: 1rem; } + .subtitle.is-7 { + font-size: 0.75rem; } + +.heading { + display: block; + font-size: 11px; + letter-spacing: 1px; + margin-bottom: 5px; + text-transform: uppercase; } + +.highlight { + font-weight: 400; + max-width: 100%; + overflow: hidden; + padding: 0; } + .highlight pre { + overflow: auto; + max-width: 100%; } + +.number { + align-items: center; + background-color: whitesmoke; + border-radius: 290486px; + display: inline-flex; + font-size: 1.25rem; + height: 2em; + justify-content: center; + margin-right: 1.5rem; + min-width: 2.5em; + padding: 0.25rem 0.5rem; + text-align: center; + vertical-align: top; } + +.select select, .textarea, .input, #documenter .docs-sidebar form.docs-search > input { + background-color: white; + border-color: #dbdbdb; + border-radius: 4px; + color: #363636; } + .select select::-moz-placeholder, .textarea::-moz-placeholder, .input::-moz-placeholder, #documenter .docs-sidebar form.docs-search > input::-moz-placeholder { + color: rgba(54, 54, 54, 0.3); } + .select select::-webkit-input-placeholder, .textarea::-webkit-input-placeholder, .input::-webkit-input-placeholder, #documenter .docs-sidebar form.docs-search > input::-webkit-input-placeholder { + color: rgba(54, 54, 54, 0.3); } + .select select:-moz-placeholder, .textarea:-moz-placeholder, .input:-moz-placeholder, #documenter .docs-sidebar form.docs-search > input:-moz-placeholder { + color: rgba(54, 54, 54, 0.3); } + .select select:-ms-input-placeholder, .textarea:-ms-input-placeholder, .input:-ms-input-placeholder, #documenter .docs-sidebar form.docs-search > input:-ms-input-placeholder { + color: rgba(54, 54, 54, 0.3); } + .select select:hover, .textarea:hover, .input:hover, #documenter .docs-sidebar form.docs-search > input:hover, .select select.is-hovered, .is-hovered.textarea, .is-hovered.input, #documenter .docs-sidebar form.docs-search > input.is-hovered { + border-color: #b5b5b5; } + .select select:focus, .textarea:focus, .input:focus, #documenter .docs-sidebar form.docs-search > input:focus, .select select.is-focused, .is-focused.textarea, .is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .select select:active, .textarea:active, .input:active, #documenter .docs-sidebar form.docs-search > input:active, .select select.is-active, .is-active.textarea, .is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + border-color: #2e63b8; + box-shadow: 0 0 0 0.125em rgba(46, 99, 184, 0.25); } + .select select[disabled], .textarea[disabled], .input[disabled], #documenter .docs-sidebar form.docs-search > input[disabled], fieldset[disabled] .select select, .select fieldset[disabled] select, fieldset[disabled] .textarea, fieldset[disabled] .input, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input { + background-color: whitesmoke; + border-color: whitesmoke; + box-shadow: none; + color: #6b6b6b; } + .select select[disabled]::-moz-placeholder, .textarea[disabled]::-moz-placeholder, .input[disabled]::-moz-placeholder, #documenter .docs-sidebar form.docs-search > input[disabled]::-moz-placeholder, fieldset[disabled] .select select::-moz-placeholder, .select fieldset[disabled] select::-moz-placeholder, fieldset[disabled] .textarea::-moz-placeholder, fieldset[disabled] .input::-moz-placeholder, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input::-moz-placeholder, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input::-moz-placeholder { + color: rgba(107, 107, 107, 0.3); } + .select select[disabled]::-webkit-input-placeholder, .textarea[disabled]::-webkit-input-placeholder, .input[disabled]::-webkit-input-placeholder, #documenter .docs-sidebar form.docs-search > input[disabled]::-webkit-input-placeholder, fieldset[disabled] .select select::-webkit-input-placeholder, .select fieldset[disabled] select::-webkit-input-placeholder, fieldset[disabled] .textarea::-webkit-input-placeholder, fieldset[disabled] .input::-webkit-input-placeholder, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input::-webkit-input-placeholder, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input::-webkit-input-placeholder { + color: rgba(107, 107, 107, 0.3); } + .select select[disabled]:-moz-placeholder, .textarea[disabled]:-moz-placeholder, .input[disabled]:-moz-placeholder, #documenter .docs-sidebar form.docs-search > input[disabled]:-moz-placeholder, fieldset[disabled] .select select:-moz-placeholder, .select fieldset[disabled] select:-moz-placeholder, fieldset[disabled] .textarea:-moz-placeholder, fieldset[disabled] .input:-moz-placeholder, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input:-moz-placeholder, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input:-moz-placeholder { + color: rgba(107, 107, 107, 0.3); } + .select select[disabled]:-ms-input-placeholder, .textarea[disabled]:-ms-input-placeholder, .input[disabled]:-ms-input-placeholder, #documenter .docs-sidebar form.docs-search > input[disabled]:-ms-input-placeholder, fieldset[disabled] .select select:-ms-input-placeholder, .select fieldset[disabled] select:-ms-input-placeholder, fieldset[disabled] .textarea:-ms-input-placeholder, fieldset[disabled] .input:-ms-input-placeholder, fieldset[disabled] #documenter .docs-sidebar form.docs-search > input:-ms-input-placeholder, #documenter .docs-sidebar fieldset[disabled] form.docs-search > input:-ms-input-placeholder { + color: rgba(107, 107, 107, 0.3); } + +.textarea, .input, #documenter .docs-sidebar form.docs-search > input { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + max-width: 100%; + width: 100%; } + .textarea[readonly], .input[readonly], #documenter .docs-sidebar form.docs-search > input[readonly] { + box-shadow: none; } + .is-white.textarea, .is-white.input, #documenter .docs-sidebar form.docs-search > input.is-white { + border-color: white; } + .is-white.textarea:focus, .is-white.input:focus, #documenter .docs-sidebar form.docs-search > input.is-white:focus, .is-white.is-focused.textarea, .is-white.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-white.textarea:active, .is-white.input:active, #documenter .docs-sidebar form.docs-search > input.is-white:active, .is-white.is-active.textarea, .is-white.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + .is-black.textarea, .is-black.input, #documenter .docs-sidebar form.docs-search > input.is-black { + border-color: #0a0a0a; } + .is-black.textarea:focus, .is-black.input:focus, #documenter .docs-sidebar form.docs-search > input.is-black:focus, .is-black.is-focused.textarea, .is-black.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-black.textarea:active, .is-black.input:active, #documenter .docs-sidebar form.docs-search > input.is-black:active, .is-black.is-active.textarea, .is-black.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + .is-light.textarea, .is-light.input, #documenter .docs-sidebar form.docs-search > input.is-light { + border-color: whitesmoke; } + .is-light.textarea:focus, .is-light.input:focus, #documenter .docs-sidebar form.docs-search > input.is-light:focus, .is-light.is-focused.textarea, .is-light.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-light.textarea:active, .is-light.input:active, #documenter .docs-sidebar form.docs-search > input.is-light:active, .is-light.is-active.textarea, .is-light.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } + .is-dark.textarea, .content kbd.textarea, .is-dark.input, #documenter .docs-sidebar form.docs-search > input.is-dark, .content kbd.input { + border-color: #363636; } + .is-dark.textarea:focus, .content kbd.textarea:focus, .is-dark.input:focus, #documenter .docs-sidebar form.docs-search > input.is-dark:focus, .content kbd.input:focus, .is-dark.is-focused.textarea, .content kbd.is-focused.textarea, .is-dark.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .content kbd.is-focused.input, #documenter .docs-sidebar .content form.docs-search > input.is-focused, .is-dark.textarea:active, .content kbd.textarea:active, .is-dark.input:active, #documenter .docs-sidebar form.docs-search > input.is-dark:active, .content kbd.input:active, .is-dark.is-active.textarea, .content kbd.is-active.textarea, .is-dark.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active, .content kbd.is-active.input, #documenter .docs-sidebar .content form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } + .is-primary.textarea, .docstring > section > a.textarea.docs-sourcelink, .is-primary.input, #documenter .docs-sidebar form.docs-search > input.is-primary, .docstring > section > a.input.docs-sourcelink { + border-color: #4eb5de; } + .is-primary.textarea:focus, .docstring > section > a.textarea.docs-sourcelink:focus, .is-primary.input:focus, #documenter .docs-sidebar form.docs-search > input.is-primary:focus, .docstring > section > a.input.docs-sourcelink:focus, .is-primary.is-focused.textarea, .docstring > section > a.is-focused.textarea.docs-sourcelink, .is-primary.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .docstring > section > a.is-focused.input.docs-sourcelink, .is-primary.textarea:active, .docstring > section > a.textarea.docs-sourcelink:active, .is-primary.input:active, #documenter .docs-sidebar form.docs-search > input.is-primary:active, .docstring > section > a.input.docs-sourcelink:active, .is-primary.is-active.textarea, .docstring > section > a.is-active.textarea.docs-sourcelink, .is-primary.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active, .docstring > section > a.is-active.input.docs-sourcelink { + box-shadow: 0 0 0 0.125em rgba(78, 181, 222, 0.25); } + .is-link.textarea, .is-link.input, #documenter .docs-sidebar form.docs-search > input.is-link { + border-color: #2e63b8; } + .is-link.textarea:focus, .is-link.input:focus, #documenter .docs-sidebar form.docs-search > input.is-link:focus, .is-link.is-focused.textarea, .is-link.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-link.textarea:active, .is-link.input:active, #documenter .docs-sidebar form.docs-search > input.is-link:active, .is-link.is-active.textarea, .is-link.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(46, 99, 184, 0.25); } + .is-info.textarea, .is-info.input, #documenter .docs-sidebar form.docs-search > input.is-info { + border-color: #209cee; } + .is-info.textarea:focus, .is-info.input:focus, #documenter .docs-sidebar form.docs-search > input.is-info:focus, .is-info.is-focused.textarea, .is-info.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-info.textarea:active, .is-info.input:active, #documenter .docs-sidebar form.docs-search > input.is-info:active, .is-info.is-active.textarea, .is-info.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } + .is-success.textarea, .is-success.input, #documenter .docs-sidebar form.docs-search > input.is-success { + border-color: #22c35b; } + .is-success.textarea:focus, .is-success.input:focus, #documenter .docs-sidebar form.docs-search > input.is-success:focus, .is-success.is-focused.textarea, .is-success.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-success.textarea:active, .is-success.input:active, #documenter .docs-sidebar form.docs-search > input.is-success:active, .is-success.is-active.textarea, .is-success.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(34, 195, 91, 0.25); } + .is-warning.textarea, .is-warning.input, #documenter .docs-sidebar form.docs-search > input.is-warning { + border-color: #ffdd57; } + .is-warning.textarea:focus, .is-warning.input:focus, #documenter .docs-sidebar form.docs-search > input.is-warning:focus, .is-warning.is-focused.textarea, .is-warning.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-warning.textarea:active, .is-warning.input:active, #documenter .docs-sidebar form.docs-search > input.is-warning:active, .is-warning.is-active.textarea, .is-warning.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } + .is-danger.textarea, .is-danger.input, #documenter .docs-sidebar form.docs-search > input.is-danger { + border-color: #da0b00; } + .is-danger.textarea:focus, .is-danger.input:focus, #documenter .docs-sidebar form.docs-search > input.is-danger:focus, .is-danger.is-focused.textarea, .is-danger.is-focused.input, #documenter .docs-sidebar form.docs-search > input.is-focused, .is-danger.textarea:active, .is-danger.input:active, #documenter .docs-sidebar form.docs-search > input.is-danger:active, .is-danger.is-active.textarea, .is-danger.is-active.input, #documenter .docs-sidebar form.docs-search > input.is-active { + box-shadow: 0 0 0 0.125em rgba(218, 11, 0, 0.25); } + .is-small.textarea, .is-small.input, #documenter .docs-sidebar form.docs-search > input { + border-radius: 2px; + font-size: 0.75rem; } + .is-medium.textarea, .is-medium.input, #documenter .docs-sidebar form.docs-search > input.is-medium { + font-size: 1.25rem; } + .is-large.textarea, .is-large.input, #documenter .docs-sidebar form.docs-search > input.is-large { + font-size: 1.5rem; } + .is-fullwidth.textarea, .is-fullwidth.input, #documenter .docs-sidebar form.docs-search > input.is-fullwidth { + display: block; + width: 100%; } + .is-inline.textarea, .is-inline.input, #documenter .docs-sidebar form.docs-search > input.is-inline { + display: inline; + width: auto; } + +.input.is-rounded, #documenter .docs-sidebar form.docs-search > input { + border-radius: 290486px; + padding-left: 1em; + padding-right: 1em; } + +.input.is-static, #documenter .docs-sidebar form.docs-search > input.is-static { + background-color: transparent; + border-color: transparent; + box-shadow: none; + padding-left: 0; + padding-right: 0; } + +.textarea { + display: block; + max-width: 100%; + min-width: 100%; + padding: 0.625em; + resize: vertical; } + .textarea:not([rows]) { + max-height: 600px; + min-height: 120px; } + .textarea[rows] { + height: initial; } + .textarea.has-fixed-size { + resize: none; } + +.radio, .checkbox { + cursor: pointer; + display: inline-block; + line-height: 1.25; + position: relative; } + .radio input, .checkbox input { + cursor: pointer; } + .radio:hover, .checkbox:hover { + color: #363636; } + .radio[disabled], .checkbox[disabled], fieldset[disabled] .radio, fieldset[disabled] .checkbox { + color: #6b6b6b; + cursor: not-allowed; } + +.radio + .radio { + margin-left: 0.5em; } + +.select { + display: inline-block; + max-width: 100%; + position: relative; + vertical-align: top; } + .select:not(.is-multiple) { + height: 2.25em; } + .select:not(.is-multiple):not(.is-loading)::after { + border-color: #2e63b8; + right: 1.125em; + z-index: 4; } + .select.is-rounded select, #documenter .docs-sidebar form.docs-search > input.select select { + border-radius: 290486px; + padding-left: 1em; } + .select select { + cursor: pointer; + display: block; + font-size: 1em; + max-width: 100%; + outline: none; } + .select select::-ms-expand { + display: none; } + .select select[disabled]:hover, fieldset[disabled] .select select:hover { + border-color: whitesmoke; } + .select select:not([multiple]) { + padding-right: 2.5em; } + .select select[multiple] { + height: auto; + padding: 0; } + .select select[multiple] option { + padding: 0.5em 1em; } + .select:not(.is-multiple):not(.is-loading):hover::after { + border-color: #363636; } + .select.is-white:not(:hover)::after { + border-color: white; } + .select.is-white select { + border-color: white; } + .select.is-white select:hover, .select.is-white select.is-hovered { + border-color: #f2f2f2; } + .select.is-white select:focus, .select.is-white select.is-focused, .select.is-white select:active, .select.is-white select.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } + .select.is-black:not(:hover)::after { + border-color: #0a0a0a; } + .select.is-black select { + border-color: #0a0a0a; } + .select.is-black select:hover, .select.is-black select.is-hovered { + border-color: black; } + .select.is-black select:focus, .select.is-black select.is-focused, .select.is-black select:active, .select.is-black select.is-active { + box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } + .select.is-light:not(:hover)::after { + border-color: whitesmoke; } + .select.is-light select { + border-color: whitesmoke; } + .select.is-light select:hover, .select.is-light select.is-hovered { + border-color: #e8e8e8; } + .select.is-light select:focus, .select.is-light select.is-focused, .select.is-light select:active, .select.is-light select.is-active { + box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } + .select.is-dark:not(:hover)::after, .content kbd.select:not(:hover)::after { + border-color: #363636; } + .select.is-dark select, .content kbd.select select { + border-color: #363636; } + .select.is-dark select:hover, .content kbd.select select:hover, .select.is-dark select.is-hovered, .content kbd.select select.is-hovered { + border-color: #292929; } + .select.is-dark select:focus, .content kbd.select select:focus, .select.is-dark select.is-focused, .content kbd.select select.is-focused, .select.is-dark select:active, .content kbd.select select:active, .select.is-dark select.is-active, .content kbd.select select.is-active { + box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } + .select.is-primary:not(:hover)::after, .docstring > section > a.select.docs-sourcelink:not(:hover)::after { + border-color: #4eb5de; } + .select.is-primary select, .docstring > section > a.select.docs-sourcelink select { + border-color: #4eb5de; } + .select.is-primary select:hover, .docstring > section > a.select.docs-sourcelink select:hover, .select.is-primary select.is-hovered, .docstring > section > a.select.docs-sourcelink select.is-hovered { + border-color: #39acda; } + .select.is-primary select:focus, .docstring > section > a.select.docs-sourcelink select:focus, .select.is-primary select.is-focused, .docstring > section > a.select.docs-sourcelink select.is-focused, .select.is-primary select:active, .docstring > section > a.select.docs-sourcelink select:active, .select.is-primary select.is-active, .docstring > section > a.select.docs-sourcelink select.is-active { + box-shadow: 0 0 0 0.125em rgba(78, 181, 222, 0.25); } + .select.is-link:not(:hover)::after { + border-color: #2e63b8; } + .select.is-link select { + border-color: #2e63b8; } + .select.is-link select:hover, .select.is-link select.is-hovered { + border-color: #2958a4; } + .select.is-link select:focus, .select.is-link select.is-focused, .select.is-link select:active, .select.is-link select.is-active { + box-shadow: 0 0 0 0.125em rgba(46, 99, 184, 0.25); } + .select.is-info:not(:hover)::after { + border-color: #209cee; } + .select.is-info select { + border-color: #209cee; } + .select.is-info select:hover, .select.is-info select.is-hovered { + border-color: #1190e3; } + .select.is-info select:focus, .select.is-info select.is-focused, .select.is-info select:active, .select.is-info select.is-active { + box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } + .select.is-success:not(:hover)::after { + border-color: #22c35b; } + .select.is-success select { + border-color: #22c35b; } + .select.is-success select:hover, .select.is-success select.is-hovered { + border-color: #1ead51; } + .select.is-success select:focus, .select.is-success select.is-focused, .select.is-success select:active, .select.is-success select.is-active { + box-shadow: 0 0 0 0.125em rgba(34, 195, 91, 0.25); } + .select.is-warning:not(:hover)::after { + border-color: #ffdd57; } + .select.is-warning select { + border-color: #ffdd57; } + .select.is-warning select:hover, .select.is-warning select.is-hovered { + border-color: #ffd83e; } + .select.is-warning select:focus, .select.is-warning select.is-focused, .select.is-warning select:active, .select.is-warning select.is-active { + box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } + .select.is-danger:not(:hover)::after { + border-color: #da0b00; } + .select.is-danger select { + border-color: #da0b00; } + .select.is-danger select:hover, .select.is-danger select.is-hovered { + border-color: #c10a00; } + .select.is-danger select:focus, .select.is-danger select.is-focused, .select.is-danger select:active, .select.is-danger select.is-active { + box-shadow: 0 0 0 0.125em rgba(218, 11, 0, 0.25); } + .select.is-small, #documenter .docs-sidebar form.docs-search > input.select { + border-radius: 2px; + font-size: 0.75rem; } + .select.is-medium { + font-size: 1.25rem; } + .select.is-large { + font-size: 1.5rem; } + .select.is-disabled::after { + border-color: #6b6b6b; } + .select.is-fullwidth { + width: 100%; } + .select.is-fullwidth select { + width: 100%; } + .select.is-loading::after { + margin-top: 0; + position: absolute; + right: 0.625em; + top: 0.625em; + transform: none; } + .select.is-loading.is-small:after, #documenter .docs-sidebar form.docs-search > input.is-loading:after { + font-size: 0.75rem; } + .select.is-loading.is-medium:after { + font-size: 1.25rem; } + .select.is-loading.is-large:after { + font-size: 1.5rem; } + +.file { + align-items: stretch; + display: flex; + justify-content: flex-start; + position: relative; } + .file.is-white .file-cta { + background-color: white; + border-color: transparent; + color: #0a0a0a; } + .file.is-white:hover .file-cta, .file.is-white.is-hovered .file-cta { + background-color: #f9f9f9; + border-color: transparent; + color: #0a0a0a; } + .file.is-white:focus .file-cta, .file.is-white.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(255, 255, 255, 0.25); + color: #0a0a0a; } + .file.is-white:active .file-cta, .file.is-white.is-active .file-cta { + background-color: #f2f2f2; + border-color: transparent; + color: #0a0a0a; } + .file.is-black .file-cta { + background-color: #0a0a0a; + border-color: transparent; + color: white; } + .file.is-black:hover .file-cta, .file.is-black.is-hovered .file-cta { + background-color: #040404; + border-color: transparent; + color: white; } + .file.is-black:focus .file-cta, .file.is-black.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(10, 10, 10, 0.25); + color: white; } + .file.is-black:active .file-cta, .file.is-black.is-active .file-cta { + background-color: black; + border-color: transparent; + color: white; } + .file.is-light .file-cta { + background-color: whitesmoke; + border-color: transparent; + color: #363636; } + .file.is-light:hover .file-cta, .file.is-light.is-hovered .file-cta { + background-color: #eeeeee; + border-color: transparent; + color: #363636; } + .file.is-light:focus .file-cta, .file.is-light.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(245, 245, 245, 0.25); + color: #363636; } + .file.is-light:active .file-cta, .file.is-light.is-active .file-cta { + background-color: #e8e8e8; + border-color: transparent; + color: #363636; } + .file.is-dark .file-cta, .content kbd.file .file-cta { + background-color: #363636; + border-color: transparent; + color: whitesmoke; } + .file.is-dark:hover .file-cta, .content kbd.file:hover .file-cta, .file.is-dark.is-hovered .file-cta, .content kbd.file.is-hovered .file-cta { + background-color: #2f2f2f; + border-color: transparent; + color: whitesmoke; } + .file.is-dark:focus .file-cta, .content kbd.file:focus .file-cta, .file.is-dark.is-focused .file-cta, .content kbd.file.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(54, 54, 54, 0.25); + color: whitesmoke; } + .file.is-dark:active .file-cta, .content kbd.file:active .file-cta, .file.is-dark.is-active .file-cta, .content kbd.file.is-active .file-cta { + background-color: #292929; + border-color: transparent; + color: whitesmoke; } + .file.is-primary .file-cta, .docstring > section > a.file.docs-sourcelink .file-cta { + background-color: #4eb5de; + border-color: transparent; + color: #fff; } + .file.is-primary:hover .file-cta, .docstring > section > a.file.docs-sourcelink:hover .file-cta, .file.is-primary.is-hovered .file-cta, .docstring > section > a.file.is-hovered.docs-sourcelink .file-cta { + background-color: #43b1dc; + border-color: transparent; + color: #fff; } + .file.is-primary:focus .file-cta, .docstring > section > a.file.docs-sourcelink:focus .file-cta, .file.is-primary.is-focused .file-cta, .docstring > section > a.file.is-focused.docs-sourcelink .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(78, 181, 222, 0.25); + color: #fff; } + .file.is-primary:active .file-cta, .docstring > section > a.file.docs-sourcelink:active .file-cta, .file.is-primary.is-active .file-cta, .docstring > section > a.file.is-active.docs-sourcelink .file-cta { + background-color: #39acda; + border-color: transparent; + color: #fff; } + .file.is-link .file-cta { + background-color: #2e63b8; + border-color: transparent; + color: #fff; } + .file.is-link:hover .file-cta, .file.is-link.is-hovered .file-cta { + background-color: #2b5eae; + border-color: transparent; + color: #fff; } + .file.is-link:focus .file-cta, .file.is-link.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(46, 99, 184, 0.25); + color: #fff; } + .file.is-link:active .file-cta, .file.is-link.is-active .file-cta { + background-color: #2958a4; + border-color: transparent; + color: #fff; } + .file.is-info .file-cta { + background-color: #209cee; + border-color: transparent; + color: #fff; } + .file.is-info:hover .file-cta, .file.is-info.is-hovered .file-cta { + background-color: #1497ed; + border-color: transparent; + color: #fff; } + .file.is-info:focus .file-cta, .file.is-info.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(32, 156, 238, 0.25); + color: #fff; } + .file.is-info:active .file-cta, .file.is-info.is-active .file-cta { + background-color: #1190e3; + border-color: transparent; + color: #fff; } + .file.is-success .file-cta { + background-color: #22c35b; + border-color: transparent; + color: #fff; } + .file.is-success:hover .file-cta, .file.is-success.is-hovered .file-cta { + background-color: #20b856; + border-color: transparent; + color: #fff; } + .file.is-success:focus .file-cta, .file.is-success.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(34, 195, 91, 0.25); + color: #fff; } + .file.is-success:active .file-cta, .file.is-success.is-active .file-cta { + background-color: #1ead51; + border-color: transparent; + color: #fff; } + .file.is-warning .file-cta { + background-color: #ffdd57; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .file.is-warning:hover .file-cta, .file.is-warning.is-hovered .file-cta { + background-color: #ffda4a; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .file.is-warning:focus .file-cta, .file.is-warning.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(255, 221, 87, 0.25); + color: rgba(0, 0, 0, 0.7); } + .file.is-warning:active .file-cta, .file.is-warning.is-active .file-cta { + background-color: #ffd83e; + border-color: transparent; + color: rgba(0, 0, 0, 0.7); } + .file.is-danger .file-cta { + background-color: #da0b00; + border-color: transparent; + color: #fff; } + .file.is-danger:hover .file-cta, .file.is-danger.is-hovered .file-cta { + background-color: #cd0a00; + border-color: transparent; + color: #fff; } + .file.is-danger:focus .file-cta, .file.is-danger.is-focused .file-cta { + border-color: transparent; + box-shadow: 0 0 0.5em rgba(218, 11, 0, 0.25); + color: #fff; } + .file.is-danger:active .file-cta, .file.is-danger.is-active .file-cta { + background-color: #c10a00; + border-color: transparent; + color: #fff; } + .file.is-small, #documenter .docs-sidebar form.docs-search > input.file { + font-size: 0.75rem; } + .file.is-medium { + font-size: 1.25rem; } + .file.is-medium .file-icon .fa { + font-size: 21px; } + .file.is-large { + font-size: 1.5rem; } + .file.is-large .file-icon .fa { + font-size: 28px; } + .file.has-name .file-cta { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + .file.has-name .file-name { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + .file.has-name.is-empty .file-cta { + border-radius: 4px; } + .file.has-name.is-empty .file-name { + display: none; } + .file.is-boxed .file-label { + flex-direction: column; } + .file.is-boxed .file-cta { + flex-direction: column; + height: auto; + padding: 1em 3em; } + .file.is-boxed .file-name { + border-width: 0 1px 1px; } + .file.is-boxed .file-icon { + height: 1.5em; + width: 1.5em; } + .file.is-boxed .file-icon .fa { + font-size: 21px; } + .file.is-boxed.is-small .file-icon .fa, #documenter .docs-sidebar form.docs-search > input.is-boxed .file-icon .fa { + font-size: 14px; } + .file.is-boxed.is-medium .file-icon .fa { + font-size: 28px; } + .file.is-boxed.is-large .file-icon .fa { + font-size: 35px; } + .file.is-boxed.has-name .file-cta { + border-radius: 4px 4px 0 0; } + .file.is-boxed.has-name .file-name { + border-radius: 0 0 4px 4px; + border-width: 0 1px 1px; } + .file.is-centered { + justify-content: center; } + .file.is-fullwidth .file-label { + width: 100%; } + .file.is-fullwidth .file-name { + flex-grow: 1; + max-width: none; } + .file.is-right { + justify-content: flex-end; } + .file.is-right .file-cta { + border-radius: 0 4px 4px 0; } + .file.is-right .file-name { + border-radius: 4px 0 0 4px; + border-width: 1px 0 1px 1px; + order: -1; } + +.file-label { + align-items: stretch; + display: flex; + cursor: pointer; + justify-content: flex-start; + overflow: hidden; + position: relative; } + .file-label:hover .file-cta { + background-color: #eeeeee; + color: #363636; } + .file-label:hover .file-name { + border-color: #d5d5d5; } + .file-label:active .file-cta { + background-color: #e8e8e8; + color: #363636; } + .file-label:active .file-name { + border-color: #cfcfcf; } + +.file-input { + height: 100%; + left: 0; + opacity: 0; + outline: none; + position: absolute; + top: 0; + width: 100%; } + +.file-cta, +.file-name { + border-color: #dbdbdb; + border-radius: 4px; + font-size: 1em; + padding-left: 1em; + padding-right: 1em; + white-space: nowrap; } + +.file-cta { + background-color: whitesmoke; + color: #4a4a4a; } + +.file-name { + border-color: #dbdbdb; + border-style: solid; + border-width: 1px 1px 1px 0; + display: block; + max-width: 16em; + overflow: hidden; + text-align: left; + text-overflow: ellipsis; } + +.file-icon { + align-items: center; + display: flex; + height: 1em; + justify-content: center; + margin-right: 0.5em; + width: 1em; } + .file-icon .fa { + font-size: 14px; } + +.label { + color: #363636; + display: block; + font-size: 1rem; + font-weight: 700; } + .label:not(:last-child) { + margin-bottom: 0.5em; } + .label.is-small, #documenter .docs-sidebar form.docs-search > input.label { + font-size: 0.75rem; } + .label.is-medium { + font-size: 1.25rem; } + .label.is-large { + font-size: 1.5rem; } + +.help { + display: block; + font-size: 0.75rem; + margin-top: 0.25rem; } + .help.is-white { + color: white; } + .help.is-black { + color: #0a0a0a; } + .help.is-light { + color: whitesmoke; } + .help.is-dark, .content kbd.help { + color: #363636; } + .help.is-primary, .docstring > section > a.help.docs-sourcelink { + color: #4eb5de; } + .help.is-link { + color: #2e63b8; } + .help.is-info { + color: #209cee; } + .help.is-success { + color: #22c35b; } + .help.is-warning { + color: #ffdd57; } + .help.is-danger { + color: #da0b00; } + +.field:not(:last-child) { + margin-bottom: 0.75rem; } + +.field.has-addons { + display: flex; + justify-content: flex-start; } + .field.has-addons .control:not(:last-child) { + margin-right: -1px; } + .field.has-addons .control:not(:first-child):not(:last-child) .button, + .field.has-addons .control:not(:first-child):not(:last-child) .input, + .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search > input, + #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search > input, + .field.has-addons .control:not(:first-child):not(:last-child) .select select { + border-radius: 0; } + .field.has-addons .control:first-child:not(:only-child) .button, + .field.has-addons .control:first-child:not(:only-child) .input, + .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search > input, + #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search > input, + .field.has-addons .control:first-child:not(:only-child) .select select { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + .field.has-addons .control:last-child:not(:only-child) .button, + .field.has-addons .control:last-child:not(:only-child) .input, + .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search > input, + #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search > input, + .field.has-addons .control:last-child:not(:only-child) .select select { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + .field.has-addons .control .button:not([disabled]):hover, .field.has-addons .control .button.is-hovered:not([disabled]), + .field.has-addons .control .input:not([disabled]):hover, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):hover, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):hover, + .field.has-addons .control .input.is-hovered:not([disabled]), + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-hovered:not([disabled]), + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-hovered:not([disabled]), + .field.has-addons .control .select select:not([disabled]):hover, + .field.has-addons .control .select select.is-hovered:not([disabled]) { + z-index: 2; } + .field.has-addons .control .button:not([disabled]):focus, .field.has-addons .control .button.is-focused:not([disabled]), .field.has-addons .control .button:not([disabled]):active, .field.has-addons .control .button.is-active:not([disabled]), + .field.has-addons .control .input:not([disabled]):focus, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):focus, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):focus, + .field.has-addons .control .input.is-focused:not([disabled]), + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-focused:not([disabled]), + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-focused:not([disabled]), + .field.has-addons .control .input:not([disabled]):active, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):active, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):active, + .field.has-addons .control .input.is-active:not([disabled]), + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-active:not([disabled]), + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-active:not([disabled]), + .field.has-addons .control .select select:not([disabled]):focus, + .field.has-addons .control .select select.is-focused:not([disabled]), + .field.has-addons .control .select select:not([disabled]):active, + .field.has-addons .control .select select.is-active:not([disabled]) { + z-index: 3; } + .field.has-addons .control .button:not([disabled]):focus:hover, .field.has-addons .control .button.is-focused:not([disabled]):hover, .field.has-addons .control .button:not([disabled]):active:hover, .field.has-addons .control .button.is-active:not([disabled]):hover, + .field.has-addons .control .input:not([disabled]):focus:hover, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):focus:hover, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):focus:hover, + .field.has-addons .control .input.is-focused:not([disabled]):hover, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-focused:not([disabled]):hover, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-focused:not([disabled]):hover, + .field.has-addons .control .input:not([disabled]):active:hover, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input:not([disabled]):active:hover, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input:not([disabled]):active:hover, + .field.has-addons .control .input.is-active:not([disabled]):hover, + .field.has-addons .control #documenter .docs-sidebar form.docs-search > input.is-active:not([disabled]):hover, + #documenter .docs-sidebar .field.has-addons .control form.docs-search > input.is-active:not([disabled]):hover, + .field.has-addons .control .select select:not([disabled]):focus:hover, + .field.has-addons .control .select select.is-focused:not([disabled]):hover, + .field.has-addons .control .select select:not([disabled]):active:hover, + .field.has-addons .control .select select.is-active:not([disabled]):hover { + z-index: 4; } + .field.has-addons .control.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + .field.has-addons.has-addons-centered { + justify-content: center; } + .field.has-addons.has-addons-right { + justify-content: flex-end; } + .field.has-addons.has-addons-fullwidth .control { + flex-grow: 1; + flex-shrink: 0; } + +.field.is-grouped { + display: flex; + justify-content: flex-start; } + .field.is-grouped > .control { + flex-shrink: 0; } + .field.is-grouped > .control:not(:last-child) { + margin-bottom: 0; + margin-right: 0.75rem; } + .field.is-grouped > .control.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + .field.is-grouped.is-grouped-centered { + justify-content: center; } + .field.is-grouped.is-grouped-right { + justify-content: flex-end; } + .field.is-grouped.is-grouped-multiline { + flex-wrap: wrap; } + .field.is-grouped.is-grouped-multiline > .control:last-child, .field.is-grouped.is-grouped-multiline > .control:not(:last-child) { + margin-bottom: 0.75rem; } + .field.is-grouped.is-grouped-multiline:last-child { + margin-bottom: -0.75rem; } + .field.is-grouped.is-grouped-multiline:not(:last-child) { + margin-bottom: 0; } + +@media screen and (min-width: 769px), print { + .field.is-horizontal { + display: flex; } } + +.field-label .label { + font-size: inherit; } + +@media screen and (max-width: 768px) { + .field-label { + margin-bottom: 0.5rem; } } + +@media screen and (min-width: 769px), print { + .field-label { + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + margin-right: 1.5rem; + text-align: right; } + .field-label.is-small, #documenter .docs-sidebar form.docs-search > input.field-label { + font-size: 0.75rem; + padding-top: 0.375em; } + .field-label.is-normal { + padding-top: 0.375em; } + .field-label.is-medium { + font-size: 1.25rem; + padding-top: 0.375em; } + .field-label.is-large { + font-size: 1.5rem; + padding-top: 0.375em; } } + +.field-body .field .field { + margin-bottom: 0; } + +@media screen and (min-width: 769px), print { + .field-body { + display: flex; + flex-basis: 0; + flex-grow: 5; + flex-shrink: 1; } + .field-body .field { + margin-bottom: 0; } + .field-body > .field { + flex-shrink: 1; } + .field-body > .field:not(.is-narrow) { + flex-grow: 1; } + .field-body > .field:not(:last-child) { + margin-right: 0.75rem; } } + +.control { + box-sizing: border-box; + clear: both; + font-size: 1rem; + position: relative; + text-align: left; } + .control.has-icons-left .input:focus ~ .icon, .control.has-icons-left #documenter .docs-sidebar form.docs-search > input:focus ~ .icon, #documenter .docs-sidebar .control.has-icons-left form.docs-search > input:focus ~ .icon, + .control.has-icons-left .select:focus ~ .icon, .control.has-icons-right .input:focus ~ .icon, .control.has-icons-right #documenter .docs-sidebar form.docs-search > input:focus ~ .icon, #documenter .docs-sidebar .control.has-icons-right form.docs-search > input:focus ~ .icon, + .control.has-icons-right .select:focus ~ .icon { + color: #6b6b6b; } + .control.has-icons-left .input.is-small ~ .icon, .control.has-icons-left #documenter .docs-sidebar form.docs-search > input ~ .icon, #documenter .docs-sidebar .control.has-icons-left form.docs-search > input ~ .icon, + .control.has-icons-left .select.is-small ~ .icon, .control.has-icons-right .input.is-small ~ .icon, .control.has-icons-right #documenter .docs-sidebar form.docs-search > input ~ .icon, #documenter .docs-sidebar .control.has-icons-right form.docs-search > input ~ .icon, + .control.has-icons-right .select.is-small ~ .icon { + font-size: 0.75rem; } + .control.has-icons-left .input.is-medium ~ .icon, .control.has-icons-left #documenter .docs-sidebar form.docs-search > input.is-medium ~ .icon, #documenter .docs-sidebar .control.has-icons-left form.docs-search > input.is-medium ~ .icon, + .control.has-icons-left .select.is-medium ~ .icon, .control.has-icons-right .input.is-medium ~ .icon, .control.has-icons-right #documenter .docs-sidebar form.docs-search > input.is-medium ~ .icon, #documenter .docs-sidebar .control.has-icons-right form.docs-search > input.is-medium ~ .icon, + .control.has-icons-right .select.is-medium ~ .icon { + font-size: 1.25rem; } + .control.has-icons-left .input.is-large ~ .icon, .control.has-icons-left #documenter .docs-sidebar form.docs-search > input.is-large ~ .icon, #documenter .docs-sidebar .control.has-icons-left form.docs-search > input.is-large ~ .icon, + .control.has-icons-left .select.is-large ~ .icon, .control.has-icons-right .input.is-large ~ .icon, .control.has-icons-right #documenter .docs-sidebar form.docs-search > input.is-large ~ .icon, #documenter .docs-sidebar .control.has-icons-right form.docs-search > input.is-large ~ .icon, + .control.has-icons-right .select.is-large ~ .icon { + font-size: 1.5rem; } + .control.has-icons-left .icon, .control.has-icons-right .icon { + color: #dbdbdb; + height: 2.25em; + pointer-events: none; + position: absolute; + top: 0; + width: 2.25em; + z-index: 4; } + .control.has-icons-left .input, .control.has-icons-left #documenter .docs-sidebar form.docs-search > input, #documenter .docs-sidebar .control.has-icons-left form.docs-search > input, + .control.has-icons-left .select select { + padding-left: 2.25em; } + .control.has-icons-left .icon.is-left { + left: 0; } + .control.has-icons-right .input, .control.has-icons-right #documenter .docs-sidebar form.docs-search > input, #documenter .docs-sidebar .control.has-icons-right form.docs-search > input, + .control.has-icons-right .select select { + padding-right: 2.25em; } + .control.has-icons-right .icon.is-right { + right: 0; } + .control.is-loading::after { + position: absolute !important; + right: 0.625em; + top: 0.625em; + z-index: 4; } + .control.is-loading.is-small:after, #documenter .docs-sidebar form.docs-search > input.is-loading:after { + font-size: 0.75rem; } + .control.is-loading.is-medium:after { + font-size: 1.25rem; } + .control.is-loading.is-large:after { + font-size: 1.5rem; } + +.breadcrumb { + font-size: 1rem; + white-space: nowrap; } + .breadcrumb a { + align-items: center; + color: #2e63b8; + display: flex; + justify-content: center; + padding: 0 0.75em; } + .breadcrumb a:hover { + color: #363636; } + .breadcrumb li { + align-items: center; + display: flex; } + .breadcrumb li:first-child a { + padding-left: 0; } + .breadcrumb li.is-active a { + color: #222222; + cursor: default; + pointer-events: none; } + .breadcrumb li + li::before { + color: #b5b5b5; + content: "\0002f"; } + .breadcrumb ul, + .breadcrumb ol { + align-items: flex-start; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; } + .breadcrumb .icon:first-child { + margin-right: 0.5em; } + .breadcrumb .icon:last-child { + margin-left: 0.5em; } + .breadcrumb.is-centered ol, + .breadcrumb.is-centered ul { + justify-content: center; } + .breadcrumb.is-right ol, + .breadcrumb.is-right ul { + justify-content: flex-end; } + .breadcrumb.is-small, #documenter .docs-sidebar form.docs-search > input.breadcrumb { + font-size: 0.75rem; } + .breadcrumb.is-medium { + font-size: 1.25rem; } + .breadcrumb.is-large { + font-size: 1.5rem; } + .breadcrumb.has-arrow-separator li + li::before { + content: "\02192"; } + .breadcrumb.has-bullet-separator li + li::before { + content: "\02022"; } + .breadcrumb.has-dot-separator li + li::before { + content: "\000b7"; } + .breadcrumb.has-succeeds-separator li + li::before { + content: "\0227B"; } + +.card { + background-color: white; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + color: #222222; + max-width: 100%; + position: relative; } + +.card-header { + background-color: transparent; + align-items: stretch; + box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1); + display: flex; } + +.card-header-title { + align-items: center; + color: #222222; + display: flex; + flex-grow: 1; + font-weight: 700; + padding: 0.75rem; } + .card-header-title.is-centered { + justify-content: center; } + +.card-header-icon { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + padding: 0.75rem; } + +.card-image { + display: block; + position: relative; } + +.card-content { + background-color: transparent; + padding: 1.5rem; } + +.card-footer { + background-color: transparent; + border-top: 1px solid #dbdbdb; + align-items: stretch; + display: flex; } + +.card-footer-item { + align-items: center; + display: flex; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + justify-content: center; + padding: 0.75rem; } + .card-footer-item:not(:last-child) { + border-right: 1px solid #dbdbdb; } + +.card .media:not(:last-child) { + margin-bottom: 1.5rem; } + +.dropdown { + display: inline-flex; + position: relative; + vertical-align: top; } + .dropdown.is-active .dropdown-menu, .dropdown.is-hoverable:hover .dropdown-menu { + display: block; } + .dropdown.is-right .dropdown-menu { + left: auto; + right: 0; } + .dropdown.is-up .dropdown-menu { + bottom: 100%; + padding-bottom: 4px; + padding-top: initial; + top: auto; } + +.dropdown-menu { + display: none; + left: 0; + min-width: 12rem; + padding-top: 4px; + position: absolute; + top: 100%; + z-index: 20; } + +.dropdown-content { + background-color: white; + border-radius: 4px; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + padding-bottom: 0.5rem; + padding-top: 0.5rem; } + +.dropdown-item { + color: #4a4a4a; + display: block; + font-size: 0.875rem; + line-height: 1.5; + padding: 0.375rem 1rem; + position: relative; } + +a.dropdown-item, +button.dropdown-item { + padding-right: 3rem; + text-align: left; + white-space: nowrap; + width: 100%; } + a.dropdown-item:hover, + button.dropdown-item:hover { + background-color: whitesmoke; + color: #0a0a0a; } + a.dropdown-item.is-active, + button.dropdown-item.is-active { + background-color: #2e63b8; + color: #fff; } + +.dropdown-divider { + background-color: #dbdbdb; + border: none; + display: block; + height: 1px; + margin: 0.5rem 0; } + +.level { + align-items: center; + justify-content: space-between; } + .level code { + border-radius: 4px; } + .level img { + display: inline-block; + vertical-align: top; } + .level.is-mobile { + display: flex; } + .level.is-mobile .level-left, + .level.is-mobile .level-right { + display: flex; } + .level.is-mobile .level-left + .level-right { + margin-top: 0; } + .level.is-mobile .level-item:not(:last-child) { + margin-bottom: 0; + margin-right: 0.75rem; } + .level.is-mobile .level-item:not(.is-narrow) { + flex-grow: 1; } + @media screen and (min-width: 769px), print { + .level { + display: flex; } + .level > .level-item:not(.is-narrow) { + flex-grow: 1; } } +.level-item { + align-items: center; + display: flex; + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; } + .level-item .title, + .level-item .subtitle { + margin-bottom: 0; } + @media screen and (max-width: 768px) { + .level-item:not(:last-child) { + margin-bottom: 0.75rem; } } +.level-left, +.level-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; } + .level-left .level-item.is-flexible, + .level-right .level-item.is-flexible { + flex-grow: 1; } + @media screen and (min-width: 769px), print { + .level-left .level-item:not(:last-child), + .level-right .level-item:not(:last-child) { + margin-right: 0.75rem; } } +.level-left { + align-items: center; + justify-content: flex-start; } + @media screen and (max-width: 768px) { + .level-left + .level-right { + margin-top: 1.5rem; } } + @media screen and (min-width: 769px), print { + .level-left { + display: flex; } } +.level-right { + align-items: center; + justify-content: flex-end; } + @media screen and (min-width: 769px), print { + .level-right { + display: flex; } } +.list { + background-color: white; + border-radius: 4px; + box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); } + +.list-item { + display: block; + padding: 0.5em 1em; } + .list-item:not(a) { + color: #222222; } + .list-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; } + .list-item:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; } + .list-item:not(:last-child) { + border-bottom: 1px solid #dbdbdb; } + .list-item.is-active { + background-color: #2e63b8; + color: #fff; } + +a.list-item { + background-color: whitesmoke; + cursor: pointer; } + +.media { + align-items: flex-start; + display: flex; + text-align: left; } + .media .content:not(:last-child) { + margin-bottom: 0.75rem; } + .media .media { + border-top: 1px solid rgba(219, 219, 219, 0.5); + display: flex; + padding-top: 0.75rem; } + .media .media .content:not(:last-child), + .media .media .control:not(:last-child) { + margin-bottom: 0.5rem; } + .media .media .media { + padding-top: 0.5rem; } + .media .media .media + .media { + margin-top: 0.5rem; } + .media + .media { + border-top: 1px solid rgba(219, 219, 219, 0.5); + margin-top: 1rem; + padding-top: 1rem; } + .media.is-large + .media { + margin-top: 1.5rem; + padding-top: 1.5rem; } + +.media-left, +.media-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; } + +.media-left { + margin-right: 1rem; } + +.media-right { + margin-left: 1rem; } + +.media-content { + flex-basis: auto; + flex-grow: 1; + flex-shrink: 1; + text-align: left; } + +@media screen and (max-width: 768px) { + .media-content { + overflow-x: auto; } } + +.menu { + font-size: 1rem; } + .menu.is-small, #documenter .docs-sidebar form.docs-search > input.menu { + font-size: 0.75rem; } + .menu.is-medium { + font-size: 1.25rem; } + .menu.is-large { + font-size: 1.5rem; } + +.menu-list { + line-height: 1.25; } + .menu-list a { + border-radius: 2px; + color: #222222; + display: block; + padding: 0.5em 0.75em; } + .menu-list a:hover { + background-color: whitesmoke; + color: #222222; } + .menu-list a.is-active { + background-color: #2e63b8; + color: #fff; } + .menu-list li ul { + border-left: 1px solid #dbdbdb; + margin: 0.75em; + padding-left: 0.75em; } + +.menu-label { + color: #6b6b6b; + font-size: 0.75em; + letter-spacing: 0.1em; + text-transform: uppercase; } + .menu-label:not(:first-child) { + margin-top: 1em; } + .menu-label:not(:last-child) { + margin-bottom: 1em; } + +.message { + background-color: whitesmoke; + border-radius: 4px; + font-size: 1rem; } + .message strong { + color: currentColor; } + .message a:not(.button):not(.tag):not(.dropdown-item) { + color: currentColor; + text-decoration: underline; } + .message.is-small, #documenter .docs-sidebar form.docs-search > input.message { + font-size: 0.75rem; } + .message.is-medium { + font-size: 1.25rem; } + .message.is-large { + font-size: 1.5rem; } + .message.is-white { + background-color: white; } + .message.is-white .message-header { + background-color: white; + color: #0a0a0a; } + .message.is-white .message-body { + border-color: white; + color: #4d4d4d; } + .message.is-black { + background-color: #fafafa; } + .message.is-black .message-header { + background-color: #0a0a0a; + color: white; } + .message.is-black .message-body { + border-color: #0a0a0a; + color: #090909; } + .message.is-light { + background-color: #fafafa; } + .message.is-light .message-header { + background-color: whitesmoke; + color: #363636; } + .message.is-light .message-body { + border-color: whitesmoke; + color: #505050; } + .message.is-dark, .content kbd.message { + background-color: #fafafa; } + .message.is-dark .message-header, .content kbd.message .message-header { + background-color: #363636; + color: whitesmoke; } + .message.is-dark .message-body, .content kbd.message .message-body { + border-color: #363636; + color: #2a2a2a; } + .message.is-primary, .docstring > section > a.message.docs-sourcelink { + background-color: #f6fbfd; } + .message.is-primary .message-header, .docstring > section > a.message.docs-sourcelink .message-header { + background-color: #4eb5de; + color: #fff; } + .message.is-primary .message-body, .docstring > section > a.message.docs-sourcelink .message-body { + border-color: #4eb5de; + color: #1f556a; } + .message.is-link { + background-color: #f7f9fd; } + .message.is-link .message-header { + background-color: #2e63b8; + color: #fff; } + .message.is-link .message-body { + border-color: #2e63b8; + color: #264981; } + .message.is-info { + background-color: #f6fbfe; } + .message.is-info .message-header { + background-color: #209cee; + color: #fff; } + .message.is-info .message-body { + border-color: #209cee; + color: #12537d; } + .message.is-success { + background-color: #f6fdf9; } + .message.is-success .message-header { + background-color: #22c35b; + color: #fff; } + .message.is-success .message-body { + border-color: #22c35b; + color: #0f361d; } + .message.is-warning { + background-color: #fffdf5; } + .message.is-warning .message-header { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .message.is-warning .message-body { + border-color: #ffdd57; + color: #3c3108; } + .message.is-danger { + background-color: #fff5f5; } + .message.is-danger .message-header { + background-color: #da0b00; + color: #fff; } + .message.is-danger .message-body { + border-color: #da0b00; + color: #9b0c04; } + +.message-header { + align-items: center; + background-color: #222222; + border-radius: 4px 4px 0 0; + color: #fff; + display: flex; + font-weight: 700; + justify-content: space-between; + line-height: 1.25; + padding: 0.75em 1em; + position: relative; } + .message-header .delete { + flex-grow: 0; + flex-shrink: 0; + margin-left: 0.75em; } + .message-header + .message-body { + border-width: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.message-body { + border-color: #dbdbdb; + border-radius: 4px; + border-style: solid; + border-width: 0 0 0 4px; + color: #222222; + padding: 1.25em 1.5em; } + .message-body code, + .message-body pre { + background-color: white; } + .message-body pre code { + background-color: transparent; } + +.modal { + align-items: center; + display: none; + flex-direction: column; + justify-content: center; + overflow: hidden; + position: fixed; + z-index: 40; } + .modal.is-active { + display: flex; } + +.modal-background { + background-color: rgba(10, 10, 10, 0.86); } + +.modal-content, +.modal-card { + margin: 0 20px; + max-height: calc(100vh - 160px); + overflow: auto; + position: relative; + width: 100%; } + @media screen and (min-width: 769px), print { + .modal-content, + .modal-card { + margin: 0 auto; + max-height: calc(100vh - 40px); + width: 640px; } } +.modal-close { + background: none; + height: 40px; + position: fixed; + right: 20px; + top: 20px; + width: 40px; } + +.modal-card { + display: flex; + flex-direction: column; + max-height: calc(100vh - 40px); + overflow: hidden; + -ms-overflow-y: visible; } + +.modal-card-head, +.modal-card-foot { + align-items: center; + background-color: whitesmoke; + display: flex; + flex-shrink: 0; + justify-content: flex-start; + padding: 20px; + position: relative; } + +.modal-card-head { + border-bottom: 1px solid #dbdbdb; + border-top-left-radius: 6px; + border-top-right-radius: 6px; } + +.modal-card-title { + color: #222222; + flex-grow: 1; + flex-shrink: 0; + font-size: 1.5rem; + line-height: 1; } + +.modal-card-foot { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + border-top: 1px solid #dbdbdb; } + .modal-card-foot .button:not(:last-child) { + margin-right: 0.5em; } + +.modal-card-body { + -webkit-overflow-scrolling: touch; + background-color: white; + flex-grow: 1; + flex-shrink: 1; + overflow: auto; + padding: 20px; } + +.navbar { + background-color: white; + min-height: 3.25rem; + position: relative; + z-index: 30; } + .navbar.is-white { + background-color: white; + color: #0a0a0a; } + .navbar.is-white .navbar-brand > .navbar-item, + .navbar.is-white .navbar-brand .navbar-link { + color: #0a0a0a; } + .navbar.is-white .navbar-brand > a.navbar-item:focus, .navbar.is-white .navbar-brand > a.navbar-item:hover, .navbar.is-white .navbar-brand > a.navbar-item.is-active, + .navbar.is-white .navbar-brand .navbar-link:focus, + .navbar.is-white .navbar-brand .navbar-link:hover, + .navbar.is-white .navbar-brand .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + .navbar.is-white .navbar-brand .navbar-link::after { + border-color: #0a0a0a; } + .navbar.is-white .navbar-burger { + color: #0a0a0a; } + @media screen and (min-width: 1056px) { + .navbar.is-white .navbar-start > .navbar-item, + .navbar.is-white .navbar-start .navbar-link, + .navbar.is-white .navbar-end > .navbar-item, + .navbar.is-white .navbar-end .navbar-link { + color: #0a0a0a; } + .navbar.is-white .navbar-start > a.navbar-item:focus, .navbar.is-white .navbar-start > a.navbar-item:hover, .navbar.is-white .navbar-start > a.navbar-item.is-active, + .navbar.is-white .navbar-start .navbar-link:focus, + .navbar.is-white .navbar-start .navbar-link:hover, + .navbar.is-white .navbar-start .navbar-link.is-active, + .navbar.is-white .navbar-end > a.navbar-item:focus, + .navbar.is-white .navbar-end > a.navbar-item:hover, + .navbar.is-white .navbar-end > a.navbar-item.is-active, + .navbar.is-white .navbar-end .navbar-link:focus, + .navbar.is-white .navbar-end .navbar-link:hover, + .navbar.is-white .navbar-end .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + .navbar.is-white .navbar-start .navbar-link::after, + .navbar.is-white .navbar-end .navbar-link::after { + border-color: #0a0a0a; } + .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #f2f2f2; + color: #0a0a0a; } + .navbar.is-white .navbar-dropdown a.navbar-item.is-active { + background-color: white; + color: #0a0a0a; } } + .navbar.is-black { + background-color: #0a0a0a; + color: white; } + .navbar.is-black .navbar-brand > .navbar-item, + .navbar.is-black .navbar-brand .navbar-link { + color: white; } + .navbar.is-black .navbar-brand > a.navbar-item:focus, .navbar.is-black .navbar-brand > a.navbar-item:hover, .navbar.is-black .navbar-brand > a.navbar-item.is-active, + .navbar.is-black .navbar-brand .navbar-link:focus, + .navbar.is-black .navbar-brand .navbar-link:hover, + .navbar.is-black .navbar-brand .navbar-link.is-active { + background-color: black; + color: white; } + .navbar.is-black .navbar-brand .navbar-link::after { + border-color: white; } + .navbar.is-black .navbar-burger { + color: white; } + @media screen and (min-width: 1056px) { + .navbar.is-black .navbar-start > .navbar-item, + .navbar.is-black .navbar-start .navbar-link, + .navbar.is-black .navbar-end > .navbar-item, + .navbar.is-black .navbar-end .navbar-link { + color: white; } + .navbar.is-black .navbar-start > a.navbar-item:focus, .navbar.is-black .navbar-start > a.navbar-item:hover, .navbar.is-black .navbar-start > a.navbar-item.is-active, + .navbar.is-black .navbar-start .navbar-link:focus, + .navbar.is-black .navbar-start .navbar-link:hover, + .navbar.is-black .navbar-start .navbar-link.is-active, + .navbar.is-black .navbar-end > a.navbar-item:focus, + .navbar.is-black .navbar-end > a.navbar-item:hover, + .navbar.is-black .navbar-end > a.navbar-item.is-active, + .navbar.is-black .navbar-end .navbar-link:focus, + .navbar.is-black .navbar-end .navbar-link:hover, + .navbar.is-black .navbar-end .navbar-link.is-active { + background-color: black; + color: white; } + .navbar.is-black .navbar-start .navbar-link::after, + .navbar.is-black .navbar-end .navbar-link::after { + border-color: white; } + .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link { + background-color: black; + color: white; } + .navbar.is-black .navbar-dropdown a.navbar-item.is-active { + background-color: #0a0a0a; + color: white; } } + .navbar.is-light { + background-color: whitesmoke; + color: #363636; } + .navbar.is-light .navbar-brand > .navbar-item, + .navbar.is-light .navbar-brand .navbar-link { + color: #363636; } + .navbar.is-light .navbar-brand > a.navbar-item:focus, .navbar.is-light .navbar-brand > a.navbar-item:hover, .navbar.is-light .navbar-brand > a.navbar-item.is-active, + .navbar.is-light .navbar-brand .navbar-link:focus, + .navbar.is-light .navbar-brand .navbar-link:hover, + .navbar.is-light .navbar-brand .navbar-link.is-active { + background-color: #e8e8e8; + color: #363636; } + .navbar.is-light .navbar-brand .navbar-link::after { + border-color: #363636; } + .navbar.is-light .navbar-burger { + color: #363636; } + @media screen and (min-width: 1056px) { + .navbar.is-light .navbar-start > .navbar-item, + .navbar.is-light .navbar-start .navbar-link, + .navbar.is-light .navbar-end > .navbar-item, + .navbar.is-light .navbar-end .navbar-link { + color: #363636; } + .navbar.is-light .navbar-start > a.navbar-item:focus, .navbar.is-light .navbar-start > a.navbar-item:hover, .navbar.is-light .navbar-start > a.navbar-item.is-active, + .navbar.is-light .navbar-start .navbar-link:focus, + .navbar.is-light .navbar-start .navbar-link:hover, + .navbar.is-light .navbar-start .navbar-link.is-active, + .navbar.is-light .navbar-end > a.navbar-item:focus, + .navbar.is-light .navbar-end > a.navbar-item:hover, + .navbar.is-light .navbar-end > a.navbar-item.is-active, + .navbar.is-light .navbar-end .navbar-link:focus, + .navbar.is-light .navbar-end .navbar-link:hover, + .navbar.is-light .navbar-end .navbar-link.is-active { + background-color: #e8e8e8; + color: #363636; } + .navbar.is-light .navbar-start .navbar-link::after, + .navbar.is-light .navbar-end .navbar-link::after { + border-color: #363636; } + .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #e8e8e8; + color: #363636; } + .navbar.is-light .navbar-dropdown a.navbar-item.is-active { + background-color: whitesmoke; + color: #363636; } } + .navbar.is-dark, .content kbd.navbar { + background-color: #363636; + color: whitesmoke; } + .navbar.is-dark .navbar-brand > .navbar-item, .content kbd.navbar .navbar-brand > .navbar-item, + .navbar.is-dark .navbar-brand .navbar-link, + .content kbd.navbar .navbar-brand .navbar-link { + color: whitesmoke; } + .navbar.is-dark .navbar-brand > a.navbar-item:focus, .content kbd.navbar .navbar-brand > a.navbar-item:focus, .navbar.is-dark .navbar-brand > a.navbar-item:hover, .content kbd.navbar .navbar-brand > a.navbar-item:hover, .navbar.is-dark .navbar-brand > a.navbar-item.is-active, .content kbd.navbar .navbar-brand > a.navbar-item.is-active, + .navbar.is-dark .navbar-brand .navbar-link:focus, + .content kbd.navbar .navbar-brand .navbar-link:focus, + .navbar.is-dark .navbar-brand .navbar-link:hover, + .content kbd.navbar .navbar-brand .navbar-link:hover, + .navbar.is-dark .navbar-brand .navbar-link.is-active, + .content kbd.navbar .navbar-brand .navbar-link.is-active { + background-color: #292929; + color: whitesmoke; } + .navbar.is-dark .navbar-brand .navbar-link::after, .content kbd.navbar .navbar-brand .navbar-link::after { + border-color: whitesmoke; } + .navbar.is-dark .navbar-burger, .content kbd.navbar .navbar-burger { + color: whitesmoke; } + @media screen and (min-width: 1056px) { + .navbar.is-dark .navbar-start > .navbar-item, .content kbd.navbar .navbar-start > .navbar-item, + .navbar.is-dark .navbar-start .navbar-link, + .content kbd.navbar .navbar-start .navbar-link, + .navbar.is-dark .navbar-end > .navbar-item, + .content kbd.navbar .navbar-end > .navbar-item, + .navbar.is-dark .navbar-end .navbar-link, + .content kbd.navbar .navbar-end .navbar-link { + color: whitesmoke; } + .navbar.is-dark .navbar-start > a.navbar-item:focus, .content kbd.navbar .navbar-start > a.navbar-item:focus, .navbar.is-dark .navbar-start > a.navbar-item:hover, .content kbd.navbar .navbar-start > a.navbar-item:hover, .navbar.is-dark .navbar-start > a.navbar-item.is-active, .content kbd.navbar .navbar-start > a.navbar-item.is-active, + .navbar.is-dark .navbar-start .navbar-link:focus, + .content kbd.navbar .navbar-start .navbar-link:focus, + .navbar.is-dark .navbar-start .navbar-link:hover, + .content kbd.navbar .navbar-start .navbar-link:hover, + .navbar.is-dark .navbar-start .navbar-link.is-active, + .content kbd.navbar .navbar-start .navbar-link.is-active, + .navbar.is-dark .navbar-end > a.navbar-item:focus, + .content kbd.navbar .navbar-end > a.navbar-item:focus, + .navbar.is-dark .navbar-end > a.navbar-item:hover, + .content kbd.navbar .navbar-end > a.navbar-item:hover, + .navbar.is-dark .navbar-end > a.navbar-item.is-active, + .content kbd.navbar .navbar-end > a.navbar-item.is-active, + .navbar.is-dark .navbar-end .navbar-link:focus, + .content kbd.navbar .navbar-end .navbar-link:focus, + .navbar.is-dark .navbar-end .navbar-link:hover, + .content kbd.navbar .navbar-end .navbar-link:hover, + .navbar.is-dark .navbar-end .navbar-link.is-active, + .content kbd.navbar .navbar-end .navbar-link.is-active { + background-color: #292929; + color: whitesmoke; } + .navbar.is-dark .navbar-start .navbar-link::after, .content kbd.navbar .navbar-start .navbar-link::after, + .navbar.is-dark .navbar-end .navbar-link::after, + .content kbd.navbar .navbar-end .navbar-link::after { + border-color: whitesmoke; } + .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link, .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link, + .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link, + .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #292929; + color: whitesmoke; } + .navbar.is-dark .navbar-dropdown a.navbar-item.is-active, .content kbd.navbar .navbar-dropdown a.navbar-item.is-active { + background-color: #363636; + color: whitesmoke; } } + .navbar.is-primary, .docstring > section > a.navbar.docs-sourcelink { + background-color: #4eb5de; + color: #fff; } + .navbar.is-primary .navbar-brand > .navbar-item, .docstring > section > a.navbar.docs-sourcelink .navbar-brand > .navbar-item, + .navbar.is-primary .navbar-brand .navbar-link, + .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link { + color: #fff; } + .navbar.is-primary .navbar-brand > a.navbar-item:focus, .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item:focus, .navbar.is-primary .navbar-brand > a.navbar-item:hover, .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item:hover, .navbar.is-primary .navbar-brand > a.navbar-item.is-active, .docstring > section > a.navbar.docs-sourcelink .navbar-brand > a.navbar-item.is-active, + .navbar.is-primary .navbar-brand .navbar-link:focus, + .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus, + .navbar.is-primary .navbar-brand .navbar-link:hover, + .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover, + .navbar.is-primary .navbar-brand .navbar-link.is-active, + .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active { + background-color: #39acda; + color: #fff; } + .navbar.is-primary .navbar-brand .navbar-link::after, .docstring > section > a.navbar.docs-sourcelink .navbar-brand .navbar-link::after { + border-color: #fff; } + .navbar.is-primary .navbar-burger, .docstring > section > a.navbar.docs-sourcelink .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + .navbar.is-primary .navbar-start > .navbar-item, .docstring > section > a.navbar.docs-sourcelink .navbar-start > .navbar-item, + .navbar.is-primary .navbar-start .navbar-link, + .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link, + .navbar.is-primary .navbar-end > .navbar-item, + .docstring > section > a.navbar.docs-sourcelink .navbar-end > .navbar-item, + .navbar.is-primary .navbar-end .navbar-link, + .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link { + color: #fff; } + .navbar.is-primary .navbar-start > a.navbar-item:focus, .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item:focus, .navbar.is-primary .navbar-start > a.navbar-item:hover, .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item:hover, .navbar.is-primary .navbar-start > a.navbar-item.is-active, .docstring > section > a.navbar.docs-sourcelink .navbar-start > a.navbar-item.is-active, + .navbar.is-primary .navbar-start .navbar-link:focus, + .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link:focus, + .navbar.is-primary .navbar-start .navbar-link:hover, + .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link:hover, + .navbar.is-primary .navbar-start .navbar-link.is-active, + .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active, + .navbar.is-primary .navbar-end > a.navbar-item:focus, + .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item:focus, + .navbar.is-primary .navbar-end > a.navbar-item:hover, + .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item:hover, + .navbar.is-primary .navbar-end > a.navbar-item.is-active, + .docstring > section > a.navbar.docs-sourcelink .navbar-end > a.navbar-item.is-active, + .navbar.is-primary .navbar-end .navbar-link:focus, + .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link:focus, + .navbar.is-primary .navbar-end .navbar-link:hover, + .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link:hover, + .navbar.is-primary .navbar-end .navbar-link.is-active, + .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active { + background-color: #39acda; + color: #fff; } + .navbar.is-primary .navbar-start .navbar-link::after, .docstring > section > a.navbar.docs-sourcelink .navbar-start .navbar-link::after, + .navbar.is-primary .navbar-end .navbar-link::after, + .docstring > section > a.navbar.docs-sourcelink .navbar-end .navbar-link::after { + border-color: #fff; } + .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link, .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link, + .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link, + .docstring > section > a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #39acda; + color: #fff; } + .navbar.is-primary .navbar-dropdown a.navbar-item.is-active, .docstring > section > a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active { + background-color: #4eb5de; + color: #fff; } } + .navbar.is-link { + background-color: #2e63b8; + color: #fff; } + .navbar.is-link .navbar-brand > .navbar-item, + .navbar.is-link .navbar-brand .navbar-link { + color: #fff; } + .navbar.is-link .navbar-brand > a.navbar-item:focus, .navbar.is-link .navbar-brand > a.navbar-item:hover, .navbar.is-link .navbar-brand > a.navbar-item.is-active, + .navbar.is-link .navbar-brand .navbar-link:focus, + .navbar.is-link .navbar-brand .navbar-link:hover, + .navbar.is-link .navbar-brand .navbar-link.is-active { + background-color: #2958a4; + color: #fff; } + .navbar.is-link .navbar-brand .navbar-link::after { + border-color: #fff; } + .navbar.is-link .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + .navbar.is-link .navbar-start > .navbar-item, + .navbar.is-link .navbar-start .navbar-link, + .navbar.is-link .navbar-end > .navbar-item, + .navbar.is-link .navbar-end .navbar-link { + color: #fff; } + .navbar.is-link .navbar-start > a.navbar-item:focus, .navbar.is-link .navbar-start > a.navbar-item:hover, .navbar.is-link .navbar-start > a.navbar-item.is-active, + .navbar.is-link .navbar-start .navbar-link:focus, + .navbar.is-link .navbar-start .navbar-link:hover, + .navbar.is-link .navbar-start .navbar-link.is-active, + .navbar.is-link .navbar-end > a.navbar-item:focus, + .navbar.is-link .navbar-end > a.navbar-item:hover, + .navbar.is-link .navbar-end > a.navbar-item.is-active, + .navbar.is-link .navbar-end .navbar-link:focus, + .navbar.is-link .navbar-end .navbar-link:hover, + .navbar.is-link .navbar-end .navbar-link.is-active { + background-color: #2958a4; + color: #fff; } + .navbar.is-link .navbar-start .navbar-link::after, + .navbar.is-link .navbar-end .navbar-link::after { + border-color: #fff; } + .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #2958a4; + color: #fff; } + .navbar.is-link .navbar-dropdown a.navbar-item.is-active { + background-color: #2e63b8; + color: #fff; } } + .navbar.is-info { + background-color: #209cee; + color: #fff; } + .navbar.is-info .navbar-brand > .navbar-item, + .navbar.is-info .navbar-brand .navbar-link { + color: #fff; } + .navbar.is-info .navbar-brand > a.navbar-item:focus, .navbar.is-info .navbar-brand > a.navbar-item:hover, .navbar.is-info .navbar-brand > a.navbar-item.is-active, + .navbar.is-info .navbar-brand .navbar-link:focus, + .navbar.is-info .navbar-brand .navbar-link:hover, + .navbar.is-info .navbar-brand .navbar-link.is-active { + background-color: #1190e3; + color: #fff; } + .navbar.is-info .navbar-brand .navbar-link::after { + border-color: #fff; } + .navbar.is-info .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + .navbar.is-info .navbar-start > .navbar-item, + .navbar.is-info .navbar-start .navbar-link, + .navbar.is-info .navbar-end > .navbar-item, + .navbar.is-info .navbar-end .navbar-link { + color: #fff; } + .navbar.is-info .navbar-start > a.navbar-item:focus, .navbar.is-info .navbar-start > a.navbar-item:hover, .navbar.is-info .navbar-start > a.navbar-item.is-active, + .navbar.is-info .navbar-start .navbar-link:focus, + .navbar.is-info .navbar-start .navbar-link:hover, + .navbar.is-info .navbar-start .navbar-link.is-active, + .navbar.is-info .navbar-end > a.navbar-item:focus, + .navbar.is-info .navbar-end > a.navbar-item:hover, + .navbar.is-info .navbar-end > a.navbar-item.is-active, + .navbar.is-info .navbar-end .navbar-link:focus, + .navbar.is-info .navbar-end .navbar-link:hover, + .navbar.is-info .navbar-end .navbar-link.is-active { + background-color: #1190e3; + color: #fff; } + .navbar.is-info .navbar-start .navbar-link::after, + .navbar.is-info .navbar-end .navbar-link::after { + border-color: #fff; } + .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #1190e3; + color: #fff; } + .navbar.is-info .navbar-dropdown a.navbar-item.is-active { + background-color: #209cee; + color: #fff; } } + .navbar.is-success { + background-color: #22c35b; + color: #fff; } + .navbar.is-success .navbar-brand > .navbar-item, + .navbar.is-success .navbar-brand .navbar-link { + color: #fff; } + .navbar.is-success .navbar-brand > a.navbar-item:focus, .navbar.is-success .navbar-brand > a.navbar-item:hover, .navbar.is-success .navbar-brand > a.navbar-item.is-active, + .navbar.is-success .navbar-brand .navbar-link:focus, + .navbar.is-success .navbar-brand .navbar-link:hover, + .navbar.is-success .navbar-brand .navbar-link.is-active { + background-color: #1ead51; + color: #fff; } + .navbar.is-success .navbar-brand .navbar-link::after { + border-color: #fff; } + .navbar.is-success .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + .navbar.is-success .navbar-start > .navbar-item, + .navbar.is-success .navbar-start .navbar-link, + .navbar.is-success .navbar-end > .navbar-item, + .navbar.is-success .navbar-end .navbar-link { + color: #fff; } + .navbar.is-success .navbar-start > a.navbar-item:focus, .navbar.is-success .navbar-start > a.navbar-item:hover, .navbar.is-success .navbar-start > a.navbar-item.is-active, + .navbar.is-success .navbar-start .navbar-link:focus, + .navbar.is-success .navbar-start .navbar-link:hover, + .navbar.is-success .navbar-start .navbar-link.is-active, + .navbar.is-success .navbar-end > a.navbar-item:focus, + .navbar.is-success .navbar-end > a.navbar-item:hover, + .navbar.is-success .navbar-end > a.navbar-item.is-active, + .navbar.is-success .navbar-end .navbar-link:focus, + .navbar.is-success .navbar-end .navbar-link:hover, + .navbar.is-success .navbar-end .navbar-link.is-active { + background-color: #1ead51; + color: #fff; } + .navbar.is-success .navbar-start .navbar-link::after, + .navbar.is-success .navbar-end .navbar-link::after { + border-color: #fff; } + .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #1ead51; + color: #fff; } + .navbar.is-success .navbar-dropdown a.navbar-item.is-active { + background-color: #22c35b; + color: #fff; } } + .navbar.is-warning { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-brand > .navbar-item, + .navbar.is-warning .navbar-brand .navbar-link { + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-brand > a.navbar-item:focus, .navbar.is-warning .navbar-brand > a.navbar-item:hover, .navbar.is-warning .navbar-brand > a.navbar-item.is-active, + .navbar.is-warning .navbar-brand .navbar-link:focus, + .navbar.is-warning .navbar-brand .navbar-link:hover, + .navbar.is-warning .navbar-brand .navbar-link.is-active { + background-color: #ffd83e; + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-brand .navbar-link::after { + border-color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-burger { + color: rgba(0, 0, 0, 0.7); } + @media screen and (min-width: 1056px) { + .navbar.is-warning .navbar-start > .navbar-item, + .navbar.is-warning .navbar-start .navbar-link, + .navbar.is-warning .navbar-end > .navbar-item, + .navbar.is-warning .navbar-end .navbar-link { + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-start > a.navbar-item:focus, .navbar.is-warning .navbar-start > a.navbar-item:hover, .navbar.is-warning .navbar-start > a.navbar-item.is-active, + .navbar.is-warning .navbar-start .navbar-link:focus, + .navbar.is-warning .navbar-start .navbar-link:hover, + .navbar.is-warning .navbar-start .navbar-link.is-active, + .navbar.is-warning .navbar-end > a.navbar-item:focus, + .navbar.is-warning .navbar-end > a.navbar-item:hover, + .navbar.is-warning .navbar-end > a.navbar-item.is-active, + .navbar.is-warning .navbar-end .navbar-link:focus, + .navbar.is-warning .navbar-end .navbar-link:hover, + .navbar.is-warning .navbar-end .navbar-link.is-active { + background-color: #ffd83e; + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-start .navbar-link::after, + .navbar.is-warning .navbar-end .navbar-link::after { + border-color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #ffd83e; + color: rgba(0, 0, 0, 0.7); } + .navbar.is-warning .navbar-dropdown a.navbar-item.is-active { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } } + .navbar.is-danger { + background-color: #da0b00; + color: #fff; } + .navbar.is-danger .navbar-brand > .navbar-item, + .navbar.is-danger .navbar-brand .navbar-link { + color: #fff; } + .navbar.is-danger .navbar-brand > a.navbar-item:focus, .navbar.is-danger .navbar-brand > a.navbar-item:hover, .navbar.is-danger .navbar-brand > a.navbar-item.is-active, + .navbar.is-danger .navbar-brand .navbar-link:focus, + .navbar.is-danger .navbar-brand .navbar-link:hover, + .navbar.is-danger .navbar-brand .navbar-link.is-active { + background-color: #c10a00; + color: #fff; } + .navbar.is-danger .navbar-brand .navbar-link::after { + border-color: #fff; } + .navbar.is-danger .navbar-burger { + color: #fff; } + @media screen and (min-width: 1056px) { + .navbar.is-danger .navbar-start > .navbar-item, + .navbar.is-danger .navbar-start .navbar-link, + .navbar.is-danger .navbar-end > .navbar-item, + .navbar.is-danger .navbar-end .navbar-link { + color: #fff; } + .navbar.is-danger .navbar-start > a.navbar-item:focus, .navbar.is-danger .navbar-start > a.navbar-item:hover, .navbar.is-danger .navbar-start > a.navbar-item.is-active, + .navbar.is-danger .navbar-start .navbar-link:focus, + .navbar.is-danger .navbar-start .navbar-link:hover, + .navbar.is-danger .navbar-start .navbar-link.is-active, + .navbar.is-danger .navbar-end > a.navbar-item:focus, + .navbar.is-danger .navbar-end > a.navbar-item:hover, + .navbar.is-danger .navbar-end > a.navbar-item.is-active, + .navbar.is-danger .navbar-end .navbar-link:focus, + .navbar.is-danger .navbar-end .navbar-link:hover, + .navbar.is-danger .navbar-end .navbar-link.is-active { + background-color: #c10a00; + color: #fff; } + .navbar.is-danger .navbar-start .navbar-link::after, + .navbar.is-danger .navbar-end .navbar-link::after { + border-color: #fff; } + .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link, + .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #c10a00; + color: #fff; } + .navbar.is-danger .navbar-dropdown a.navbar-item.is-active { + background-color: #da0b00; + color: #fff; } } + .navbar > .container { + align-items: stretch; + display: flex; + min-height: 3.25rem; + width: 100%; } + .navbar.has-shadow { + box-shadow: 0 2px 0 0 whitesmoke; } + .navbar.is-fixed-bottom, .navbar.is-fixed-top { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + .navbar.is-fixed-bottom { + bottom: 0; } + .navbar.is-fixed-bottom.has-shadow { + box-shadow: 0 -2px 0 0 whitesmoke; } + .navbar.is-fixed-top { + top: 0; } + +html.has-navbar-fixed-top, +body.has-navbar-fixed-top { + padding-top: 3.25rem; } + +html.has-navbar-fixed-bottom, +body.has-navbar-fixed-bottom { + padding-bottom: 3.25rem; } + +.navbar-brand, +.navbar-tabs { + align-items: stretch; + display: flex; + flex-shrink: 0; + min-height: 3.25rem; } + +.navbar-brand a.navbar-item:focus, .navbar-brand a.navbar-item:hover { + background-color: transparent; } + +.navbar-tabs { + -webkit-overflow-scrolling: touch; + max-width: 100vw; + overflow-x: auto; + overflow-y: hidden; } + +.navbar-burger { + color: #4a4a4a; + cursor: pointer; + display: block; + height: 3.25rem; + position: relative; + width: 3.25rem; + margin-left: auto; } + .navbar-burger span { + background-color: currentColor; + display: block; + height: 1px; + left: calc(50% - 8px); + position: absolute; + transform-origin: center; + transition-duration: 86ms; + transition-property: background-color, opacity, transform; + transition-timing-function: ease-out; + width: 16px; } + .navbar-burger span:nth-child(1) { + top: calc(50% - 6px); } + .navbar-burger span:nth-child(2) { + top: calc(50% - 1px); } + .navbar-burger span:nth-child(3) { + top: calc(50% + 4px); } + .navbar-burger:hover { + background-color: rgba(0, 0, 0, 0.05); } + .navbar-burger.is-active span:nth-child(1) { + transform: translateY(5px) rotate(45deg); } + .navbar-burger.is-active span:nth-child(2) { + opacity: 0; } + .navbar-burger.is-active span:nth-child(3) { + transform: translateY(-5px) rotate(-45deg); } + +.navbar-menu { + display: none; } + +.navbar-item, +.navbar-link { + color: #4a4a4a; + display: block; + line-height: 1.5; + padding: 0.5rem 0.75rem; + position: relative; } + .navbar-item .icon:only-child, + .navbar-link .icon:only-child { + margin-left: -0.25rem; + margin-right: -0.25rem; } + +a.navbar-item, +.navbar-link { + cursor: pointer; } + a.navbar-item:focus, a.navbar-item:focus-within, a.navbar-item:hover, a.navbar-item.is-active, + .navbar-link:focus, + .navbar-link:focus-within, + .navbar-link:hover, + .navbar-link.is-active { + background-color: #fafafa; + color: #2e63b8; } + +.navbar-item { + display: block; + flex-grow: 0; + flex-shrink: 0; } + .navbar-item img { + max-height: 1.75rem; } + .navbar-item.has-dropdown { + padding: 0; } + .navbar-item.is-expanded { + flex-grow: 1; + flex-shrink: 1; } + .navbar-item.is-tab { + border-bottom: 1px solid transparent; + min-height: 3.25rem; + padding-bottom: calc(0.5rem - 1px); } + .navbar-item.is-tab:focus, .navbar-item.is-tab:hover { + background-color: transparent; + border-bottom-color: #2e63b8; } + .navbar-item.is-tab.is-active { + background-color: transparent; + border-bottom-color: #2e63b8; + border-bottom-style: solid; + border-bottom-width: 3px; + color: #2e63b8; + padding-bottom: calc(0.5rem - 3px); } + +.navbar-content { + flex-grow: 1; + flex-shrink: 1; } + +.navbar-link:not(.is-arrowless) { + padding-right: 2.5em; } + .navbar-link:not(.is-arrowless)::after { + border-color: #2e63b8; + margin-top: -0.375em; + right: 1.125em; } + +.navbar-dropdown { + font-size: 0.875rem; + padding-bottom: 0.5rem; + padding-top: 0.5rem; } + .navbar-dropdown .navbar-item { + padding-left: 1.5rem; + padding-right: 1.5rem; } + +.navbar-divider { + background-color: whitesmoke; + border: none; + display: none; + height: 2px; + margin: 0.5rem 0; } + +@media screen and (max-width: 1055px) { + .navbar > .container { + display: block; } + .navbar-brand .navbar-item, + .navbar-tabs .navbar-item { + align-items: center; + display: flex; } + .navbar-link::after { + display: none; } + .navbar-menu { + background-color: white; + box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1); + padding: 0.5rem 0; } + .navbar-menu.is-active { + display: block; } + .navbar.is-fixed-bottom-touch, .navbar.is-fixed-top-touch { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + .navbar.is-fixed-bottom-touch { + bottom: 0; } + .navbar.is-fixed-bottom-touch.has-shadow { + box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } + .navbar.is-fixed-top-touch { + top: 0; } + .navbar.is-fixed-top .navbar-menu, .navbar.is-fixed-top-touch .navbar-menu { + -webkit-overflow-scrolling: touch; + max-height: calc(100vh - 3.25rem); + overflow: auto; } + html.has-navbar-fixed-top-touch, + body.has-navbar-fixed-top-touch { + padding-top: 3.25rem; } + html.has-navbar-fixed-bottom-touch, + body.has-navbar-fixed-bottom-touch { + padding-bottom: 3.25rem; } } + +@media screen and (min-width: 1056px) { + .navbar, + .navbar-menu, + .navbar-start, + .navbar-end { + align-items: stretch; + display: flex; } + .navbar { + min-height: 3.25rem; } + .navbar.is-spaced { + padding: 1rem 2rem; } + .navbar.is-spaced .navbar-start, + .navbar.is-spaced .navbar-end { + align-items: center; } + .navbar.is-spaced a.navbar-item, + .navbar.is-spaced .navbar-link { + border-radius: 4px; } + .navbar.is-transparent a.navbar-item:focus, .navbar.is-transparent a.navbar-item:hover, .navbar.is-transparent a.navbar-item.is-active, + .navbar.is-transparent .navbar-link:focus, + .navbar.is-transparent .navbar-link:hover, + .navbar.is-transparent .navbar-link.is-active { + background-color: transparent !important; } + .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link { + background-color: transparent !important; } + .navbar.is-transparent .navbar-dropdown a.navbar-item:focus, .navbar.is-transparent .navbar-dropdown a.navbar-item:hover { + background-color: whitesmoke; + color: #0a0a0a; } + .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active { + background-color: whitesmoke; + color: #2e63b8; } + .navbar-burger { + display: none; } + .navbar-item, + .navbar-link { + align-items: center; + display: flex; } + .navbar-item { + display: flex; } + .navbar-item.has-dropdown { + align-items: stretch; } + .navbar-item.has-dropdown-up .navbar-link::after { + transform: rotate(135deg) translate(0.25em, -0.25em); } + .navbar-item.has-dropdown-up .navbar-dropdown { + border-bottom: 2px solid #dbdbdb; + border-radius: 6px 6px 0 0; + border-top: none; + bottom: 100%; + box-shadow: 0 -8px 8px rgba(10, 10, 10, 0.1); + top: auto; } + .navbar-item.is-active .navbar-dropdown, .navbar-item.is-hoverable:focus .navbar-dropdown, .navbar-item.is-hoverable:focus-within .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown { + display: block; } + .navbar.is-spaced .navbar-item.is-active .navbar-dropdown, .navbar-item.is-active .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown, .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown, .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed { + opacity: 1; + pointer-events: auto; + transform: translateY(0); } + .navbar-menu { + flex-grow: 1; + flex-shrink: 0; } + .navbar-start { + justify-content: flex-start; + margin-right: auto; } + .navbar-end { + justify-content: flex-end; + margin-left: auto; } + .navbar-dropdown { + background-color: white; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + border-top: 2px solid #dbdbdb; + box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1); + display: none; + font-size: 0.875rem; + left: 0; + min-width: 100%; + position: absolute; + top: 100%; + z-index: 20; } + .navbar-dropdown .navbar-item { + padding: 0.375rem 1rem; + white-space: nowrap; } + .navbar-dropdown a.navbar-item { + padding-right: 3rem; } + .navbar-dropdown a.navbar-item:focus, .navbar-dropdown a.navbar-item:hover { + background-color: whitesmoke; + color: #0a0a0a; } + .navbar-dropdown a.navbar-item.is-active { + background-color: whitesmoke; + color: #2e63b8; } + .navbar.is-spaced .navbar-dropdown, .navbar-dropdown.is-boxed { + border-radius: 6px; + border-top: none; + box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); + display: block; + opacity: 0; + pointer-events: none; + top: calc(100% + (-4px)); + transform: translateY(-5px); + transition-duration: 86ms; + transition-property: opacity, transform; } + .navbar-dropdown.is-right { + left: auto; + right: 0; } + .navbar-divider { + display: block; } + .navbar > .container .navbar-brand, + .container > .navbar .navbar-brand { + margin-left: -.75rem; } + .navbar > .container .navbar-menu, + .container > .navbar .navbar-menu { + margin-right: -.75rem; } + .navbar.is-fixed-bottom-desktop, .navbar.is-fixed-top-desktop { + left: 0; + position: fixed; + right: 0; + z-index: 30; } + .navbar.is-fixed-bottom-desktop { + bottom: 0; } + .navbar.is-fixed-bottom-desktop.has-shadow { + box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } + .navbar.is-fixed-top-desktop { + top: 0; } + html.has-navbar-fixed-top-desktop, + body.has-navbar-fixed-top-desktop { + padding-top: 3.25rem; } + html.has-navbar-fixed-bottom-desktop, + body.has-navbar-fixed-bottom-desktop { + padding-bottom: 3.25rem; } + html.has-spaced-navbar-fixed-top, + body.has-spaced-navbar-fixed-top { + padding-top: 5.25rem; } + html.has-spaced-navbar-fixed-bottom, + body.has-spaced-navbar-fixed-bottom { + padding-bottom: 5.25rem; } + a.navbar-item.is-active, + .navbar-link.is-active { + color: #0a0a0a; } + a.navbar-item.is-active:not(:focus):not(:hover), + .navbar-link.is-active:not(:focus):not(:hover) { + background-color: transparent; } + .navbar-item.has-dropdown:focus .navbar-link, .navbar-item.has-dropdown:hover .navbar-link, .navbar-item.has-dropdown.is-active .navbar-link { + background-color: #fafafa; } } + +.hero.is-fullheight-with-navbar { + min-height: calc(100vh - 3.25rem); } + +.pagination { + font-size: 1rem; + margin: -0.25rem; } + .pagination.is-small, #documenter .docs-sidebar form.docs-search > input.pagination { + font-size: 0.75rem; } + .pagination.is-medium { + font-size: 1.25rem; } + .pagination.is-large { + font-size: 1.5rem; } + .pagination.is-rounded .pagination-previous, #documenter .docs-sidebar form.docs-search > input.pagination .pagination-previous, + .pagination.is-rounded .pagination-next, + #documenter .docs-sidebar form.docs-search > input.pagination .pagination-next { + padding-left: 1em; + padding-right: 1em; + border-radius: 290486px; } + .pagination.is-rounded .pagination-link, #documenter .docs-sidebar form.docs-search > input.pagination .pagination-link { + border-radius: 290486px; } + +.pagination, +.pagination-list { + align-items: center; + display: flex; + justify-content: center; + text-align: center; } + +.pagination-previous, +.pagination-next, +.pagination-link, +.pagination-ellipsis { + font-size: 1em; + justify-content: center; + margin: 0.25rem; + padding-left: 0.5em; + padding-right: 0.5em; + text-align: center; } + +.pagination-previous, +.pagination-next, +.pagination-link { + border-color: #dbdbdb; + color: #363636; + min-width: 2.25em; } + .pagination-previous:hover, + .pagination-next:hover, + .pagination-link:hover { + border-color: #b5b5b5; + color: #363636; } + .pagination-previous:focus, + .pagination-next:focus, + .pagination-link:focus { + border-color: #3c5dcd; } + .pagination-previous:active, + .pagination-next:active, + .pagination-link:active { + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2); } + .pagination-previous[disabled], + .pagination-next[disabled], + .pagination-link[disabled] { + background-color: #dbdbdb; + border-color: #dbdbdb; + box-shadow: none; + color: #6b6b6b; + opacity: 0.5; } + +.pagination-previous, +.pagination-next { + padding-left: 0.75em; + padding-right: 0.75em; + white-space: nowrap; } + +.pagination-link.is-current { + background-color: #2e63b8; + border-color: #2e63b8; + color: #fff; } + +.pagination-ellipsis { + color: #b5b5b5; + pointer-events: none; } + +.pagination-list { + flex-wrap: wrap; } + +@media screen and (max-width: 768px) { + .pagination { + flex-wrap: wrap; } + .pagination-previous, + .pagination-next { + flex-grow: 1; + flex-shrink: 1; } + .pagination-list li { + flex-grow: 1; + flex-shrink: 1; } } + +@media screen and (min-width: 769px), print { + .pagination-list { + flex-grow: 1; + flex-shrink: 1; + justify-content: flex-start; + order: 1; } + .pagination-previous { + order: 2; } + .pagination-next { + order: 3; } + .pagination { + justify-content: space-between; } + .pagination.is-centered .pagination-previous { + order: 1; } + .pagination.is-centered .pagination-list { + justify-content: center; + order: 2; } + .pagination.is-centered .pagination-next { + order: 3; } + .pagination.is-right .pagination-previous { + order: 1; } + .pagination.is-right .pagination-next { + order: 2; } + .pagination.is-right .pagination-list { + justify-content: flex-end; + order: 3; } } + +.panel { + font-size: 1rem; } + .panel:not(:last-child) { + margin-bottom: 1.5rem; } + +.panel-heading, +.panel-tabs, +.panel-block { + border-bottom: 1px solid #dbdbdb; + border-left: 1px solid #dbdbdb; + border-right: 1px solid #dbdbdb; } + .panel-heading:first-child, + .panel-tabs:first-child, + .panel-block:first-child { + border-top: 1px solid #dbdbdb; } + +.panel-heading { + background-color: whitesmoke; + border-radius: 4px 4px 0 0; + color: #222222; + font-size: 1.25em; + font-weight: 300; + line-height: 1.25; + padding: 0.5em 0.75em; } + +.panel-tabs { + align-items: flex-end; + display: flex; + font-size: 0.875em; + justify-content: center; } + .panel-tabs a { + border-bottom: 1px solid #dbdbdb; + margin-bottom: -1px; + padding: 0.5em; } + .panel-tabs a.is-active { + border-bottom-color: #4a4a4a; + color: #363636; } + +.panel-list a { + color: #222222; } + .panel-list a:hover { + color: #2e63b8; } + +.panel-block { + align-items: center; + color: #222222; + display: flex; + justify-content: flex-start; + padding: 0.5em 0.75em; } + .panel-block input[type="checkbox"] { + margin-right: 0.75em; } + .panel-block > .control { + flex-grow: 1; + flex-shrink: 1; + width: 100%; } + .panel-block.is-wrapped { + flex-wrap: wrap; } + .panel-block.is-active { + border-left-color: #2e63b8; + color: #363636; } + .panel-block.is-active .panel-icon { + color: #2e63b8; } + +a.panel-block, +label.panel-block { + cursor: pointer; } + a.panel-block:hover, + label.panel-block:hover { + background-color: whitesmoke; } + +.panel-icon { + display: inline-block; + font-size: 14px; + height: 1em; + line-height: 1em; + text-align: center; + vertical-align: top; + width: 1em; + color: #6b6b6b; + margin-right: 0.75em; } + .panel-icon .fa { + font-size: inherit; + line-height: inherit; } + +.tabs { + -webkit-overflow-scrolling: touch; + align-items: stretch; + display: flex; + font-size: 1rem; + justify-content: space-between; + overflow: hidden; + overflow-x: auto; + white-space: nowrap; } + .tabs a { + align-items: center; + border-bottom-color: #dbdbdb; + border-bottom-style: solid; + border-bottom-width: 1px; + color: #222222; + display: flex; + justify-content: center; + margin-bottom: -1px; + padding: 0.5em 1em; + vertical-align: top; } + .tabs a:hover { + border-bottom-color: #222222; + color: #222222; } + .tabs li { + display: block; } + .tabs li.is-active a { + border-bottom-color: #2e63b8; + color: #2e63b8; } + .tabs ul { + align-items: center; + border-bottom-color: #dbdbdb; + border-bottom-style: solid; + border-bottom-width: 1px; + display: flex; + flex-grow: 1; + flex-shrink: 0; + justify-content: flex-start; } + .tabs ul.is-left { + padding-right: 0.75em; } + .tabs ul.is-center { + flex: none; + justify-content: center; + padding-left: 0.75em; + padding-right: 0.75em; } + .tabs ul.is-right { + justify-content: flex-end; + padding-left: 0.75em; } + .tabs .icon:first-child { + margin-right: 0.5em; } + .tabs .icon:last-child { + margin-left: 0.5em; } + .tabs.is-centered ul { + justify-content: center; } + .tabs.is-right ul { + justify-content: flex-end; } + .tabs.is-boxed a { + border: 1px solid transparent; + border-radius: 4px 4px 0 0; } + .tabs.is-boxed a:hover { + background-color: whitesmoke; + border-bottom-color: #dbdbdb; } + .tabs.is-boxed li.is-active a { + background-color: white; + border-color: #dbdbdb; + border-bottom-color: transparent !important; } + .tabs.is-fullwidth li { + flex-grow: 1; + flex-shrink: 0; } + .tabs.is-toggle a { + border-color: #dbdbdb; + border-style: solid; + border-width: 1px; + margin-bottom: 0; + position: relative; } + .tabs.is-toggle a:hover { + background-color: whitesmoke; + border-color: #b5b5b5; + z-index: 2; } + .tabs.is-toggle li + li { + margin-left: -1px; } + .tabs.is-toggle li:first-child a { + border-radius: 4px 0 0 4px; } + .tabs.is-toggle li:last-child a { + border-radius: 0 4px 4px 0; } + .tabs.is-toggle li.is-active a { + background-color: #2e63b8; + border-color: #2e63b8; + color: #fff; + z-index: 1; } + .tabs.is-toggle ul { + border-bottom: none; } + .tabs.is-toggle.is-toggle-rounded li:first-child a { + border-bottom-left-radius: 290486px; + border-top-left-radius: 290486px; + padding-left: 1.25em; } + .tabs.is-toggle.is-toggle-rounded li:last-child a { + border-bottom-right-radius: 290486px; + border-top-right-radius: 290486px; + padding-right: 1.25em; } + .tabs.is-small, #documenter .docs-sidebar form.docs-search > input.tabs { + font-size: 0.75rem; } + .tabs.is-medium { + font-size: 1.25rem; } + .tabs.is-large { + font-size: 1.5rem; } + +.column { + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + padding: 0.75rem; } + .columns.is-mobile > .column.is-narrow { + flex: none; } + .columns.is-mobile > .column.is-full { + flex: none; + width: 100%; } + .columns.is-mobile > .column.is-three-quarters { + flex: none; + width: 75%; } + .columns.is-mobile > .column.is-two-thirds { + flex: none; + width: 66.6666%; } + .columns.is-mobile > .column.is-half { + flex: none; + width: 50%; } + .columns.is-mobile > .column.is-one-third { + flex: none; + width: 33.3333%; } + .columns.is-mobile > .column.is-one-quarter { + flex: none; + width: 25%; } + .columns.is-mobile > .column.is-one-fifth { + flex: none; + width: 20%; } + .columns.is-mobile > .column.is-two-fifths { + flex: none; + width: 40%; } + .columns.is-mobile > .column.is-three-fifths { + flex: none; + width: 60%; } + .columns.is-mobile > .column.is-four-fifths { + flex: none; + width: 80%; } + .columns.is-mobile > .column.is-offset-three-quarters { + margin-left: 75%; } + .columns.is-mobile > .column.is-offset-two-thirds { + margin-left: 66.6666%; } + .columns.is-mobile > .column.is-offset-half { + margin-left: 50%; } + .columns.is-mobile > .column.is-offset-one-third { + margin-left: 33.3333%; } + .columns.is-mobile > .column.is-offset-one-quarter { + margin-left: 25%; } + .columns.is-mobile > .column.is-offset-one-fifth { + margin-left: 20%; } + .columns.is-mobile > .column.is-offset-two-fifths { + margin-left: 40%; } + .columns.is-mobile > .column.is-offset-three-fifths { + margin-left: 60%; } + .columns.is-mobile > .column.is-offset-four-fifths { + margin-left: 80%; } + .columns.is-mobile > .column.is-0 { + flex: none; + width: 0%; } + .columns.is-mobile > .column.is-offset-0 { + margin-left: 0%; } + .columns.is-mobile > .column.is-1 { + flex: none; + width: 8.3333333333%; } + .columns.is-mobile > .column.is-offset-1 { + margin-left: 8.3333333333%; } + .columns.is-mobile > .column.is-2 { + flex: none; + width: 16.6666666667%; } + .columns.is-mobile > .column.is-offset-2 { + margin-left: 16.6666666667%; } + .columns.is-mobile > .column.is-3 { + flex: none; + width: 25%; } + .columns.is-mobile > .column.is-offset-3 { + margin-left: 25%; } + .columns.is-mobile > .column.is-4 { + flex: none; + width: 33.3333333333%; } + .columns.is-mobile > .column.is-offset-4 { + margin-left: 33.3333333333%; } + .columns.is-mobile > .column.is-5 { + flex: none; + width: 41.6666666667%; } + .columns.is-mobile > .column.is-offset-5 { + margin-left: 41.6666666667%; } + .columns.is-mobile > .column.is-6 { + flex: none; + width: 50%; } + .columns.is-mobile > .column.is-offset-6 { + margin-left: 50%; } + .columns.is-mobile > .column.is-7 { + flex: none; + width: 58.3333333333%; } + .columns.is-mobile > .column.is-offset-7 { + margin-left: 58.3333333333%; } + .columns.is-mobile > .column.is-8 { + flex: none; + width: 66.6666666667%; } + .columns.is-mobile > .column.is-offset-8 { + margin-left: 66.6666666667%; } + .columns.is-mobile > .column.is-9 { + flex: none; + width: 75%; } + .columns.is-mobile > .column.is-offset-9 { + margin-left: 75%; } + .columns.is-mobile > .column.is-10 { + flex: none; + width: 83.3333333333%; } + .columns.is-mobile > .column.is-offset-10 { + margin-left: 83.3333333333%; } + .columns.is-mobile > .column.is-11 { + flex: none; + width: 91.6666666667%; } + .columns.is-mobile > .column.is-offset-11 { + margin-left: 91.6666666667%; } + .columns.is-mobile > .column.is-12 { + flex: none; + width: 100%; } + .columns.is-mobile > .column.is-offset-12 { + margin-left: 100%; } + @media screen and (max-width: 768px) { + .column.is-narrow-mobile { + flex: none; } + .column.is-full-mobile { + flex: none; + width: 100%; } + .column.is-three-quarters-mobile { + flex: none; + width: 75%; } + .column.is-two-thirds-mobile { + flex: none; + width: 66.6666%; } + .column.is-half-mobile { + flex: none; + width: 50%; } + .column.is-one-third-mobile { + flex: none; + width: 33.3333%; } + .column.is-one-quarter-mobile { + flex: none; + width: 25%; } + .column.is-one-fifth-mobile { + flex: none; + width: 20%; } + .column.is-two-fifths-mobile { + flex: none; + width: 40%; } + .column.is-three-fifths-mobile { + flex: none; + width: 60%; } + .column.is-four-fifths-mobile { + flex: none; + width: 80%; } + .column.is-offset-three-quarters-mobile { + margin-left: 75%; } + .column.is-offset-two-thirds-mobile { + margin-left: 66.6666%; } + .column.is-offset-half-mobile { + margin-left: 50%; } + .column.is-offset-one-third-mobile { + margin-left: 33.3333%; } + .column.is-offset-one-quarter-mobile { + margin-left: 25%; } + .column.is-offset-one-fifth-mobile { + margin-left: 20%; } + .column.is-offset-two-fifths-mobile { + margin-left: 40%; } + .column.is-offset-three-fifths-mobile { + margin-left: 60%; } + .column.is-offset-four-fifths-mobile { + margin-left: 80%; } + .column.is-0-mobile { + flex: none; + width: 0%; } + .column.is-offset-0-mobile { + margin-left: 0%; } + .column.is-1-mobile { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1-mobile { + margin-left: 8.3333333333%; } + .column.is-2-mobile { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2-mobile { + margin-left: 16.6666666667%; } + .column.is-3-mobile { + flex: none; + width: 25%; } + .column.is-offset-3-mobile { + margin-left: 25%; } + .column.is-4-mobile { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4-mobile { + margin-left: 33.3333333333%; } + .column.is-5-mobile { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5-mobile { + margin-left: 41.6666666667%; } + .column.is-6-mobile { + flex: none; + width: 50%; } + .column.is-offset-6-mobile { + margin-left: 50%; } + .column.is-7-mobile { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7-mobile { + margin-left: 58.3333333333%; } + .column.is-8-mobile { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8-mobile { + margin-left: 66.6666666667%; } + .column.is-9-mobile { + flex: none; + width: 75%; } + .column.is-offset-9-mobile { + margin-left: 75%; } + .column.is-10-mobile { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10-mobile { + margin-left: 83.3333333333%; } + .column.is-11-mobile { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11-mobile { + margin-left: 91.6666666667%; } + .column.is-12-mobile { + flex: none; + width: 100%; } + .column.is-offset-12-mobile { + margin-left: 100%; } } + @media screen and (min-width: 769px), print { + .column.is-narrow, .column.is-narrow-tablet { + flex: none; } + .column.is-full, .column.is-full-tablet { + flex: none; + width: 100%; } + .column.is-three-quarters, .column.is-three-quarters-tablet { + flex: none; + width: 75%; } + .column.is-two-thirds, .column.is-two-thirds-tablet { + flex: none; + width: 66.6666%; } + .column.is-half, .column.is-half-tablet { + flex: none; + width: 50%; } + .column.is-one-third, .column.is-one-third-tablet { + flex: none; + width: 33.3333%; } + .column.is-one-quarter, .column.is-one-quarter-tablet { + flex: none; + width: 25%; } + .column.is-one-fifth, .column.is-one-fifth-tablet { + flex: none; + width: 20%; } + .column.is-two-fifths, .column.is-two-fifths-tablet { + flex: none; + width: 40%; } + .column.is-three-fifths, .column.is-three-fifths-tablet { + flex: none; + width: 60%; } + .column.is-four-fifths, .column.is-four-fifths-tablet { + flex: none; + width: 80%; } + .column.is-offset-three-quarters, .column.is-offset-three-quarters-tablet { + margin-left: 75%; } + .column.is-offset-two-thirds, .column.is-offset-two-thirds-tablet { + margin-left: 66.6666%; } + .column.is-offset-half, .column.is-offset-half-tablet { + margin-left: 50%; } + .column.is-offset-one-third, .column.is-offset-one-third-tablet { + margin-left: 33.3333%; } + .column.is-offset-one-quarter, .column.is-offset-one-quarter-tablet { + margin-left: 25%; } + .column.is-offset-one-fifth, .column.is-offset-one-fifth-tablet { + margin-left: 20%; } + .column.is-offset-two-fifths, .column.is-offset-two-fifths-tablet { + margin-left: 40%; } + .column.is-offset-three-fifths, .column.is-offset-three-fifths-tablet { + margin-left: 60%; } + .column.is-offset-four-fifths, .column.is-offset-four-fifths-tablet { + margin-left: 80%; } + .column.is-0, .column.is-0-tablet { + flex: none; + width: 0%; } + .column.is-offset-0, .column.is-offset-0-tablet { + margin-left: 0%; } + .column.is-1, .column.is-1-tablet { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1, .column.is-offset-1-tablet { + margin-left: 8.3333333333%; } + .column.is-2, .column.is-2-tablet { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2, .column.is-offset-2-tablet { + margin-left: 16.6666666667%; } + .column.is-3, .column.is-3-tablet { + flex: none; + width: 25%; } + .column.is-offset-3, .column.is-offset-3-tablet { + margin-left: 25%; } + .column.is-4, .column.is-4-tablet { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4, .column.is-offset-4-tablet { + margin-left: 33.3333333333%; } + .column.is-5, .column.is-5-tablet { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5, .column.is-offset-5-tablet { + margin-left: 41.6666666667%; } + .column.is-6, .column.is-6-tablet { + flex: none; + width: 50%; } + .column.is-offset-6, .column.is-offset-6-tablet { + margin-left: 50%; } + .column.is-7, .column.is-7-tablet { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7, .column.is-offset-7-tablet { + margin-left: 58.3333333333%; } + .column.is-8, .column.is-8-tablet { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8, .column.is-offset-8-tablet { + margin-left: 66.6666666667%; } + .column.is-9, .column.is-9-tablet { + flex: none; + width: 75%; } + .column.is-offset-9, .column.is-offset-9-tablet { + margin-left: 75%; } + .column.is-10, .column.is-10-tablet { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10, .column.is-offset-10-tablet { + margin-left: 83.3333333333%; } + .column.is-11, .column.is-11-tablet { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11, .column.is-offset-11-tablet { + margin-left: 91.6666666667%; } + .column.is-12, .column.is-12-tablet { + flex: none; + width: 100%; } + .column.is-offset-12, .column.is-offset-12-tablet { + margin-left: 100%; } } + @media screen and (max-width: 1055px) { + .column.is-narrow-touch { + flex: none; } + .column.is-full-touch { + flex: none; + width: 100%; } + .column.is-three-quarters-touch { + flex: none; + width: 75%; } + .column.is-two-thirds-touch { + flex: none; + width: 66.6666%; } + .column.is-half-touch { + flex: none; + width: 50%; } + .column.is-one-third-touch { + flex: none; + width: 33.3333%; } + .column.is-one-quarter-touch { + flex: none; + width: 25%; } + .column.is-one-fifth-touch { + flex: none; + width: 20%; } + .column.is-two-fifths-touch { + flex: none; + width: 40%; } + .column.is-three-fifths-touch { + flex: none; + width: 60%; } + .column.is-four-fifths-touch { + flex: none; + width: 80%; } + .column.is-offset-three-quarters-touch { + margin-left: 75%; } + .column.is-offset-two-thirds-touch { + margin-left: 66.6666%; } + .column.is-offset-half-touch { + margin-left: 50%; } + .column.is-offset-one-third-touch { + margin-left: 33.3333%; } + .column.is-offset-one-quarter-touch { + margin-left: 25%; } + .column.is-offset-one-fifth-touch { + margin-left: 20%; } + .column.is-offset-two-fifths-touch { + margin-left: 40%; } + .column.is-offset-three-fifths-touch { + margin-left: 60%; } + .column.is-offset-four-fifths-touch { + margin-left: 80%; } + .column.is-0-touch { + flex: none; + width: 0%; } + .column.is-offset-0-touch { + margin-left: 0%; } + .column.is-1-touch { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1-touch { + margin-left: 8.3333333333%; } + .column.is-2-touch { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2-touch { + margin-left: 16.6666666667%; } + .column.is-3-touch { + flex: none; + width: 25%; } + .column.is-offset-3-touch { + margin-left: 25%; } + .column.is-4-touch { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4-touch { + margin-left: 33.3333333333%; } + .column.is-5-touch { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5-touch { + margin-left: 41.6666666667%; } + .column.is-6-touch { + flex: none; + width: 50%; } + .column.is-offset-6-touch { + margin-left: 50%; } + .column.is-7-touch { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7-touch { + margin-left: 58.3333333333%; } + .column.is-8-touch { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8-touch { + margin-left: 66.6666666667%; } + .column.is-9-touch { + flex: none; + width: 75%; } + .column.is-offset-9-touch { + margin-left: 75%; } + .column.is-10-touch { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10-touch { + margin-left: 83.3333333333%; } + .column.is-11-touch { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11-touch { + margin-left: 91.6666666667%; } + .column.is-12-touch { + flex: none; + width: 100%; } + .column.is-offset-12-touch { + margin-left: 100%; } } + @media screen and (min-width: 1056px) { + .column.is-narrow-desktop { + flex: none; } + .column.is-full-desktop { + flex: none; + width: 100%; } + .column.is-three-quarters-desktop { + flex: none; + width: 75%; } + .column.is-two-thirds-desktop { + flex: none; + width: 66.6666%; } + .column.is-half-desktop { + flex: none; + width: 50%; } + .column.is-one-third-desktop { + flex: none; + width: 33.3333%; } + .column.is-one-quarter-desktop { + flex: none; + width: 25%; } + .column.is-one-fifth-desktop { + flex: none; + width: 20%; } + .column.is-two-fifths-desktop { + flex: none; + width: 40%; } + .column.is-three-fifths-desktop { + flex: none; + width: 60%; } + .column.is-four-fifths-desktop { + flex: none; + width: 80%; } + .column.is-offset-three-quarters-desktop { + margin-left: 75%; } + .column.is-offset-two-thirds-desktop { + margin-left: 66.6666%; } + .column.is-offset-half-desktop { + margin-left: 50%; } + .column.is-offset-one-third-desktop { + margin-left: 33.3333%; } + .column.is-offset-one-quarter-desktop { + margin-left: 25%; } + .column.is-offset-one-fifth-desktop { + margin-left: 20%; } + .column.is-offset-two-fifths-desktop { + margin-left: 40%; } + .column.is-offset-three-fifths-desktop { + margin-left: 60%; } + .column.is-offset-four-fifths-desktop { + margin-left: 80%; } + .column.is-0-desktop { + flex: none; + width: 0%; } + .column.is-offset-0-desktop { + margin-left: 0%; } + .column.is-1-desktop { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1-desktop { + margin-left: 8.3333333333%; } + .column.is-2-desktop { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2-desktop { + margin-left: 16.6666666667%; } + .column.is-3-desktop { + flex: none; + width: 25%; } + .column.is-offset-3-desktop { + margin-left: 25%; } + .column.is-4-desktop { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4-desktop { + margin-left: 33.3333333333%; } + .column.is-5-desktop { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5-desktop { + margin-left: 41.6666666667%; } + .column.is-6-desktop { + flex: none; + width: 50%; } + .column.is-offset-6-desktop { + margin-left: 50%; } + .column.is-7-desktop { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7-desktop { + margin-left: 58.3333333333%; } + .column.is-8-desktop { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8-desktop { + margin-left: 66.6666666667%; } + .column.is-9-desktop { + flex: none; + width: 75%; } + .column.is-offset-9-desktop { + margin-left: 75%; } + .column.is-10-desktop { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10-desktop { + margin-left: 83.3333333333%; } + .column.is-11-desktop { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11-desktop { + margin-left: 91.6666666667%; } + .column.is-12-desktop { + flex: none; + width: 100%; } + .column.is-offset-12-desktop { + margin-left: 100%; } } + @media screen and (min-width: 1216px) { + .column.is-narrow-widescreen { + flex: none; } + .column.is-full-widescreen { + flex: none; + width: 100%; } + .column.is-three-quarters-widescreen { + flex: none; + width: 75%; } + .column.is-two-thirds-widescreen { + flex: none; + width: 66.6666%; } + .column.is-half-widescreen { + flex: none; + width: 50%; } + .column.is-one-third-widescreen { + flex: none; + width: 33.3333%; } + .column.is-one-quarter-widescreen { + flex: none; + width: 25%; } + .column.is-one-fifth-widescreen { + flex: none; + width: 20%; } + .column.is-two-fifths-widescreen { + flex: none; + width: 40%; } + .column.is-three-fifths-widescreen { + flex: none; + width: 60%; } + .column.is-four-fifths-widescreen { + flex: none; + width: 80%; } + .column.is-offset-three-quarters-widescreen { + margin-left: 75%; } + .column.is-offset-two-thirds-widescreen { + margin-left: 66.6666%; } + .column.is-offset-half-widescreen { + margin-left: 50%; } + .column.is-offset-one-third-widescreen { + margin-left: 33.3333%; } + .column.is-offset-one-quarter-widescreen { + margin-left: 25%; } + .column.is-offset-one-fifth-widescreen { + margin-left: 20%; } + .column.is-offset-two-fifths-widescreen { + margin-left: 40%; } + .column.is-offset-three-fifths-widescreen { + margin-left: 60%; } + .column.is-offset-four-fifths-widescreen { + margin-left: 80%; } + .column.is-0-widescreen { + flex: none; + width: 0%; } + .column.is-offset-0-widescreen { + margin-left: 0%; } + .column.is-1-widescreen { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1-widescreen { + margin-left: 8.3333333333%; } + .column.is-2-widescreen { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2-widescreen { + margin-left: 16.6666666667%; } + .column.is-3-widescreen { + flex: none; + width: 25%; } + .column.is-offset-3-widescreen { + margin-left: 25%; } + .column.is-4-widescreen { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4-widescreen { + margin-left: 33.3333333333%; } + .column.is-5-widescreen { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5-widescreen { + margin-left: 41.6666666667%; } + .column.is-6-widescreen { + flex: none; + width: 50%; } + .column.is-offset-6-widescreen { + margin-left: 50%; } + .column.is-7-widescreen { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7-widescreen { + margin-left: 58.3333333333%; } + .column.is-8-widescreen { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8-widescreen { + margin-left: 66.6666666667%; } + .column.is-9-widescreen { + flex: none; + width: 75%; } + .column.is-offset-9-widescreen { + margin-left: 75%; } + .column.is-10-widescreen { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10-widescreen { + margin-left: 83.3333333333%; } + .column.is-11-widescreen { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11-widescreen { + margin-left: 91.6666666667%; } + .column.is-12-widescreen { + flex: none; + width: 100%; } + .column.is-offset-12-widescreen { + margin-left: 100%; } } + @media screen and (min-width: 1408px) { + .column.is-narrow-fullhd { + flex: none; } + .column.is-full-fullhd { + flex: none; + width: 100%; } + .column.is-three-quarters-fullhd { + flex: none; + width: 75%; } + .column.is-two-thirds-fullhd { + flex: none; + width: 66.6666%; } + .column.is-half-fullhd { + flex: none; + width: 50%; } + .column.is-one-third-fullhd { + flex: none; + width: 33.3333%; } + .column.is-one-quarter-fullhd { + flex: none; + width: 25%; } + .column.is-one-fifth-fullhd { + flex: none; + width: 20%; } + .column.is-two-fifths-fullhd { + flex: none; + width: 40%; } + .column.is-three-fifths-fullhd { + flex: none; + width: 60%; } + .column.is-four-fifths-fullhd { + flex: none; + width: 80%; } + .column.is-offset-three-quarters-fullhd { + margin-left: 75%; } + .column.is-offset-two-thirds-fullhd { + margin-left: 66.6666%; } + .column.is-offset-half-fullhd { + margin-left: 50%; } + .column.is-offset-one-third-fullhd { + margin-left: 33.3333%; } + .column.is-offset-one-quarter-fullhd { + margin-left: 25%; } + .column.is-offset-one-fifth-fullhd { + margin-left: 20%; } + .column.is-offset-two-fifths-fullhd { + margin-left: 40%; } + .column.is-offset-three-fifths-fullhd { + margin-left: 60%; } + .column.is-offset-four-fifths-fullhd { + margin-left: 80%; } + .column.is-0-fullhd { + flex: none; + width: 0%; } + .column.is-offset-0-fullhd { + margin-left: 0%; } + .column.is-1-fullhd { + flex: none; + width: 8.3333333333%; } + .column.is-offset-1-fullhd { + margin-left: 8.3333333333%; } + .column.is-2-fullhd { + flex: none; + width: 16.6666666667%; } + .column.is-offset-2-fullhd { + margin-left: 16.6666666667%; } + .column.is-3-fullhd { + flex: none; + width: 25%; } + .column.is-offset-3-fullhd { + margin-left: 25%; } + .column.is-4-fullhd { + flex: none; + width: 33.3333333333%; } + .column.is-offset-4-fullhd { + margin-left: 33.3333333333%; } + .column.is-5-fullhd { + flex: none; + width: 41.6666666667%; } + .column.is-offset-5-fullhd { + margin-left: 41.6666666667%; } + .column.is-6-fullhd { + flex: none; + width: 50%; } + .column.is-offset-6-fullhd { + margin-left: 50%; } + .column.is-7-fullhd { + flex: none; + width: 58.3333333333%; } + .column.is-offset-7-fullhd { + margin-left: 58.3333333333%; } + .column.is-8-fullhd { + flex: none; + width: 66.6666666667%; } + .column.is-offset-8-fullhd { + margin-left: 66.6666666667%; } + .column.is-9-fullhd { + flex: none; + width: 75%; } + .column.is-offset-9-fullhd { + margin-left: 75%; } + .column.is-10-fullhd { + flex: none; + width: 83.3333333333%; } + .column.is-offset-10-fullhd { + margin-left: 83.3333333333%; } + .column.is-11-fullhd { + flex: none; + width: 91.6666666667%; } + .column.is-offset-11-fullhd { + margin-left: 91.6666666667%; } + .column.is-12-fullhd { + flex: none; + width: 100%; } + .column.is-offset-12-fullhd { + margin-left: 100%; } } +.columns { + margin-left: -0.75rem; + margin-right: -0.75rem; + margin-top: -0.75rem; } + .columns:last-child { + margin-bottom: -0.75rem; } + .columns:not(:last-child) { + margin-bottom: calc(1.5rem - 0.75rem); } + .columns.is-centered { + justify-content: center; } + .columns.is-gapless { + margin-left: 0; + margin-right: 0; + margin-top: 0; } + .columns.is-gapless > .column { + margin: 0; + padding: 0 !important; } + .columns.is-gapless:not(:last-child) { + margin-bottom: 1.5rem; } + .columns.is-gapless:last-child { + margin-bottom: 0; } + .columns.is-mobile { + display: flex; } + .columns.is-multiline { + flex-wrap: wrap; } + .columns.is-vcentered { + align-items: center; } + @media screen and (min-width: 769px), print { + .columns:not(.is-desktop) { + display: flex; } } + @media screen and (min-width: 1056px) { + .columns.is-desktop { + display: flex; } } +.columns.is-variable { + --columnGap: 0.75rem; + margin-left: calc(-1 * var(--columnGap)); + margin-right: calc(-1 * var(--columnGap)); } + .columns.is-variable .column { + padding-left: var(--columnGap); + padding-right: var(--columnGap); } + .columns.is-variable.is-0 { + --columnGap: 0rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-0-mobile { + --columnGap: 0rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-0-tablet { + --columnGap: 0rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-0-tablet-only { + --columnGap: 0rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-0-touch { + --columnGap: 0rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-0-desktop { + --columnGap: 0rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-0-desktop-only { + --columnGap: 0rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-0-widescreen { + --columnGap: 0rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-0-widescreen-only { + --columnGap: 0rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-0-fullhd { + --columnGap: 0rem; } } + .columns.is-variable.is-1 { + --columnGap: 0.25rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-1-mobile { + --columnGap: 0.25rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-1-tablet { + --columnGap: 0.25rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-1-tablet-only { + --columnGap: 0.25rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-1-touch { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-1-desktop { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-1-desktop-only { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-1-widescreen { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-1-widescreen-only { + --columnGap: 0.25rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-1-fullhd { + --columnGap: 0.25rem; } } + .columns.is-variable.is-2 { + --columnGap: 0.5rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-2-mobile { + --columnGap: 0.5rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-2-tablet { + --columnGap: 0.5rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-2-tablet-only { + --columnGap: 0.5rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-2-touch { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-2-desktop { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-2-desktop-only { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-2-widescreen { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-2-widescreen-only { + --columnGap: 0.5rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-2-fullhd { + --columnGap: 0.5rem; } } + .columns.is-variable.is-3 { + --columnGap: 0.75rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-3-mobile { + --columnGap: 0.75rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-3-tablet { + --columnGap: 0.75rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-3-tablet-only { + --columnGap: 0.75rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-3-touch { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-3-desktop { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-3-desktop-only { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-3-widescreen { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-3-widescreen-only { + --columnGap: 0.75rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-3-fullhd { + --columnGap: 0.75rem; } } + .columns.is-variable.is-4 { + --columnGap: 1rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-4-mobile { + --columnGap: 1rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-4-tablet { + --columnGap: 1rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-4-tablet-only { + --columnGap: 1rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-4-touch { + --columnGap: 1rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-4-desktop { + --columnGap: 1rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-4-desktop-only { + --columnGap: 1rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-4-widescreen { + --columnGap: 1rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-4-widescreen-only { + --columnGap: 1rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-4-fullhd { + --columnGap: 1rem; } } + .columns.is-variable.is-5 { + --columnGap: 1.25rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-5-mobile { + --columnGap: 1.25rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-5-tablet { + --columnGap: 1.25rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-5-tablet-only { + --columnGap: 1.25rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-5-touch { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-5-desktop { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-5-desktop-only { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-5-widescreen { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-5-widescreen-only { + --columnGap: 1.25rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-5-fullhd { + --columnGap: 1.25rem; } } + .columns.is-variable.is-6 { + --columnGap: 1.5rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-6-mobile { + --columnGap: 1.5rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-6-tablet { + --columnGap: 1.5rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-6-tablet-only { + --columnGap: 1.5rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-6-touch { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-6-desktop { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-6-desktop-only { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-6-widescreen { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-6-widescreen-only { + --columnGap: 1.5rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-6-fullhd { + --columnGap: 1.5rem; } } + .columns.is-variable.is-7 { + --columnGap: 1.75rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-7-mobile { + --columnGap: 1.75rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-7-tablet { + --columnGap: 1.75rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-7-tablet-only { + --columnGap: 1.75rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-7-touch { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-7-desktop { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-7-desktop-only { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-7-widescreen { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-7-widescreen-only { + --columnGap: 1.75rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-7-fullhd { + --columnGap: 1.75rem; } } + .columns.is-variable.is-8 { + --columnGap: 2rem; } + @media screen and (max-width: 768px) { + .columns.is-variable.is-8-mobile { + --columnGap: 2rem; } } + @media screen and (min-width: 769px), print { + .columns.is-variable.is-8-tablet { + --columnGap: 2rem; } } + @media screen and (min-width: 769px) and (max-width: 1055px) { + .columns.is-variable.is-8-tablet-only { + --columnGap: 2rem; } } + @media screen and (max-width: 1055px) { + .columns.is-variable.is-8-touch { + --columnGap: 2rem; } } + @media screen and (min-width: 1056px) { + .columns.is-variable.is-8-desktop { + --columnGap: 2rem; } } + @media screen and (min-width: 1056px) and (max-width: 1215px) { + .columns.is-variable.is-8-desktop-only { + --columnGap: 2rem; } } + @media screen and (min-width: 1216px) { + .columns.is-variable.is-8-widescreen { + --columnGap: 2rem; } } + @media screen and (min-width: 1216px) and (max-width: 1407px) { + .columns.is-variable.is-8-widescreen-only { + --columnGap: 2rem; } } + @media screen and (min-width: 1408px) { + .columns.is-variable.is-8-fullhd { + --columnGap: 2rem; } } +.tile { + align-items: stretch; + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + min-height: min-content; } + .tile.is-ancestor { + margin-left: -0.75rem; + margin-right: -0.75rem; + margin-top: -0.75rem; } + .tile.is-ancestor:last-child { + margin-bottom: -0.75rem; } + .tile.is-ancestor:not(:last-child) { + margin-bottom: 0.75rem; } + .tile.is-child { + margin: 0 !important; } + .tile.is-parent { + padding: 0.75rem; } + .tile.is-vertical { + flex-direction: column; } + .tile.is-vertical > .tile.is-child:not(:last-child) { + margin-bottom: 1.5rem !important; } + @media screen and (min-width: 769px), print { + .tile:not(.is-child) { + display: flex; } + .tile.is-1 { + flex: none; + width: 8.3333333333%; } + .tile.is-2 { + flex: none; + width: 16.6666666667%; } + .tile.is-3 { + flex: none; + width: 25%; } + .tile.is-4 { + flex: none; + width: 33.3333333333%; } + .tile.is-5 { + flex: none; + width: 41.6666666667%; } + .tile.is-6 { + flex: none; + width: 50%; } + .tile.is-7 { + flex: none; + width: 58.3333333333%; } + .tile.is-8 { + flex: none; + width: 66.6666666667%; } + .tile.is-9 { + flex: none; + width: 75%; } + .tile.is-10 { + flex: none; + width: 83.3333333333%; } + .tile.is-11 { + flex: none; + width: 91.6666666667%; } + .tile.is-12 { + flex: none; + width: 100%; } } +.hero { + align-items: stretch; + display: flex; + flex-direction: column; + justify-content: space-between; } + .hero .navbar { + background: none; } + .hero .tabs ul { + border-bottom: none; } + .hero.is-white { + background-color: white; + color: #0a0a0a; } + .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-white strong { + color: inherit; } + .hero.is-white .title { + color: #0a0a0a; } + .hero.is-white .subtitle { + color: rgba(10, 10, 10, 0.9); } + .hero.is-white .subtitle a:not(.button), + .hero.is-white .subtitle strong { + color: #0a0a0a; } + @media screen and (max-width: 1055px) { + .hero.is-white .navbar-menu { + background-color: white; } } + .hero.is-white .navbar-item, + .hero.is-white .navbar-link { + color: rgba(10, 10, 10, 0.7); } + .hero.is-white a.navbar-item:hover, .hero.is-white a.navbar-item.is-active, + .hero.is-white .navbar-link:hover, + .hero.is-white .navbar-link.is-active { + background-color: #f2f2f2; + color: #0a0a0a; } + .hero.is-white .tabs a { + color: #0a0a0a; + opacity: 0.9; } + .hero.is-white .tabs a:hover { + opacity: 1; } + .hero.is-white .tabs li.is-active a { + opacity: 1; } + .hero.is-white .tabs.is-boxed a, .hero.is-white .tabs.is-toggle a { + color: #0a0a0a; } + .hero.is-white .tabs.is-boxed a:hover, .hero.is-white .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-white .tabs.is-boxed li.is-active a, .hero.is-white .tabs.is-boxed li.is-active a:hover, .hero.is-white .tabs.is-toggle li.is-active a, .hero.is-white .tabs.is-toggle li.is-active a:hover { + background-color: #0a0a0a; + border-color: #0a0a0a; + color: white; } + .hero.is-white.is-bold { + background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); } + @media screen and (max-width: 768px) { + .hero.is-white.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #e8e3e4 0%, white 71%, white 100%); } } + .hero.is-black { + background-color: #0a0a0a; + color: white; } + .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-black strong { + color: inherit; } + .hero.is-black .title { + color: white; } + .hero.is-black .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-black .subtitle a:not(.button), + .hero.is-black .subtitle strong { + color: white; } + @media screen and (max-width: 1055px) { + .hero.is-black .navbar-menu { + background-color: #0a0a0a; } } + .hero.is-black .navbar-item, + .hero.is-black .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-black a.navbar-item:hover, .hero.is-black a.navbar-item.is-active, + .hero.is-black .navbar-link:hover, + .hero.is-black .navbar-link.is-active { + background-color: black; + color: white; } + .hero.is-black .tabs a { + color: white; + opacity: 0.9; } + .hero.is-black .tabs a:hover { + opacity: 1; } + .hero.is-black .tabs li.is-active a { + opacity: 1; } + .hero.is-black .tabs.is-boxed a, .hero.is-black .tabs.is-toggle a { + color: white; } + .hero.is-black .tabs.is-boxed a:hover, .hero.is-black .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-black .tabs.is-boxed li.is-active a, .hero.is-black .tabs.is-boxed li.is-active a:hover, .hero.is-black .tabs.is-toggle li.is-active a, .hero.is-black .tabs.is-toggle li.is-active a:hover { + background-color: white; + border-color: white; + color: #0a0a0a; } + .hero.is-black.is-bold { + background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } + @media screen and (max-width: 768px) { + .hero.is-black.is-bold .navbar-menu { + background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } } + .hero.is-light { + background-color: whitesmoke; + color: #363636; } + .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-light strong { + color: inherit; } + .hero.is-light .title { + color: #363636; } + .hero.is-light .subtitle { + color: rgba(54, 54, 54, 0.9); } + .hero.is-light .subtitle a:not(.button), + .hero.is-light .subtitle strong { + color: #363636; } + @media screen and (max-width: 1055px) { + .hero.is-light .navbar-menu { + background-color: whitesmoke; } } + .hero.is-light .navbar-item, + .hero.is-light .navbar-link { + color: rgba(54, 54, 54, 0.7); } + .hero.is-light a.navbar-item:hover, .hero.is-light a.navbar-item.is-active, + .hero.is-light .navbar-link:hover, + .hero.is-light .navbar-link.is-active { + background-color: #e8e8e8; + color: #363636; } + .hero.is-light .tabs a { + color: #363636; + opacity: 0.9; } + .hero.is-light .tabs a:hover { + opacity: 1; } + .hero.is-light .tabs li.is-active a { + opacity: 1; } + .hero.is-light .tabs.is-boxed a, .hero.is-light .tabs.is-toggle a { + color: #363636; } + .hero.is-light .tabs.is-boxed a:hover, .hero.is-light .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-light .tabs.is-boxed li.is-active a, .hero.is-light .tabs.is-boxed li.is-active a:hover, .hero.is-light .tabs.is-toggle li.is-active a, .hero.is-light .tabs.is-toggle li.is-active a:hover { + background-color: #363636; + border-color: #363636; + color: whitesmoke; } + .hero.is-light.is-bold { + background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); } + @media screen and (max-width: 768px) { + .hero.is-light.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); } } + .hero.is-dark, .content kbd.hero { + background-color: #363636; + color: whitesmoke; } + .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-dark strong, + .content kbd.hero strong { + color: inherit; } + .hero.is-dark .title, .content kbd.hero .title { + color: whitesmoke; } + .hero.is-dark .subtitle, .content kbd.hero .subtitle { + color: rgba(245, 245, 245, 0.9); } + .hero.is-dark .subtitle a:not(.button), .content kbd.hero .subtitle a:not(.button), + .hero.is-dark .subtitle strong, + .content kbd.hero .subtitle strong { + color: whitesmoke; } + @media screen and (max-width: 1055px) { + .hero.is-dark .navbar-menu, .content kbd.hero .navbar-menu { + background-color: #363636; } } + .hero.is-dark .navbar-item, .content kbd.hero .navbar-item, + .hero.is-dark .navbar-link, + .content kbd.hero .navbar-link { + color: rgba(245, 245, 245, 0.7); } + .hero.is-dark a.navbar-item:hover, .content kbd.hero a.navbar-item:hover, .hero.is-dark a.navbar-item.is-active, .content kbd.hero a.navbar-item.is-active, + .hero.is-dark .navbar-link:hover, + .content kbd.hero .navbar-link:hover, + .hero.is-dark .navbar-link.is-active, + .content kbd.hero .navbar-link.is-active { + background-color: #292929; + color: whitesmoke; } + .hero.is-dark .tabs a, .content kbd.hero .tabs a { + color: whitesmoke; + opacity: 0.9; } + .hero.is-dark .tabs a:hover, .content kbd.hero .tabs a:hover { + opacity: 1; } + .hero.is-dark .tabs li.is-active a, .content kbd.hero .tabs li.is-active a { + opacity: 1; } + .hero.is-dark .tabs.is-boxed a, .content kbd.hero .tabs.is-boxed a, .hero.is-dark .tabs.is-toggle a, .content kbd.hero .tabs.is-toggle a { + color: whitesmoke; } + .hero.is-dark .tabs.is-boxed a:hover, .content kbd.hero .tabs.is-boxed a:hover, .hero.is-dark .tabs.is-toggle a:hover, .content kbd.hero .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-dark .tabs.is-boxed li.is-active a, .content kbd.hero .tabs.is-boxed li.is-active a, .hero.is-dark .tabs.is-boxed li.is-active a:hover, .hero.is-dark .tabs.is-toggle li.is-active a, .content kbd.hero .tabs.is-toggle li.is-active a, .hero.is-dark .tabs.is-toggle li.is-active a:hover { + background-color: whitesmoke; + border-color: whitesmoke; + color: #363636; } + .hero.is-dark.is-bold, .content kbd.hero.is-bold { + background-image: linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%); } + @media screen and (max-width: 768px) { + .hero.is-dark.is-bold .navbar-menu, .content kbd.hero.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%); } } + .hero.is-primary, .docstring > section > a.hero.docs-sourcelink { + background-color: #4eb5de; + color: #fff; } + .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), .docstring > section > a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-primary strong, + .docstring > section > a.hero.docs-sourcelink strong { + color: inherit; } + .hero.is-primary .title, .docstring > section > a.hero.docs-sourcelink .title { + color: #fff; } + .hero.is-primary .subtitle, .docstring > section > a.hero.docs-sourcelink .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-primary .subtitle a:not(.button), .docstring > section > a.hero.docs-sourcelink .subtitle a:not(.button), + .hero.is-primary .subtitle strong, + .docstring > section > a.hero.docs-sourcelink .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + .hero.is-primary .navbar-menu, .docstring > section > a.hero.docs-sourcelink .navbar-menu { + background-color: #4eb5de; } } + .hero.is-primary .navbar-item, .docstring > section > a.hero.docs-sourcelink .navbar-item, + .hero.is-primary .navbar-link, + .docstring > section > a.hero.docs-sourcelink .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-primary a.navbar-item:hover, .docstring > section > a.hero.docs-sourcelink a.navbar-item:hover, .hero.is-primary a.navbar-item.is-active, .docstring > section > a.hero.docs-sourcelink a.navbar-item.is-active, + .hero.is-primary .navbar-link:hover, + .docstring > section > a.hero.docs-sourcelink .navbar-link:hover, + .hero.is-primary .navbar-link.is-active, + .docstring > section > a.hero.docs-sourcelink .navbar-link.is-active { + background-color: #39acda; + color: #fff; } + .hero.is-primary .tabs a, .docstring > section > a.hero.docs-sourcelink .tabs a { + color: #fff; + opacity: 0.9; } + .hero.is-primary .tabs a:hover, .docstring > section > a.hero.docs-sourcelink .tabs a:hover { + opacity: 1; } + .hero.is-primary .tabs li.is-active a, .docstring > section > a.hero.docs-sourcelink .tabs li.is-active a { + opacity: 1; } + .hero.is-primary .tabs.is-boxed a, .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed a, .hero.is-primary .tabs.is-toggle a, .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle a { + color: #fff; } + .hero.is-primary .tabs.is-boxed a:hover, .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed a:hover, .hero.is-primary .tabs.is-toggle a:hover, .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-primary .tabs.is-boxed li.is-active a, .docstring > section > a.hero.docs-sourcelink .tabs.is-boxed li.is-active a, .hero.is-primary .tabs.is-boxed li.is-active a:hover, .hero.is-primary .tabs.is-toggle li.is-active a, .docstring > section > a.hero.docs-sourcelink .tabs.is-toggle li.is-active a, .hero.is-primary .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #4eb5de; } + .hero.is-primary.is-bold, .docstring > section > a.hero.is-bold.docs-sourcelink { + background-image: linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%); } + @media screen and (max-width: 768px) { + .hero.is-primary.is-bold .navbar-menu, .docstring > section > a.hero.is-bold.docs-sourcelink .navbar-menu { + background-image: linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%); } } + .hero.is-link { + background-color: #2e63b8; + color: #fff; } + .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-link strong { + color: inherit; } + .hero.is-link .title { + color: #fff; } + .hero.is-link .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-link .subtitle a:not(.button), + .hero.is-link .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + .hero.is-link .navbar-menu { + background-color: #2e63b8; } } + .hero.is-link .navbar-item, + .hero.is-link .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-link a.navbar-item:hover, .hero.is-link a.navbar-item.is-active, + .hero.is-link .navbar-link:hover, + .hero.is-link .navbar-link.is-active { + background-color: #2958a4; + color: #fff; } + .hero.is-link .tabs a { + color: #fff; + opacity: 0.9; } + .hero.is-link .tabs a:hover { + opacity: 1; } + .hero.is-link .tabs li.is-active a { + opacity: 1; } + .hero.is-link .tabs.is-boxed a, .hero.is-link .tabs.is-toggle a { + color: #fff; } + .hero.is-link .tabs.is-boxed a:hover, .hero.is-link .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-link .tabs.is-boxed li.is-active a, .hero.is-link .tabs.is-boxed li.is-active a:hover, .hero.is-link .tabs.is-toggle li.is-active a, .hero.is-link .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #2e63b8; } + .hero.is-link.is-bold { + background-image: linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%); } + @media screen and (max-width: 768px) { + .hero.is-link.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%); } } + .hero.is-info { + background-color: #209cee; + color: #fff; } + .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-info strong { + color: inherit; } + .hero.is-info .title { + color: #fff; } + .hero.is-info .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-info .subtitle a:not(.button), + .hero.is-info .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + .hero.is-info .navbar-menu { + background-color: #209cee; } } + .hero.is-info .navbar-item, + .hero.is-info .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-info a.navbar-item:hover, .hero.is-info a.navbar-item.is-active, + .hero.is-info .navbar-link:hover, + .hero.is-info .navbar-link.is-active { + background-color: #1190e3; + color: #fff; } + .hero.is-info .tabs a { + color: #fff; + opacity: 0.9; } + .hero.is-info .tabs a:hover { + opacity: 1; } + .hero.is-info .tabs li.is-active a { + opacity: 1; } + .hero.is-info .tabs.is-boxed a, .hero.is-info .tabs.is-toggle a { + color: #fff; } + .hero.is-info .tabs.is-boxed a:hover, .hero.is-info .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-info .tabs.is-boxed li.is-active a, .hero.is-info .tabs.is-boxed li.is-active a:hover, .hero.is-info .tabs.is-toggle li.is-active a, .hero.is-info .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #209cee; } + .hero.is-info.is-bold { + background-image: linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%); } + @media screen and (max-width: 768px) { + .hero.is-info.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%); } } + .hero.is-success { + background-color: #22c35b; + color: #fff; } + .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-success strong { + color: inherit; } + .hero.is-success .title { + color: #fff; } + .hero.is-success .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-success .subtitle a:not(.button), + .hero.is-success .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + .hero.is-success .navbar-menu { + background-color: #22c35b; } } + .hero.is-success .navbar-item, + .hero.is-success .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-success a.navbar-item:hover, .hero.is-success a.navbar-item.is-active, + .hero.is-success .navbar-link:hover, + .hero.is-success .navbar-link.is-active { + background-color: #1ead51; + color: #fff; } + .hero.is-success .tabs a { + color: #fff; + opacity: 0.9; } + .hero.is-success .tabs a:hover { + opacity: 1; } + .hero.is-success .tabs li.is-active a { + opacity: 1; } + .hero.is-success .tabs.is-boxed a, .hero.is-success .tabs.is-toggle a { + color: #fff; } + .hero.is-success .tabs.is-boxed a:hover, .hero.is-success .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-success .tabs.is-boxed li.is-active a, .hero.is-success .tabs.is-boxed li.is-active a:hover, .hero.is-success .tabs.is-toggle li.is-active a, .hero.is-success .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #22c35b; } + .hero.is-success.is-bold { + background-image: linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%); } + @media screen and (max-width: 768px) { + .hero.is-success.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%); } } + .hero.is-warning { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-warning strong { + color: inherit; } + .hero.is-warning .title { + color: rgba(0, 0, 0, 0.7); } + .hero.is-warning .subtitle { + color: rgba(0, 0, 0, 0.9); } + .hero.is-warning .subtitle a:not(.button), + .hero.is-warning .subtitle strong { + color: rgba(0, 0, 0, 0.7); } + @media screen and (max-width: 1055px) { + .hero.is-warning .navbar-menu { + background-color: #ffdd57; } } + .hero.is-warning .navbar-item, + .hero.is-warning .navbar-link { + color: rgba(0, 0, 0, 0.7); } + .hero.is-warning a.navbar-item:hover, .hero.is-warning a.navbar-item.is-active, + .hero.is-warning .navbar-link:hover, + .hero.is-warning .navbar-link.is-active { + background-color: #ffd83e; + color: rgba(0, 0, 0, 0.7); } + .hero.is-warning .tabs a { + color: rgba(0, 0, 0, 0.7); + opacity: 0.9; } + .hero.is-warning .tabs a:hover { + opacity: 1; } + .hero.is-warning .tabs li.is-active a { + opacity: 1; } + .hero.is-warning .tabs.is-boxed a, .hero.is-warning .tabs.is-toggle a { + color: rgba(0, 0, 0, 0.7); } + .hero.is-warning .tabs.is-boxed a:hover, .hero.is-warning .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-warning .tabs.is-boxed li.is-active a, .hero.is-warning .tabs.is-boxed li.is-active a:hover, .hero.is-warning .tabs.is-toggle li.is-active a, .hero.is-warning .tabs.is-toggle li.is-active a:hover { + background-color: rgba(0, 0, 0, 0.7); + border-color: rgba(0, 0, 0, 0.7); + color: #ffdd57; } + .hero.is-warning.is-bold { + background-image: linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%); } + @media screen and (max-width: 768px) { + .hero.is-warning.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%); } } + .hero.is-danger { + background-color: #da0b00; + color: #fff; } + .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current), + .hero.is-danger strong { + color: inherit; } + .hero.is-danger .title { + color: #fff; } + .hero.is-danger .subtitle { + color: rgba(255, 255, 255, 0.9); } + .hero.is-danger .subtitle a:not(.button), + .hero.is-danger .subtitle strong { + color: #fff; } + @media screen and (max-width: 1055px) { + .hero.is-danger .navbar-menu { + background-color: #da0b00; } } + .hero.is-danger .navbar-item, + .hero.is-danger .navbar-link { + color: rgba(255, 255, 255, 0.7); } + .hero.is-danger a.navbar-item:hover, .hero.is-danger a.navbar-item.is-active, + .hero.is-danger .navbar-link:hover, + .hero.is-danger .navbar-link.is-active { + background-color: #c10a00; + color: #fff; } + .hero.is-danger .tabs a { + color: #fff; + opacity: 0.9; } + .hero.is-danger .tabs a:hover { + opacity: 1; } + .hero.is-danger .tabs li.is-active a { + opacity: 1; } + .hero.is-danger .tabs.is-boxed a, .hero.is-danger .tabs.is-toggle a { + color: #fff; } + .hero.is-danger .tabs.is-boxed a:hover, .hero.is-danger .tabs.is-toggle a:hover { + background-color: rgba(10, 10, 10, 0.1); } + .hero.is-danger .tabs.is-boxed li.is-active a, .hero.is-danger .tabs.is-boxed li.is-active a:hover, .hero.is-danger .tabs.is-toggle li.is-active a, .hero.is-danger .tabs.is-toggle li.is-active a:hover { + background-color: #fff; + border-color: #fff; + color: #da0b00; } + .hero.is-danger.is-bold { + background-image: linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%); } + @media screen and (max-width: 768px) { + .hero.is-danger.is-bold .navbar-menu { + background-image: linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%); } } + .hero.is-small .hero-body, #documenter .docs-sidebar form.docs-search > input.hero .hero-body { + padding-bottom: 1.5rem; + padding-top: 1.5rem; } + @media screen and (min-width: 769px), print { + .hero.is-medium .hero-body { + padding-bottom: 9rem; + padding-top: 9rem; } } + @media screen and (min-width: 769px), print { + .hero.is-large .hero-body { + padding-bottom: 18rem; + padding-top: 18rem; } } + .hero.is-halfheight .hero-body, .hero.is-fullheight .hero-body, .hero.is-fullheight-with-navbar .hero-body { + align-items: center; + display: flex; } + .hero.is-halfheight .hero-body > .container, .hero.is-fullheight .hero-body > .container, .hero.is-fullheight-with-navbar .hero-body > .container { + flex-grow: 1; + flex-shrink: 1; } + .hero.is-halfheight { + min-height: 50vh; } + .hero.is-fullheight { + min-height: 100vh; } + +.hero-video { + overflow: hidden; } + .hero-video video { + left: 50%; + min-height: 100%; + min-width: 100%; + position: absolute; + top: 50%; + transform: translate3d(-50%, -50%, 0); } + .hero-video.is-transparent { + opacity: 0.3; } + @media screen and (max-width: 768px) { + .hero-video { + display: none; } } +.hero-buttons { + margin-top: 1.5rem; } + @media screen and (max-width: 768px) { + .hero-buttons .button { + display: flex; } + .hero-buttons .button:not(:last-child) { + margin-bottom: 0.75rem; } } + @media screen and (min-width: 769px), print { + .hero-buttons { + display: flex; + justify-content: center; } + .hero-buttons .button:not(:last-child) { + margin-right: 1.5rem; } } +.hero-head, +.hero-foot { + flex-grow: 0; + flex-shrink: 0; } + +.hero-body { + flex-grow: 1; + flex-shrink: 0; + padding: 3rem 1.5rem; } + +.section { + padding: 3rem 1.5rem; } + @media screen and (min-width: 1056px) { + .section.is-medium { + padding: 9rem 1.5rem; } + .section.is-large { + padding: 18rem 1.5rem; } } +.footer { + background-color: #fafafa; + padding: 3rem 1.5rem 6rem; } + +h1 .docs-heading-anchor, h1 .docs-heading-anchor:hover, h1 .docs-heading-anchor:visited, h2 .docs-heading-anchor, h2 .docs-heading-anchor:hover, h2 .docs-heading-anchor:visited, h3 .docs-heading-anchor, h3 .docs-heading-anchor:hover, h3 .docs-heading-anchor:visited, h4 .docs-heading-anchor, h4 .docs-heading-anchor:hover, h4 .docs-heading-anchor:visited, h5 .docs-heading-anchor, h5 .docs-heading-anchor:hover, h5 .docs-heading-anchor:visited, h6 .docs-heading-anchor, h6 .docs-heading-anchor:hover, h6 .docs-heading-anchor:visited { + color: #222222; } + +h1 .docs-heading-anchor-permalink, h2 .docs-heading-anchor-permalink, h3 .docs-heading-anchor-permalink, h4 .docs-heading-anchor-permalink, h5 .docs-heading-anchor-permalink, h6 .docs-heading-anchor-permalink { + visibility: hidden; + vertical-align: middle; + margin-left: 0.5em; + font-size: 0.7rem; } + h1 .docs-heading-anchor-permalink::before, h2 .docs-heading-anchor-permalink::before, h3 .docs-heading-anchor-permalink::before, h4 .docs-heading-anchor-permalink::before, h5 .docs-heading-anchor-permalink::before, h6 .docs-heading-anchor-permalink::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0c1"; } + +h1:hover .docs-heading-anchor-permalink, h2:hover .docs-heading-anchor-permalink, h3:hover .docs-heading-anchor-permalink, h4:hover .docs-heading-anchor-permalink, h5:hover .docs-heading-anchor-permalink, h6:hover .docs-heading-anchor-permalink { + visibility: visible; } + +.docs-dark-only { + display: none !important; } + +pre { + position: relative; + overflow: hidden; } + pre code, pre code.hljs { + padding: 0 0.75rem !important; + overflow: auto; + display: block; } + pre code:first-of-type, pre code.hljs:first-of-type { + padding-top: 0.5rem !important; } + pre code:last-of-type, pre code.hljs:last-of-type { + padding-bottom: 0.5rem !important; } + pre .copy-button { + opacity: 0.2; + transition: opacity 0.2s; + position: absolute; + right: 0em; + top: 0em; + padding: 0.5em; + width: 2.5em; + height: 2.5em; + background: transparent; + border: none; + font-family: "Font Awesome 5 Free"; + color: #222222; + cursor: pointer; + text-align: center; } + pre .copy-button:focus, pre .copy-button:hover { + opacity: 1; + background: rgba(34, 34, 34, 0.1); + color: #2e63b8; } + pre .copy-button.success { + color: #259a12; + opacity: 1; } + pre .copy-button.error { + color: #cb3c33; + opacity: 1; } + pre:hover .copy-button { + opacity: 1; } + +.admonition { + background-color: #b5b5b5; + border-style: solid; + border-width: 1px; + border-color: #363636; + border-radius: 4px; + font-size: 1rem; } + .admonition strong { + color: currentColor; } + .admonition.is-small, #documenter .docs-sidebar form.docs-search > input.admonition { + font-size: 0.75rem; } + .admonition.is-medium { + font-size: 1.25rem; } + .admonition.is-large { + font-size: 1.5rem; } + .admonition.is-default { + background-color: #b5b5b5; + border-color: #363636; } + .admonition.is-default > .admonition-header { + background-color: #363636; + color: #fff; } + .admonition.is-default > .admonition-body { + color: #fff; } + .admonition.is-info { + background-color: #def0fc; + border-color: #209cee; } + .admonition.is-info > .admonition-header { + background-color: #209cee; + color: #fff; } + .admonition.is-info > .admonition-body { + color: rgba(0, 0, 0, 0.7); } + .admonition.is-success { + background-color: #bdf4d1; + border-color: #22c35b; } + .admonition.is-success > .admonition-header { + background-color: #22c35b; + color: #fff; } + .admonition.is-success > .admonition-body { + color: rgba(0, 0, 0, 0.7); } + .admonition.is-warning { + background-color: #fff3c5; + border-color: #ffdd57; } + .admonition.is-warning > .admonition-header { + background-color: #ffdd57; + color: rgba(0, 0, 0, 0.7); } + .admonition.is-warning > .admonition-body { + color: rgba(0, 0, 0, 0.7); } + .admonition.is-danger { + background-color: #ffaba7; + border-color: #da0b00; } + .admonition.is-danger > .admonition-header { + background-color: #da0b00; + color: #fff; } + .admonition.is-danger > .admonition-body { + color: rgba(0, 0, 0, 0.7); } + .admonition.is-compat { + background-color: #bdeff5; + border-color: #1db5c9; } + .admonition.is-compat > .admonition-header { + background-color: #1db5c9; + color: #fff; } + .admonition.is-compat > .admonition-body { + color: rgba(0, 0, 0, 0.7); } + +.admonition-header { + color: #fff; + background-color: #363636; + align-items: center; + font-weight: 700; + justify-content: space-between; + line-height: 1.25; + padding: 0.5rem 0.75rem; + position: relative; } + .admonition-header:before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + margin-right: 0.75rem; + content: "\f06a"; } + +.admonition-body { + color: #222222; + padding: 0.5rem 0.75rem; } + .admonition-body pre { + background-color: whitesmoke; } + .admonition-body code { + background-color: rgba(0, 0, 0, 0.05); } + +.docstring { + margin-bottom: 1em; + background-color: transparent; + border: 1px solid #dbdbdb; + box-shadow: 2px 2px 3px rgba(10, 10, 10, 0.1); + max-width: 100%; } + .docstring > header { + display: flex; + flex-grow: 1; + align-items: stretch; + padding: 0.5rem 0.75rem; + background-color: whitesmoke; + box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1); + box-shadow: none; + border-bottom: 1px solid #dbdbdb; } + .docstring > header code { + background-color: transparent; } + .docstring > header .docstring-binding { + margin-right: 0.3em; } + .docstring > header .docstring-category { + margin-left: 0.3em; } + .docstring > section { + position: relative; + padding: 0.75rem 0.75rem; + border-bottom: 1px solid #dbdbdb; } + .docstring > section:last-child { + border-bottom: none; } + .docstring > section > a.docs-sourcelink { + transition: opacity 0.3s; + opacity: 0; + position: absolute; + right: 0.375rem; + bottom: 0.375rem; } + .docstring > section > a.docs-sourcelink:focus { + opacity: 1 !important; } + .docstring:hover > section > a.docs-sourcelink { + opacity: 0.2; } + .docstring:focus-within > section > a.docs-sourcelink { + opacity: 0.2; } + .docstring > section:hover a.docs-sourcelink { + opacity: 1; } + +.documenter-example-output { + background-color: white; } + +.outdated-warning-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + z-index: 999; + background-color: #ffaba7; + color: rgba(0, 0, 0, 0.7); + border-bottom: 3px solid #da0b00; + padding: 10px 35px; + text-align: center; + font-size: 15px; } + .outdated-warning-overlay .outdated-warning-closer { + position: absolute; + top: calc(50% - 10px); + right: 18px; + cursor: pointer; + width: 12px; } + .outdated-warning-overlay a { + color: #2e63b8; } + .outdated-warning-overlay a:hover { + color: #363636; } + +.content pre { + border: 1px solid #dbdbdb; } + +.content code { + font-weight: inherit; } + +.content a code { + color: #2e63b8; } + +.content h1 code, .content h2 code, .content h3 code, .content h4 code, .content h5 code, .content h6 code { + color: #222222; } + +.content table { + display: block; + width: initial; + max-width: 100%; + overflow-x: auto; } + +.content blockquote > ul:first-child, .content blockquote > ol:first-child, .content .admonition-body > ul:first-child, .content .admonition-body > ol:first-child { + margin-top: 0; } + +pre, code { + font-variant-ligatures: no-contextual; } + +.breadcrumb a.is-disabled { + cursor: default; + pointer-events: none; } + .breadcrumb a.is-disabled, .breadcrumb a.is-disabled:hover { + color: #222222; } + +.hljs { + background: initial !important; } + +.katex .katex-mathml { + top: 0; + right: 0; } + +.katex-display, mjx-container, .MathJax_Display { + margin: 0.5em 0 !important; } + +html { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: auto; } + +li.no-marker { + list-style: none; } + +/* This file contain the overall layout. + * + * The main container is
    that is identified by id #documenter. + */ +#documenter .docs-main > article { + overflow-wrap: break-word; } + #documenter .docs-main > article .math-container { + overflow-x: auto; + overflow-y: hidden; } + +@media screen and (min-width: 1056px) { + #documenter .docs-main { + max-width: 52rem; + margin-left: 20rem; + padding-right: 1rem; } } + +@media screen and (max-width: 1055px) { + #documenter .docs-main { + width: 100%; } + #documenter .docs-main > article { + max-width: 52rem; + margin-left: auto; + margin-right: auto; + margin-bottom: 1rem; + padding: 0 1rem; } + #documenter .docs-main > header, #documenter .docs-main > nav { + max-width: 100%; + width: 100%; + margin: 0; } } + +#documenter .docs-main header.docs-navbar { + background-color: white; + border-bottom: 1px solid #dbdbdb; + z-index: 2; + min-height: 4rem; + margin-bottom: 1rem; + display: flex; } + #documenter .docs-main header.docs-navbar .breadcrumb { + flex-grow: 1; } + #documenter .docs-main header.docs-navbar .docs-right { + display: flex; + white-space: nowrap; } + #documenter .docs-main header.docs-navbar .docs-right .docs-icon, #documenter .docs-main header.docs-navbar .docs-right .docs-label, #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button { + display: inline-block; } + #documenter .docs-main header.docs-navbar .docs-right .docs-label { + padding: 0; + margin-left: 0.3em; } + #documenter .docs-main header.docs-navbar .docs-right .docs-settings-button { + margin: auto 0 auto 1rem; } + #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button { + font-size: 1.5rem; + margin: auto 0 auto 1rem; } + #documenter .docs-main header.docs-navbar > * { + margin: auto 0; } + @media screen and (max-width: 1055px) { + #documenter .docs-main header.docs-navbar { + position: sticky; + top: 0; + padding: 0 1rem; + /* For Headroom.js */ + transition-property: top, box-shadow; + -webkit-transition-property: top, box-shadow; + /* Safari */ + transition-duration: 0.3s; + -webkit-transition-duration: 0.3s; + /* Safari */ } + #documenter .docs-main header.docs-navbar.headroom--not-top { + box-shadow: 0.2rem 0rem 0.4rem #bbb; + transition-duration: 0.7s; + -webkit-transition-duration: 0.7s; + /* Safari */ } + #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom { + top: -4.5rem; + transition-duration: 0.7s; + -webkit-transition-duration: 0.7s; + /* Safari */ } } +#documenter .docs-main section.footnotes { + border-top: 1px solid #dbdbdb; } + #documenter .docs-main section.footnotes li .tag:first-child, #documenter .docs-main section.footnotes li .docstring > section > a.docs-sourcelink:first-child, #documenter .docs-main section.footnotes li .content kbd:first-child, .content #documenter .docs-main section.footnotes li kbd:first-child { + margin-right: 1em; + margin-bottom: 0.4em; } + +#documenter .docs-main .docs-footer { + display: flex; + flex-wrap: wrap; + margin-left: 0; + margin-right: 0; + border-top: 1px solid #dbdbdb; + padding-top: 1rem; + padding-bottom: 1rem; } + @media screen and (max-width: 1055px) { + #documenter .docs-main .docs-footer { + padding-left: 1rem; + padding-right: 1rem; } } + #documenter .docs-main .docs-footer .docs-footer-nextpage, #documenter .docs-main .docs-footer .docs-footer-prevpage { + flex-grow: 1; } + #documenter .docs-main .docs-footer .docs-footer-nextpage { + text-align: right; } + #documenter .docs-main .docs-footer .flexbox-break { + flex-basis: 100%; + height: 0; } + #documenter .docs-main .docs-footer .footer-message { + font-size: 0.8em; + margin: 0.5em auto 0 auto; + text-align: center; } + +#documenter .docs-sidebar { + display: flex; + flex-direction: column; + color: #0a0a0a; + background-color: whitesmoke; + border-right: 1px solid #dbdbdb; + padding: 0; + flex: 0 0 18rem; + z-index: 5; + font-size: 1rem; + position: fixed; + left: -18rem; + width: 18rem; + height: 100%; + transition: left 0.3s; + /* Setting up a nicer theme style for the scrollbar */ } + #documenter .docs-sidebar.visible { + left: 0; + box-shadow: 0.4rem 0rem 0.8rem #bbb; } + @media screen and (min-width: 1056px) { + #documenter .docs-sidebar.visible { + box-shadow: none; } } + @media screen and (min-width: 1056px) { + #documenter .docs-sidebar { + left: 0; + top: 0; } } + #documenter .docs-sidebar .docs-logo { + margin-top: 1rem; + padding: 0 1rem; } + #documenter .docs-sidebar .docs-logo > img { + max-height: 6rem; + margin: auto; } + #documenter .docs-sidebar .docs-package-name { + flex-shrink: 0; + font-size: 1.5rem; + font-weight: 700; + text-align: center; + white-space: nowrap; + overflow: hidden; + padding: 0.5rem 0; } + #documenter .docs-sidebar .docs-package-name .docs-autofit { + max-width: 16.2rem; } + #documenter .docs-sidebar .docs-package-name a, #documenter .docs-sidebar .docs-package-name a:hover { + color: #0a0a0a; } + #documenter .docs-sidebar .docs-version-selector { + border-top: 1px solid #dbdbdb; + display: none; + padding: 0.5rem; } + #documenter .docs-sidebar .docs-version-selector.visible { + display: flex; } + #documenter .docs-sidebar ul.docs-menu { + flex-grow: 1; + user-select: none; + border-top: 1px solid #dbdbdb; + padding-bottom: 1.5rem; + /* Managing collapsible submenus */ } + #documenter .docs-sidebar ul.docs-menu > li > .tocitem { + font-weight: bold; } + #documenter .docs-sidebar ul.docs-menu > li li { + font-size: 0.95rem; + margin-left: 1em; + border-left: 1px solid #dbdbdb; } + #documenter .docs-sidebar ul.docs-menu input.collapse-toggle { + display: none; } + #documenter .docs-sidebar ul.docs-menu ul.collapsed { + display: none; } + #documenter .docs-sidebar ul.docs-menu input:checked ~ ul.collapsed { + display: block; } + #documenter .docs-sidebar ul.docs-menu label.tocitem { + display: flex; } + #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label { + flex-grow: 2; } + #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron { + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + font-size: 0.75rem; + margin-left: 1rem; + margin-top: auto; + margin-bottom: auto; } + #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f054"; } + #documenter .docs-sidebar ul.docs-menu input:checked ~ label.tocitem .docs-chevron::before { + content: "\f078"; } + #documenter .docs-sidebar ul.docs-menu .tocitem { + display: block; + padding: 0.5rem 0.5rem; } + #documenter .docs-sidebar ul.docs-menu .tocitem, #documenter .docs-sidebar ul.docs-menu .tocitem:hover { + color: #0a0a0a; + background: whitesmoke; } + #documenter .docs-sidebar ul.docs-menu a.tocitem:hover, #documenter .docs-sidebar ul.docs-menu label.tocitem:hover { + color: #0a0a0a; + background-color: #ebebeb; } + #documenter .docs-sidebar ul.docs-menu li.is-active { + border-top: 1px solid #dbdbdb; + border-bottom: 1px solid #dbdbdb; + background-color: white; } + #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem, #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover { + background-color: white; + color: #0a0a0a; } + #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover { + background-color: #ebebeb; + color: #0a0a0a; } + #documenter .docs-sidebar ul.docs-menu > li.is-active:first-child { + border-top: none; } + #documenter .docs-sidebar ul.docs-menu ul.internal { + margin: 0 0.5rem 0.5rem; + border-top: 1px solid #dbdbdb; } + #documenter .docs-sidebar ul.docs-menu ul.internal li { + font-size: 0.85rem; + border-left: none; + margin-left: 0; + margin-top: 0.5rem; } + #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem { + width: 100%; + padding: 0; } + #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before { + content: "⚬"; + margin-right: 0.4em; } + #documenter .docs-sidebar form.docs-search { + margin: auto; + margin-top: 0.5rem; + margin-bottom: 0.5rem; } + #documenter .docs-sidebar form.docs-search > input { + width: 14.4rem; } + @media screen and (min-width: 1056px) { + #documenter .docs-sidebar ul.docs-menu { + overflow-y: auto; + -webkit-overflow-scroll: touch; } + #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar { + width: .3rem; + background: none; } + #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb { + border-radius: 5px 0px 0px 5px; + background: #e0e0e0; } + #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover { + background: #cccccc; } } + @media screen and (max-width: 1055px) { + #documenter .docs-sidebar { + overflow-y: auto; + -webkit-overflow-scroll: touch; } + #documenter .docs-sidebar::-webkit-scrollbar { + width: .3rem; + background: none; } + #documenter .docs-sidebar::-webkit-scrollbar-thumb { + border-radius: 5px 0px 0px 5px; + background: #e0e0e0; } + #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover { + background: #cccccc; } } +#documenter .docs-main #documenter-search-info { + margin-bottom: 1rem; } + +#documenter .docs-main #documenter-search-results { + list-style-type: circle; + list-style-position: outside; } + #documenter .docs-main #documenter-search-results li { + margin-left: 2rem; } + #documenter .docs-main #documenter-search-results .docs-highlight { + background-color: yellow; } + +.ansi span.sgr1 { + font-weight: bolder; } + +.ansi span.sgr2 { + font-weight: lighter; } + +.ansi span.sgr3 { + font-style: italic; } + +.ansi span.sgr4 { + text-decoration: underline; } + +.ansi span.sgr7 { + color: white; + background-color: #222222; } + +.ansi span.sgr8 { + color: transparent; } + .ansi span.sgr8 span { + color: transparent; } + +.ansi span.sgr9 { + text-decoration: line-through; } + +.ansi span.sgr30 { + color: #242424; } + +.ansi span.sgr31 { + color: #a7201f; } + +.ansi span.sgr32 { + color: #066f00; } + +.ansi span.sgr33 { + color: #856b00; } + +.ansi span.sgr34 { + color: #2149b0; } + +.ansi span.sgr35 { + color: #7d4498; } + +.ansi span.sgr36 { + color: #007989; } + +.ansi span.sgr37 { + color: gray; } + +.ansi span.sgr40 { + background-color: #242424; } + +.ansi span.sgr41 { + background-color: #a7201f; } + +.ansi span.sgr42 { + background-color: #066f00; } + +.ansi span.sgr43 { + background-color: #856b00; } + +.ansi span.sgr44 { + background-color: #2149b0; } + +.ansi span.sgr45 { + background-color: #7d4498; } + +.ansi span.sgr46 { + background-color: #007989; } + +.ansi span.sgr47 { + background-color: gray; } + +.ansi span.sgr90 { + color: #616161; } + +.ansi span.sgr91 { + color: #cb3c33; } + +.ansi span.sgr92 { + color: #0e8300; } + +.ansi span.sgr93 { + color: #a98800; } + +.ansi span.sgr94 { + color: #3c5dcd; } + +.ansi span.sgr95 { + color: #9256af; } + +.ansi span.sgr96 { + color: #008fa3; } + +.ansi span.sgr97 { + color: whitesmoke; } + +.ansi span.sgr100 { + background-color: #616161; } + +.ansi span.sgr101 { + background-color: #cb3c33; } + +.ansi span.sgr102 { + background-color: #0e8300; } + +.ansi span.sgr103 { + background-color: #a98800; } + +.ansi span.sgr104 { + background-color: #3c5dcd; } + +.ansi span.sgr105 { + background-color: #9256af; } + +.ansi span.sgr106 { + background-color: #008fa3; } + +.ansi span.sgr107 { + background-color: whitesmoke; } + +code.language-julia-repl > span.hljs-meta { + color: #066f00; + font-weight: bolder; } + +/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/ +/* +This is left on purpose making default.css the single file that can be lifted +as-is from the repository directly without the need for a build step + +Typically this "required" baseline CSS is added by `makestuff.js` during build. +*/ +pre code.hljs { + display: block; + overflow-x: auto; } + +code.hljs { + padding: 3px 5px; } + +/* end baseline CSS */ +.hljs { + background: #F0F0F0; + color: #444; } + +/* Base color: saturation 0; */ +.hljs-subst { + /* default */ } + +/* purposely ignored */ +.hljs-comment { + color: #888888; } + +.hljs-tag, +.hljs-punctuation { + color: #444a; } + +.hljs-tag .hljs-name, +.hljs-tag .hljs-attr { + color: #444; } + +.hljs-keyword, +.hljs-attribute, +.hljs-selector-tag, +.hljs-meta .hljs-keyword, +.hljs-doctag, +.hljs-name { + font-weight: bold; } + +/* User color: hue: 0 */ +.hljs-type, +.hljs-string, +.hljs-number, +.hljs-selector-id, +.hljs-selector-class, +.hljs-quote, +.hljs-template-tag, +.hljs-deletion { + color: #880000; } + +.hljs-title, +.hljs-section { + color: #880000; + font-weight: bold; } + +.hljs-regexp, +.hljs-symbol, +.hljs-variable, +.hljs-template-variable, +.hljs-link, +.hljs-selector-attr, +.hljs-operator, +.hljs-selector-pseudo { + color: #BC6060; } + +/* Language color: hue: 90; */ +.hljs-literal { + color: #78A960; } + +.hljs-built_in, +.hljs-bullet, +.hljs-code, +.hljs-addition { + color: #397300; } + +/* Meta color: hue: 200 */ +.hljs-meta { + color: #1f7199; } + +.hljs-meta .hljs-string { + color: #4d99bf; } + +/* Misc effects */ +.hljs-emphasis { + font-style: italic; } + +.hljs-strong { + font-weight: bold; } diff --git a/previews/PR2003/assets/themeswap.js b/previews/PR2003/assets/themeswap.js new file mode 100644 index 0000000000..c58e993e3e --- /dev/null +++ b/previews/PR2003/assets/themeswap.js @@ -0,0 +1,66 @@ +// Small function to quickly swap out themes. Gets put into the tag.. +function set_theme_from_local_storage() { + // Intialize the theme to null, which means default + var theme = null; + // If the browser supports the localstorage and is not disabled then try to get the + // documenter theme + if(window.localStorage != null) { + // Get the user-picked theme from localStorage. May be `null`, which means the default + // theme. + theme = window.localStorage.getItem("documenter-theme"); + } + // Check if the browser supports user color preference + var darkPreference = false; + // Check if the users preference is for dark color scheme + if(window.matchMedia('(prefers-color-scheme: dark)').matches === true) { + darkPreference = true; + } + // Initialize a few variables for the loop: + // + // - active: will contain the index of the theme that should be active. Note that there + // is no guarantee that localStorage contains sane values. If `active` stays `null` + // we either could not find the theme or it is the default (primary) theme anyway. + // Either way, we then need to stick to the primary theme. + // + // - disabled: style sheets that should be disabled (i.e. all the theme style sheets + // that are not the currently active theme) + var active = null; var disabled = []; var darkTheme = null; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if(themename === null) continue; + // To distinguish the default (primary) theme, it needs to have the data-theme-primary + // attribute set. + var isprimary = (ss.ownerNode.getAttribute("data-theme-primary") !== null); + // Check if the theme is primary dark theme + var isDarkTheme = (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null); + // If ss is for dark theme then set the value of darkTheme to the name of the theme + if(isDarkTheme) darkTheme = themename; + // If we find a matching theme (and it's not the default), we'll set active to non-null + if(themename === theme) active = i; + // Store the style sheets of inactive themes so that we could disable them + if(themename !== theme) disabled.push(ss); + } + if(active !== null) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName('html')[0].className = "theme--" + theme; + // and (2) disable all the other theme stylesheets + disabled.forEach(function(ss){ + ss.disabled = true; + }); + } + else if(darkTheme !== null && darkPreference === true) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName('html')[0].className = "theme--" + darkTheme; + // and (2) disable all the other theme stylesheets + disabled.forEach(function(ss){ + if (ss.ownerNode.getAttribute("data-theme-name") !== darkTheme) { + ss.disabled = true; + } + }); + } +} +set_theme_from_local_storage(); diff --git a/previews/PR2003/assets/warner.js b/previews/PR2003/assets/warner.js new file mode 100644 index 0000000000..5531c8851b --- /dev/null +++ b/previews/PR2003/assets/warner.js @@ -0,0 +1,49 @@ +function maybeAddWarning () { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return + }; + + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return + }; + + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return + }; + + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement('meta'); + meta.name = 'robots'; + meta.content = 'noindex'; + + document.getElementsByTagName('head')[0].appendChild(meta); + }; + + const div = document.createElement('div'); + div.classList.add('outdated-warning-overlay'); + const closer = document.createElement('button'); + closer.classList.add('outdated-warning-closer', 'delete'); + closer.addEventListener('click', function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + '/../' + window.DOCUMENTER_STABLE; + div.innerHTML = 'This documentation is not for the latest stable release, but for either the development version or an older release.
    Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', maybeAddWarning); +} else { + maybeAddWarning(); +}; diff --git a/previews/PR2003/development/debugging/index.html b/previews/PR2003/development/debugging/index.html new file mode 100644 index 0000000000..5b7dc5565b --- /dev/null +++ b/previews/PR2003/development/debugging/index.html @@ -0,0 +1,42 @@ + +Debugging · CUDA.jl

    Debugging

    Even if your kernel executes, it may be computing the wrong values, or even error at run time. To debug these issues, both CUDA.jl and the CUDA toolkit provide several utilities. These are generally low-level, since we generally cannot use the full extend of the Julia programming language and its tools within GPU kernels.

    Adding output statements

    The easiest, and often reasonably effective way to debug GPU code is to visualize intermediary computations using output functions. CUDA.jl provides several macros that facilitate this style of debugging:

    • @cushow (like @show): to visualize an expression, its result, and return that value. This makes it easy to wrap expressions without disturbing their execution.
    • @cuprintln (like println): to print text and values. This macro does support string interpolation, but the types it can print are restricted to C primitives.

    The @cuaassert macro (like @assert) can also be useful to find issues and abort execution.

    Stack trace information

    If you run into run-time exceptions, stack trace information will by default be very limited. For example, given the following out-of-bounds access:

    julia> function kernel(a)
    +         a[threadIdx().x] = 0
    +         return
    +       end
    +kernel (generic function with 1 method)
    +
    +julia> @cuda threads=2 kernel(CuArray([1]))

    If we execute this code, we'll get a very short error message:

    ERROR: a exception was thrown during kernel execution.
    +Run Julia on debug level 2 for device stack traces.

    As the message suggests, we can have CUDA.jl emit more rich stack trace information by setting Julia's debug level to 2 or higher by passing -g2 to the julia invocation:

    ERROR: a exception was thrown during kernel execution.
    +Stacktrace:
    + [1] throw_boundserror at abstractarray.jl:541
    + [2] checkbounds at abstractarray.jl:506
    + [3] arrayset at /home/tim/Julia/pkg/CUDA/src/device/array.jl:84
    + [4] setindex! at /home/tim/Julia/pkg/CUDA/src/device/array.jl:101
    + [5] kernel at REPL[4]:2

    Note that these messages are embedded in the module (CUDA does not support stack unwinding), and thus bloat its size. To avoid any overhead, you can disable these messages by setting the debug level to 0 (passing -g0 to julia). This disabled any device-side message, but retains the host-side detection:

    julia> @cuda threads=2 kernel(CuArray([1]))
    +# no device-side error message!
    +
    +julia> synchronize()
    +ERROR: KernelException: exception thrown during kernel execution

    Debug info and line-number information

    Setting the debug level does not only enrich stack traces, it also changes the debug info emitted in the CUDA module. On debug level 1, which is the default setting if unspecified, CUDA.jl emits line number information corresponding to nvcc -lineinfo. This information does not hurt performance, and is used by a variety of tools to improve the debugging experience.

    To emit actual debug info as nvcc -G does, you need to start Julia on debug level 2 by passing the flag -g2. Support for emitting PTX-compatible debug info is a recent addition to the NVPTX LLVM back-end, so it's possible this information is incorrect or otherwise affects compilation.

    Warning

    Due to bugs in ptxas, you need CUDA 11.5 or higher for debug info support.

    To disable all debug info emission, start Julia with the flag -g0.

    compute-sanitizer

    To debug kernel issues like memory errors or race conditions, you can use CUDA's compute-sanitizer tool. Refer to the manual for more information.

    To facilitate using the compute sanitizer, CUDA.jl ships the tool as part of its artifacts. You can get the path to the tool using the following function:

    julia> using CUDA
    +
    +julia> CUDA.compute_sanitizer()
    +".julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer"
    +
    +# including recommended options for use with Julia and CUDA.jl
    +julia> CUDA.compute_sanitizer_cmd()
    +`.julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer --tool memcheck --launch-timeout=0 --target-processes=all --report-api-errors=no`

    To quickly spawn a new Julia session under compute-sanitizer, another helper function is provided:

    julia> CUDA.run_compute_sanitizer()
    +Re-starting your active Julia session...
    +
    +========= COMPUTE-SANITIZER
    +julia> using CUDA
    +
    +julia> CuArray([1]) .+ 1
    +1-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
    + 2
    +
    +julia> exit()
    +========= ERROR SUMMARY: 0 errors
    +Process(`.julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer --tool memcheck --launch-timeout=0 --target-processes=all --report-api-errors=no julia -g1`, ProcessExited(0))

    cuda-gdb

    To debug Julia code, you can use the CUDA debugger cuda-gdb. When using this tool, it is recommended to enable Julia debug mode 2 so that debug information is emitted. Do note that the DWARF info emitted by Julia is currently insufficient to e.g. inspect variables, so the debug experience will not be pleasant.

    If you encounter the CUDBG_ERROR_UNINITIALIZED error, ensure all your devices are supported by cuda-gdb (e.g., Kepler-era devices aren't). If some aren't, re-start Julia with CUDA_VISIBLE_DEVICES set to ignore that device.

    diff --git a/previews/PR2003/development/nsight_compute-api.png b/previews/PR2003/development/nsight_compute-api.png new file mode 100644 index 0000000000..d25d3d89ea Binary files /dev/null and b/previews/PR2003/development/nsight_compute-api.png differ diff --git a/previews/PR2003/development/nsight_compute-attach.png b/previews/PR2003/development/nsight_compute-attach.png new file mode 100644 index 0000000000..4a699a9c13 Binary files /dev/null and b/previews/PR2003/development/nsight_compute-attach.png differ diff --git a/previews/PR2003/development/nsight_compute-kernel.png b/previews/PR2003/development/nsight_compute-kernel.png new file mode 100644 index 0000000000..e1a9bbd403 Binary files /dev/null and b/previews/PR2003/development/nsight_compute-kernel.png differ diff --git a/previews/PR2003/development/nsight_compute-resume.png b/previews/PR2003/development/nsight_compute-resume.png new file mode 100644 index 0000000000..fe01701322 Binary files /dev/null and b/previews/PR2003/development/nsight_compute-resume.png differ diff --git a/previews/PR2003/development/nsight_systems.png b/previews/PR2003/development/nsight_systems.png new file mode 100644 index 0000000000..bcf0a1cb91 Binary files /dev/null and b/previews/PR2003/development/nsight_systems.png differ diff --git a/previews/PR2003/development/nvvp.png b/previews/PR2003/development/nvvp.png new file mode 100644 index 0000000000..1b818e4f5a Binary files /dev/null and b/previews/PR2003/development/nvvp.png differ diff --git a/previews/PR2003/development/profiling/index.html b/previews/PR2003/development/profiling/index.html new file mode 100644 index 0000000000..f792406945 --- /dev/null +++ b/previews/PR2003/development/profiling/index.html @@ -0,0 +1,81 @@ + +Profiling · CUDA.jl

    Profiling

    Profiling GPU code is harder than profiling Julia code executing on the CPU. For one, kernels typically execute asynchronously, and thus require appropriate synchronization when measuring their execution time. Furthermore, because the code executes on a different processor, it is much harder to know what is currently executing. CUDA, and the Julia CUDA packages, provide several tools and APIs to remedy this.

    Time measurements

    To accurately measure execution time in the presence of asynchronously-executing kernels, CUDA.jl provides an @elapsed macro that, much like Base.@elapsed, measures the total execution time of a block of code on the GPU:

    julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> Base.@elapsed sin.(a)  # WRONG!
    +0.008714211
    +
    +julia> CUDA.@elapsed sin.(a)
    +0.051607586f0

    This is a low-level utility, and measures time by submitting events to the GPU and measuring the time between them. As such, if the GPU was not idle in the first place, you may not get the expected result. The macro is mainly useful if your application needs to know about the time it took to complete certain GPU operations.

    For more convenient time reporting, you can use the CUDA.@time macro which mimics Base.@time by printing execution times as well as memory allocation stats, while making sure the GPU is idle before starting the measurement, as well as waiting for all asynchronous operations to complete:

    julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> CUDA.@time sin.(a);
    +  0.046063 seconds (96 CPU allocations: 3.750 KiB) (1 GPU allocation: 4.000 GiB, 14.33% gc time of which 99.89% spent allocating)

    The @time macro is more user-friendly and is a generally more useful tool when measuring the end-to-end performance characteristics of a GPU application.

    For robust measurements however, it is advised to use the BenchmarkTools.jl package which goes to great lengths to perform accurate measurements. Due to the asynchronous nature of GPUs, you need to ensure the GPU is synchronized at the end of every sample, e.g. by calling synchronize() or, even better, wrapping your code in CUDA.@sync:

    julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> @benchmark CUDA.@sync sin.($a)
    +BenchmarkTools.Trial:
    +  memory estimate:  3.73 KiB
    +  allocs estimate:  95
    +  --------------
    +  minimum time:     46.341 ms (0.00% GC)
    +  median time:      133.302 ms (0.50% GC)
    +  mean time:        130.087 ms (0.49% GC)
    +  maximum time:     153.465 ms (0.43% GC)
    +  --------------
    +  samples:          39
    +  evals/sample:     1

    Note that the allocations as reported by BenchmarkTools are CPU allocations. For the GPU allocation behavior you need to consult CUDA.@time.

    Application profiling

    For profiling large applications, simple timings are insufficient. Instead, we want a overview of how and when the GPU was active, to avoid times where the device was idle and/or find which kernels needs optimization.

    As we cannot use the Julia profiler for this task, we will be using external profiling software as part of the CUDA toolkit. To inform those external tools which code needs to be profiled (e.g., to exclude warm-up iterations or other noninteresting elements) you can use the CUDA.@profile macro to surround interesting code with. Again, this macro mimics an equivalent from the standard library, but this time requires external software to actually perform the profiling:

    julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> sin.(a);  # warmup
    +
    +julia> CUDA.@profile sin.(a);
    +┌ Warning: Calling CUDA.@profile only informs an external profiler to start.
    +│ The user is responsible for launching Julia under a CUDA profiler like `nvprof`.
    +└ @ CUDA.Profile ~/Julia/pkg/CUDA/src/profile.jl:42

    nvprof and nvvp

    Warning

    These tools are deprecated, and will be removed from future versions of CUDA. Prefer to use the Nsight tools described below.

    For simple profiling, prefix your Julia command-line invocation with the nvprof utility. For a better timeline, be sure to use CUDA.@profile to delimit interesting code and start nvprof with the option --profile-from-start off:

    $ nvprof --profile-from-start off julia
    +
    +julia> using CUDA
    +
    +julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> sin.(a);
    +
    +julia> CUDA.@profile sin.(a);
    +
    +julia> exit()
    +==156406== Profiling application: julia
    +==156406== Profiling result:
    +            Type  Time(%)      Time     Calls       Avg       Min       Max  Name
    + GPU activities:  100.00%  44.777ms         1  44.777ms  44.777ms  44.777ms  ptxcall_broadcast_1
    +      API calls:   56.46%  6.6544ms         1  6.6544ms  6.6544ms  6.6544ms  cuMemAlloc
    +                   43.52%  5.1286ms         1  5.1286ms  5.1286ms  5.1286ms  cuLaunchKernel
    +                    0.01%  1.3200us         1  1.3200us  1.3200us  1.3200us  cuDeviceGetCount
    +                    0.01%     725ns         3     241ns     196ns     301ns  cuCtxGetCurrent
    Info

    If nvprof crashes, reporting that the application returned non-zero code 12, try starting nvprof with --openacc-profiling off.

    For a visual overview of these results, you can use the NVIDIA Visual Profiler (nvvp):

    "NVIDIA Visual Profiler"

    Note however that both nvprof and nvvp are deprecated, and will be removed from future versions of the CUDA toolkit.

    NVIDIA Nsight Systems

    Following the deprecation of above tools, NVIDIA published the Nsight Systems and Nsight Compute tools for respectively timeline profiling and more detailed kernel analysis. The former is well-integrated with the Julia GPU packages, and makes it possible to iteratively profile without having to restart Julia as was the case with nvvp and nvprof.

    After downloading and installing NSight Systems (a version might have been installed alongside with the CUDA toolkit, but it is recommended to download and install the latest version from the NVIDIA website), you need to launch Julia from the command-line, wrapped by the nsys utility from NSight Systems:

    $ nsys launch julia

    You can then execute whatever code you want in the REPL, including e.g. loading Revise so that you can modify your application as you go. When you call into code that is wrapped by CUDA.@profile, the profiler will become active and generate a profile output file in the current folder:

    julia> using CUDA
    +
    +julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> sin.(a);
    +
    +julia> CUDA.@profile sin.(a);
    +start executed
    +Processing events...
    +Capturing symbol files...
    +Saving intermediate "report.qdstrm" file to disk...
    +
    +Importing [===============================================================100%]
    +Saved report file to "report.qdrep"
    +stop executed
    Note

    Even with a warm-up iteration, the first kernel or API call might seem to take significantly longer in the profiler. If you are analyzing short executions, instead of whole applications, repeat the operation twice (optionally separated by a call to synchronize() or wrapping in CUDA.@sync)

    You can open the resulting .qdrep file with nsight-sys:

    "NVIDIA Nsight Systems"

    Info

    If NSight Systems does not capture any kernel launch, even though you have used CUDA.@profile, try starting nsys with --trace cuda.

    NVIDIA Nsight Compute

    If you want details on the execution properties of a kernel, or inspect API interactions, Nsight Compute is the tool for you. It is again possible to use this profiler with an interactive session of Julia, and debug or profile only those sections of your application that are marked with CUDA.@profile.

    Start with launching Julia under the Nsight Compute CLI tool:

    $ ncu --mode=launch julia

    You will get an interactive REPL, where you can execute whatever code you want:

    julia> using CUDA
    +
    +julia> CUDA.driver_version()
    +
    +# Julia hangs!

    As soon as you use CUDA.jl, your Julia process will hang. This is expected, as the tool breaks upon the very first call to the CUDA API, at which point you are expected to launch the Nsight Compute GUI utility and attach to the running session:

    "NVIDIA Nsight Compute - Attaching to a session"

    You will see that the tool has stopped execution on the call to cuInit. Now check Profile > Auto Profile to make Nsight Compute gather statistics on our kernels, and clock Debug > Resume to resume your session.

    Now our CLI session comes to life again, and we can enter the rest of our script:

    julia> a = CUDA.rand(1024,1024,1024);
    +
    +julia> sin.(a);
    +
    +julia> CUDA.@profile sin.(a);

    Once that's finished, the Nsight Compute GUI window will have plenty details on our kernel:

    "NVIDIA Nsight Compute - Kernel profiling"

    At any point in time, you can also pause your application from the debug menu, and inspect the API calls that have been made:

    "NVIDIA Nsight Compute - API inspection"

    Source-code annotations

    If you want to put additional information in the profile, e.g. phases of your application, or expensive CPU operations, you can use the NVTX library via the NVTX.jl package:

    using CUDA, NVTX
    +
    +NVTX.@range "doing X" begin
    +    ...
    +end
    +
    +NVTX.@mark "reached Y"

    Compiler options

    Some tools, like nvvp and NSight Systems Compute, also make it possible to do source-level profiling. CUDA.jl will by default emit the necessary source line information, which you can disable by launching Julia with -g0. Conversely, launching with -g2 will emit additional debug information, which can be useful in combination with tools like cuda-gdb, but might hurt performance or code size.

    Warning

    Due to bugs in LLVM and CUDA, debug info emission is unavailable in Julia 1.4 and higher.

    diff --git a/previews/PR2003/development/troubleshooting/index.html b/previews/PR2003/development/troubleshooting/index.html new file mode 100644 index 0000000000..496f5d6aa5 --- /dev/null +++ b/previews/PR2003/development/troubleshooting/index.html @@ -0,0 +1,48 @@ + +Troubleshooting · CUDA.jl

    Troubleshooting

    This section deals with common errors you might run into while writing GPU code, preventing the code to compile.

    InvalidIRError: compiling ... resulted in invalid LLVM IR

    Not all of Julia is supported by CUDA.jl. Several commonly-used features, like strings or exceptions, will not compile to GPU code, because of their interactions with the CPU-only runtime library.

    For example, say we define and try to execute the following kernel:

    julia> function kernel(a)
    +         @inbounds a[threadId().x] = 0
    +         return
    +       end
    +
    +julia> @cuda kernel(CuArray([1]))
    +ERROR: InvalidIRError: compiling kernel kernel(CuDeviceArray{Int64,1,1}) resulted in invalid LLVM IR
    +Reason: unsupported dynamic function invocation (call to setindex!)
    +Stacktrace:
    + [1] kernel at REPL[2]:2
    +Reason: unsupported dynamic function invocation (call to getproperty)
    +Stacktrace:
    + [1] kernel at REPL[2]:2
    +Reason: unsupported use of an undefined name (use of 'threadId')
    +Stacktrace:
    + [1] kernel at REPL[2]:2

    CUDA.jl does its best to decode the unsupported IR and figure out where it came from. In this case, there's two so-called dynamic invocations, which happen when a function call cannot be statically resolved (often because the compiler could not fully infer the call, e.g., due to inaccurate or instable type information). These are a red herring, and the real cause is listed last: a typo in the use of the threadIdx function! If we fix this, the IR error disappears and our kernel successfully compiles and executes.

    KernelError: kernel returns a value of type Union{}

    Where the previous section clearly pointed to the source of invalid IR, in other cases your function will return an error. This is encoded by the Julia compiler as a return value of type Union{}:

    julia> function kernel(a)
    +         @inbounds a[threadId().x] = CUDA.sin(a[threadIdx().x])
    +         return
    +       end
    +
    +julia> @cuda kernel(CuArray([1]))
    +ERROR: GPU compilation of kernel kernel(CuDeviceArray{Int64,1,1}) failed
    +KernelError: kernel returns a value of type `Union{}`

    Now we don't know where this error came from, and we will have to take a look ourselves at the generated code. This is easily done using the @device_code introspection macros, which mimic their Base counterparts (e.g. @device_code_llvm instead of @code_llvm, etc).

    To debug an error returned by a kernel, we should use @device_code_warntype to inspect the Julia IR. Furthermore, this macro has an interactive mode, which further facilitates inspecting this IR using Cthulhu.jl. First, install and import this package, and then try to execute the kernel again prefixed by @device_code_warntype interactive=true:

    julia> using Cthulhu
    +
    +julia> @device_code_warntype interactive=true @cuda kernel(CuArray([1]))
    +Variables
    +  #self#::Core.Compiler.Const(kernel, false)
    +  a::CuDeviceArray{Int64,1,1}
    +  val::Union{}
    +
    +Body::Union{}
    +1 ─ %1  = CUDA.sin::Core.Compiler.Const(CUDA.sin, false)
    +│   ...
    +│   %14 = (...)::Int64
    +└──       goto #2
    +2 ─       (%1)(%14)
    +└──       $(Expr(:unreachable))
    +
    +Select a call to descend into or ↩ to ascend.
    + • %17  = call CUDA.sin(::Int64)::Union{}

    Both from the IR and the list of calls Cthulhu offers to inspect further, we can see that the call to CUDA.sin(::Int64) results in an error: in the IR it is immediately followed by an unreachable, while in the list of calls it is inferred to return Union{}. Now we know where to look, it's easy to figure out what's wrong:

    help?> CUDA.sin
    +  # 2 methods for generic function "sin":
    +  [1] sin(x::Float32) in CUDA at /home/tim/Julia/pkg/CUDA/src/device/intrinsics/math.jl:13
    +  [2] sin(x::Float64) in CUDA at /home/tim/Julia/pkg/CUDA/src/device/intrinsics/math.jl:12

    There's no method of CUDA.sin that accepts an Int64, and thus the function was determined to unconditionally throw a method error. For now, we disallow these situations and refuse to compile, but in the spirit of dynamic languages we might change this behavior to just throw an error at run time.

    diff --git a/previews/PR2003/faq/index.html b/previews/PR2003/faq/index.html new file mode 100644 index 0000000000..4e564fba5d --- /dev/null +++ b/previews/PR2003/faq/index.html @@ -0,0 +1,23 @@ + +FAQ · CUDA.jl

    Frequently Asked Questions

    This page is a compilation of frequently asked questions and answers.

    An old version of CUDA.jl keeps getting installed!

    Sometimes it happens that a breaking version of CUDA.jl or one of its dependencies is released. If any package you use isn't yet compatible with this release, this will block automatic upgrade of CUDA.jl. For example, with Flux.jl v0.11.1 we get CUDA.jl v1.3.3 despite there being a v2.x release:

    pkg> add Flux
    +  [587475ba] + Flux v0.11.1
    +pkg> add CUDA
    +  [052768ef] + CUDA v1.3.3

    To examine which package is holding back CUDA.jl, you can "force" an upgrade by specifically requesting a newer version. The resolver will then complain, and explain why this upgrade isn't possible:

    pkg> add CUDA.jl@2
    +  Resolving package versions...
    +ERROR: Unsatisfiable requirements detected for package Adapt [79e6a3ab]:
    + Adapt [79e6a3ab] log:
    + ├─possible versions are: [0.3.0-0.3.1, 0.4.0-0.4.2, 1.0.0-1.0.1, 1.1.0, 2.0.0-2.0.2, 2.1.0, 2.2.0, 2.3.0] or uninstalled
    + ├─restricted by compatibility requirements with CUDA [052768ef] to versions: [2.2.0, 2.3.0]
    + │ └─CUDA [052768ef] log:
    + │   ├─possible versions are: [0.1.0, 1.0.0-1.0.2, 1.1.0, 1.2.0-1.2.1, 1.3.0-1.3.3, 2.0.0-2.0.2] or uninstalled
    + │   └─restricted to versions 2 by an explicit requirement, leaving only versions 2.0.0-2.0.2
    + └─restricted by compatibility requirements with Flux [587475ba] to versions: [0.3.0-0.3.1, 0.4.0-0.4.2, 1.0.0-1.0.1, 1.1.0] — no versions left
    +   └─Flux [587475ba] log:
    +     ├─possible versions are: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4, 0.11.0-0.11.1] or uninstalled
    +     ├─restricted to versions * by an explicit requirement, leaving only versions [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4, 0.11.0-0.11.1]
    +     └─restricted by compatibility requirements with CUDA [052768ef] to versions: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4] or uninstalled, leaving only versions: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4]
    +       └─CUDA [052768ef] log: see above

    A common source of these incompatibilities is having both CUDA.jl and the older CUDAnative.jl/CuArrays.jl/CUDAdrv.jl stack installed: These are incompatible, and cannot coexist. You can inspect in the Pkg REPL which exact packages you have installed using the status --manifest option.

    Can you wrap this or that CUDA API?

    If a certain API isn't wrapped with some high-level functionality, you can always use the underlying C APIs which are always available as unexported methods. For example, you can access the CUDA driver library as cu prefixed, unexported functions like CUDA.cuDriverGetVersion. Similarly, vendor libraries like CUBLAS are available through their exported submodule handles, e.g., CUBLAS.cublasGetVersion_v2.

    Any help on designing or implementing high-level wrappers for this low-level functionality is greatly appreciated, so please consider contributing your uses of these APIs on the respective repositories.

    diff --git a/previews/PR2003/index.html b/previews/PR2003/index.html new file mode 100644 index 0000000000..6fbf4af39e --- /dev/null +++ b/previews/PR2003/index.html @@ -0,0 +1,16 @@ + +Home · CUDA.jl

    CUDA programming in Julia

    The CUDA.jl package is the main entrypoint for programming NVIDIA GPUs in Julia. The package makes it possible to do so at various abstraction levels, from easy-to-use arrays down to hand-written kernels using low-level CUDA APIs.

    If you have any questions, please feel free to use the #gpu channel on the Julia slack, or the GPU domain of the Julia Discourse.

    For information on recent or upcoming changes, consult the NEWS.md document in the CUDA.jl repository.

    Quick Start

    The Julia CUDA stack only requires a working NVIDIA driver; you don't need to install the entire CUDA toolkit, as it will automatically be downloaded when you first use the package:

    # install the package
    +using Pkg
    +Pkg.add("CUDA")
    +
    +# smoke test (this will download the CUDA toolkit)
    +using CUDA
    +CUDA.versioninfo()

    If you want to ensure everything works as expected, you can execute the test suite. Note that this test suite is fairly exhaustive, taking around an hour to complete when using a single thread (multiple processes are used automatically based on the number of threads Julia is started with), and requiring significant amounts of CPU and GPU memory.

    using Pkg
    +Pkg.test("CUDA")
    +
    +# the test suite takes command-line options that allow customization; pass --help for details:
    +#Pkg.test("CUDA"; test_args=`--help`)

    For more details on the installation process, consult the Installation section. To understand the toolchain in more detail, have a look at the tutorials in this manual. It is highly recommended that new users start with the Introduction tutorial. For an overview of the available functionality, read the Usage section. The following resources may also be of interest:

    • Effectively using GPUs with Julia: video, slides
    • How Julia is compiled to GPUs: video

    Acknowledgements

    The Julia CUDA stack has been a collaborative effort by many individuals. Significant contributions have been made by the following individuals:

    • Tim Besard (@maleadt) (lead developer)
    • Valentin Churavy (@vchuravy)
    • Mike Innes (@MikeInnes)
    • Katharine Hyatt (@kshyatt)
    • Simon Danisch (@SimonDanisch)

    Supporting and Citing

    Much of the software in this ecosystem was developed as part of academic research. If you would like to help support it, please star the repository as such metrics may help us secure funding in the future. If you use our software as part of your research, teaching, or other activities, we would be grateful if you could cite our work. The CITATION.bib file in the root of this repository lists the relevant papers.

    diff --git a/previews/PR2003/installation/conditional/index.html b/previews/PR2003/installation/conditional/index.html new file mode 100644 index 0000000000..163aefcda7 --- /dev/null +++ b/previews/PR2003/installation/conditional/index.html @@ -0,0 +1,36 @@ + +Conditional use · CUDA.jl

    Conditional use

    CUDA.jl is special in that developers may want to depend on the GPU toolchain even though users might not have a GPU. In this section, we describe two different usage scenarios and how to implement them. Key to remember is that CUDA.jl will always load, which means you need to manually check if the package is functional.

    Because CUDA.jl always loads, even if the user doesn't have a GPU or CUDA, you should just depend on it like any other package (and not use, e.g., Requires.jl). This ensures that breaking changes to the GPU stack will be taken into account by the package resolver when installing your package.

    If you unconditionally use the functionality from CUDA.jl, you will get a run-time error in the case the package failed to initialize. For example, on a system without CUDA:

    julia> using CUDA
    +julia> CUDA.driver_version()
    +ERROR: UndefVarError: libcuda not defined

    To avoid this, you should call CUDA.functional() to inspect whether the package is functional and condition your use of GPU functionality on that. Let's illustrate with two scenarios, one where having a GPU is required, and one where it's optional.

    Scenario 1: GPU is required

    If your application requires a GPU, and its functionality is not designed to work without CUDA, you should just import the necessary packages and inspect if they are functional:

    using CUDA
    +@assert CUDA.functional(true)

    Passing true as an argument makes CUDA.jl display why initialization might have failed.

    If you are developing a package, you should take care only to perform this check at run time. This ensures that your module can always be precompiled, even on a system without a GPU:

    module MyApplication
    +
    +using CUDA
    +
    +__init__() = @assert CUDA.functional(true)
    +
    +end

    This of course also implies that you should avoid any calls to the GPU stack from global scope, since the package might not be functional.

    Scenario 2: GPU is optional

    If your application does not require a GPU, and can work without the CUDA packages, there is a tradeoff. As an example, let's define a function that uploads an array to the GPU if available:

    module MyApplication
    +
    +using CUDA
    +
    +if CUDA.functional()
    +    to_gpu_or_not_to_gpu(x::AbstractArray) = CuArray(x)
    +else
    +    to_gpu_or_not_to_gpu(x::AbstractArray) = x
    +end
    +
    +end

    This works, but cannot be simply adapted to a scenario with precompilation on a system without CUDA. One option is to evaluate code at run time:

    function __init__()
    +    if CUDA.functional()
    +        @eval to_gpu_or_not_to_gpu(x::AbstractArray) = CuArray(x)
    +    else
    +        @eval to_gpu_or_not_to_gpu(x::AbstractArray) = x
    +    end
    +end

    However, this causes compilation at run-time, and might negate much of the advantages that precompilation has to offer. Instead, you can use a global flag:

    const use_gpu = Ref(false)
    +to_gpu_or_not_to_gpu(x::AbstractArray) = use_gpu[] ? CuArray(x) : x
    +
    +function __init__()
    +    use_gpu[] = CUDA.functional()
    +end

    The disadvantage of this approach is the introduction of a type instability.

    diff --git a/previews/PR2003/installation/overview/index.html b/previews/PR2003/installation/overview/index.html new file mode 100644 index 0000000000..a6d904911e --- /dev/null +++ b/previews/PR2003/installation/overview/index.html @@ -0,0 +1,48 @@ + +Overview · CUDA.jl

    Overview

    The Julia CUDA stack requires users to have a functional NVIDIA driver and corresponding CUDA toolkit. The former should be installed by you or your system administrator, while the latter can be automatically downloaded by Julia using the artifact subsystem.

    Package installation

    For most users, installing the latest tagged version of CUDA.jl will be sufficient. You can easily do that using the package manager:

    pkg> add CUDA

    Or, equivalently, via the Pkg API:

    julia> import Pkg; Pkg.add("CUDA")

    In some cases, you might need to use the master version of this package, e.g., because it includes a specific fix you need. Often, however, the development version of this package itself relies on unreleased versions of other packages. This information is recorded in the manifest at the root of the repository, which you can use by starting Julia from the CUDA.jl directory with the --project flag:

    $ cd .julia/dev/CUDA.jl     # or wherever you have CUDA.jl checked out
    +$ julia --project
    +pkg> instantiate            # to install correct dependencies
    +julia> using CUDA

    In the case you want to use the development version of CUDA.jl with other packages, you cannot use the manifest and you need to manually install those dependencies from the master branch. Again, the exact requirements are recorded in CUDA.jl's manifest, but often the following instructions will work:

    pkg> add GPUCompiler#master
    +pkg> add GPUArrays#master
    +pkg> add LLVM#master

    Platform support

    We support the same operation systems that NVIDIA supports: Linux, and Windows. Similarly, we support x86, ARM, PPC, ... as long as Julia is supported on it and there exists an NVIDIA driver and CUDA toolkit for your platform. The main development platform (and the only CI system) however is x86_64 on Linux, so if you are using a more exotic combination there might be bugs.

    NVIDIA driver

    To use the Julia GPU stack, you need to install the NVIDIA driver for your system and GPU. You can find detailed instructions on the NVIDIA home page.

    If you're using Linux you should always consider installing the driver through the package manager of your distribution. In the case that driver is out of date or does not support your GPU, and you need to download a driver from the NVIDIA home page, similarly prefer a distribution-specific package (e.g., deb, rpm) instead of the generic runfile option.

    If you are using a shared system, ask your system administrator on how to install or load the NVIDIA driver. Generally, you should be able to find and use the CUDA driver library, called libcuda.so on Linux, libcuda.dylib on macOS and nvcuda64.dll on Windows. You should also be able to execute the nvidia-smi command, which lists all available GPUs you have access to.

    On some enterprise systems, CUDA.jl will be able to upgrade the driver for the duration of the session (using CUDA's Forward Compatibility mechanism). This will be mentioned in the CUDA.versioninfo() output, so be sure to verify that before asking your system administrator to upgrade:

    julia> CUDA.versioninfo()
    +CUDA runtime 10.2
    +CUDA driver 11.8
    +NVIDIA driver 520.56.6, originally for CUDA 11.7

    Finally, to be able to use all of the Julia GPU stack you need to have permission to profile GPU code. On Linux, that means loading the nvidia kernel module with the NVreg_RestrictProfilingToAdminUsers=0 option configured (e.g., in /etc/modprobe.d). Refer to the following document for more information.

    CUDA toolkit

    The recommended way to use CUDA.jl is to let it automatically download an appropriate CUDA toolkit. CUDA.jl will check your driver's capabilities, which versions of CUDA are available for your platform, and automatically download an appropriate artifact containing all the libraries that CUDA.jl supports.

    If you really need to use a different CUDA toolkit, it's possible (but not recommended) to load a different version of the CUDA runtime, or even an installation from your local system. Both are configured by setting the version preference (using Preferences.jl) on the CUDARuntimejll.jl package, but there is also a user-friendly API available in CUDA.jl.

    Specifying the CUDA version

    You can choose which version to (try to) download and use by calling CUDA.set_runtime_version!:

    julia> using CUDA
    +
    +julia> CUDA.set_runtime_version!(v"11.8")
    +┌ Warning: CUDA Runtime version set to 11.8, please re-start Julia for this to take effect.
    +└ @ CUDA /usr/local/share/julia/packages/CUDA/irdEw/lib/cudadrv/version.jl:54

    This generates the following LocalPreferences.toml file in your active environment:

    [CUDA_Runtime_jll]
    +version = "11.8"

    This preference is compatible with other CUDA JLLs, e.g., if you load CUDNN_jll it will only select artifacts that are compatible with the configured CUDA runtime.

    Using a local CUDA

    To use a local installation, you can invoke the same API but set the version to "local":

    julia> using CUDA
    +
    +julia> CUDA.versioninfo()
    +CUDA runtime 11.8, artifact installation
    +...
    +
    +julia> CUDA.set_runtime_version!("local")
    +┌ Warning: CUDA Runtime version set to local, please re-start Julia for this to take effect.
    +└ @ CUDA ~/Julia/pkg/CUDA/lib/cudadrv/version.jl:73

    After re-launching Julia:

    julia> using CUDA
    +
    +julia> CUDA.versioninfo()
    +CUDA runtime 11.8, local installation
    +...

    Calling the above helper function generates the following LocalPreferences.toml file in your active environment:

    [CUDA_Runtime_jll]
    +version = "local"

    This preference not only configures CUDA.jl to use a local toolkit, it also prevents downloading any artifact, so it may be interesting to set this preference before ever importing CUDA.jl (e.g., by putting this preference file in a system-wide depot).

    If CUDA.jl doesn't properly detect your local toolkit, it may be that certain libraries or binaries aren't on a globally-discoverable path. For more information, run Julia with the JULIA_DEBUG environment variable set to CUDA_Runtime_Discovery.

    Note that setting the version to "local" disables use of any CUDA-related JLL, not just of CUDA_Runtime_jll. This is out of necessity: JLLs are baked in the precompilation image at compile time, while local toolkit discovery happens at run time; this inconsistency makes it impossible to select a compatible artifact for the JLLs. If you care about other JLLs, use CUDA from artifacts.

    Containers

    CUDA.jl is container friendly: You can install, precompile, and even import the package on a system without a GPU:

    $ docker run --rm -it julia   # note how we're *not* using `--gpus=all` here,
    +                              # so we won't have access to a GPU (or its driver)
    +
    +pkg> add CUDA
    +
    +pkg> precompile
    +Precompiling project...
    +[ Info: Precompiling CUDA [052768ef-5323-5732-b1bb-66c8b64840ba]

    The above is common when building a container (docker build does not take a --gpus argument). It does prevent CUDA.jl from downloading the toolkit artifacts that will be required at run time, because it cannot query the driver for the CUDA compatibility level.

    To avoid having to download the CUDA toolkit artifacts each time you restart your container, it's possible to inform CUDA.jl which toolkit to use. This can be done by calling CUDA.set_runtime_version! when building the container, after which a subsequent import of CUDA.jl will download the necessary artifacts.

    At run time you obviously do need a CUDA-compatible GPU as well as the CUDA driver library to interface with it. Typically, that library is imported from the host system, e.g., by launching docker using the --gpus=all flag:

    $ docker run --rm -it --gpus=all julia
    +
    +julia> using CUDA
    +
    +julia> CUDA.versioninfo()
    +CUDA runtime 11.8
    +CUDA driver 11.8
    +NVIDIA driver 520.56.6
    +
    +...

    All of the above is demonstrated in the Dockerfile that's part of the CUDA.jl repository.

    diff --git a/previews/PR2003/installation/troubleshooting/index.html b/previews/PR2003/installation/troubleshooting/index.html new file mode 100644 index 0000000000..0e7d76f3a9 --- /dev/null +++ b/previews/PR2003/installation/troubleshooting/index.html @@ -0,0 +1,6 @@ + +Troubleshooting · CUDA.jl

    Troubleshooting

    UndefVarError: libcuda not defined

    This means that CUDA.jl could not find a suitable CUDA driver. For more information, re-run with the JULIA_DEBUG environment variable set to CUDA_Driver_jll.

    UNKNOWN_ERROR(999)

    If you encounter this error, there are several known issues that may be causing it:

    • a mismatch between the CUDA driver and driver library: on Linux, look for clues in dmesg
    • the CUDA driver is in a bad state: this can happen after resume. Try rebooting.

    Generally though, it's impossible to say what's the reason for the error, but Julia is likely not to blame. Make sure your set-up works (e.g., try executing nvidia-smi, a CUDA C binary, etc), and if everything looks good file an issue.

    NVML library not found (on Windows)

    Check and make sure the NVSMI folder is in your PATH. By default it may not be. Look in C:\Program Files\NVIDIA Corporation for the NVSMI folder - you should see nvml.dll within it. You can add this folder to your PATH and check that nvidia-smi runs properly.

    The specified module could not be found (on Windows)

    Ensure the Visual C++ Redistributable is installed.

    diff --git a/previews/PR2003/lib/driver/index.html b/previews/PR2003/lib/driver/index.html new file mode 100644 index 0000000000..e6758c54c8 --- /dev/null +++ b/previews/PR2003/lib/driver/index.html @@ -0,0 +1,41 @@ + +CUDA driver · CUDA.jl

    CUDA driver

    This section lists the package's public functionality that directly corresponds to functionality of the CUDA driver API. In general, the abstractions stay close to those of the CUDA driver API, so for more information on certain library calls you can consult the CUDA driver API reference.

    The documentation is grouped according to the modules of the driver API.

    Error Handling

    CUDA.CuErrorType
    CuError(code)
    +CuError(code, meta)

    Create a CUDA error object with error code code. The optional meta parameter indicates whether extra information, such as error logs, is known.

    source
    CUDA.nameMethod
    name(err::CuError)

    Gets the string representation of an error code.

    julia> err = CuError(CUDA.cudaError_enum(1))
    +CuError(CUDA_ERROR_INVALID_VALUE)
    +
    +julia> name(err)
    +"ERROR_INVALID_VALUE"
    source

    Version Management

    CUDA.system_driver_versionMethod
    system_driver_version()

    Returns the latest version of CUDA supported by the original system driver, or nothing if the driver was not upgraded.

    source
    CUDA.set_runtime_version!Function
    set_runtime_version!([version])

    Sets the CUDA Runtime version preference to version. This can be a version number, in which case such a versioned artifact will be attempted to be used; or "local" for using a runtime from the local system. Invoke this function without an argument to reset the preference, in which case CUDA.jl will use the most recent compatible runtime available.

    source

    Device Management

    CUDA.current_deviceFunction
    current_device()

    Returns the current device.

    Warning

    This is a low-level API, returning the current device as known to the CUDA driver. For most users, it is recommended to use the device method instead.

    source
    CUDA.nameMethod
    name(dev::CuDevice)

    Returns an identifier string for the device.

    source
    CUDA.totalmemMethod
    totalmem(dev::CuDevice)

    Returns the total amount of memory (in bytes) on the device.

    source
    CUDA.attributeFunction
    attribute(dev::CuDevice, code)

    Returns information about the device.

    source
    attribute(X, pool::CuMemoryPool, attr)

    Returns attribute attr about pool. The type of the returned value depends on the attribute, and as such must be passed as the X parameter.

    source
    attribute(X, ptr::Union{Ptr,CuPtr}, attr)

    Returns attribute attr about pointer ptr. The type of the returned value depends on the attribute, and as such must be passed as the X parameter.

    source

    Certain common attributes are exposed by additional convenience functions:

    CUDA.warpsizeMethod
    warpsize(dev::CuDevice)

    Returns the warp size (in threads) of the device.

    source

    Context Management

    CUDA.CuContextType
    CuContext(dev::CuDevice, flags=CTX_SCHED_AUTO)
    +CuContext(f::Function, ...)

    Create a CUDA context for device. A context on the GPU is analogous to a process on the CPU, with its own distinct address space and allocated resources. When a context is destroyed, the system cleans up the resources allocated to it.

    When you are done using the context, call CUDA.unsafe_destroy! to mark it for deletion, or use do-block syntax with this constructor.

    source
    CUDA.unsafe_destroy!Method
    unsafe_destroy!(ctx::CuContext)

    Immediately destroy a context, freeing up all resources associated with it. This does not respect any users of the context, and might make other objects unusable.

    source
    CUDA.current_contextFunction
    current_context()

    Returns the current context.

    Warning

    This is a low-level API, returning the current context as known to the CUDA driver. For most users, it is recommended to use the context method instead.

    source
    CUDA.activateMethod
    activate(ctx::CuContext)

    Binds the specified CUDA context to the calling CPU thread.

    source
    CUDA.synchronizeMethod
    synchronize(ctx::Context)

    Block for the all operations on ctx to complete. This is a heavyweight operation, typically you only need to call synchronize which only synchronizes the stream associated with the current task.

    source
    Missing docstring.

    Missing docstring for device_synchronize. Check Documenter's build log for details.

    Primary Context Management

    CUDA.CuPrimaryContextType
    CuPrimaryContext(dev::CuDevice)

    Create a primary CUDA context for a given device.

    Each primary context is unique per device and is shared with CUDA runtime API. It is meant for interoperability with (applications using) the runtime API.

    source
    CUDA.CuContextMethod
    CuContext(pctx::CuPrimaryContext)

    Retain the primary context on the GPU, returning a context compatible with the driver API. The primary context will be released when the returned driver context is finalized.

    As these contexts are refcounted by CUDA, you should not call CUDA.unsafe_destroy! on them but use CUDA.unsafe_release! instead (available with do-block syntax as well).

    source
    CUDA.isactiveMethod
    isactive(pctx::CuPrimaryContext)

    Query whether a primary context is active.

    source
    CUDA.flagsMethod
    flags(pctx::CuPrimaryContext)

    Query the flags of a primary context.

    source
    CUDA.unsafe_reset!Method
    unsafe_reset!(pctx::CuPrimaryContext)

    Explicitly destroys and cleans up all resources associated with a device's primary context in the current process. Note that this forcibly invalidates all contexts derived from this primary context, and as a result outstanding resources might become invalid.

    source
    CUDA.unsafe_release!Method
    CUDA.unsafe_release!(ctx::CuContext)

    Lower the refcount of a context, possibly freeing up all resources associated with it. This does not respect any users of the context, and might make other objects unusable.

    source

    Module Management

    CUDA.CuModuleType
    CuModule(data, options::Dict{CUjit_option,Any})
    +CuModuleFile(path, options::Dict{CUjit_option,Any})

    Create a CUDA module from a data, or a file containing data. The data may be PTX code, a CUBIN, or a FATBIN.

    The options is an optional dictionary of JIT options and their respective value.

    source

    Function Management

    CUDA.CuFunctionType
    CuFunction(mod::CuModule, name::String)

    Acquires a function handle from a named function in a module.

    source

    Global Variable Management

    CUDA.CuGlobalType
    CuGlobal{T}(mod::CuModule, name::String)

    Acquires a typed global variable handle from a named global in a module.

    source
    Base.eltypeMethod
    eltype(var::CuGlobal)

    Return the element type of a global variable object.

    source
    Base.getindexMethod
    Base.getindex(var::CuGlobal)

    Return the current value of a global variable.

    source
    Base.setindex!Method
    Base.setindex(var::CuGlobal{T}, val::T)

    Set the value of a global variable to val

    source

    Linker

    CUDA.add_data!Function
    add_data!(link::CuLink, name::String, code::String)

    Add PTX code to a pending link operation.

    source
    add_data!(link::CuLink, name::String, data::Vector{UInt8}, type::CUjitInputType)

    Add object code to a pending link operation.

    source
    CUDA.add_file!Function
    add_file!(link::CuLink, path::String, typ::CUjitInputType)

    Add data from a file to a link operation. The argument typ indicates the type of the contained data.

    source
    CUDA.CuLinkImageType

    The result of a linking operation.

    This object keeps its parent linker object alive, as destroying a linker destroys linked images too.

    source
    CUDA.completeFunction
    complete(link::CuLink)

    Complete a pending linker invocation, returning an output image.

    source
    CUDA.CuModuleMethod
    CuModule(img::CuLinkImage, ...)

    Create a CUDA module from a completed linking operation. Options from CuModule apply.

    source

    Memory Management

    Three kinds of memory buffers can be allocated: device memory, host memory, and unified memory. Each of these buffers can be allocated by calling alloc with the type of buffer as first argument, and freed by calling free. Certain buffers have specific methods defined.

    CUDA.Mem.allocMethod
    Mem.alloc(DeviceBuffer, bytesize::Integer;
    +          [async=false], [stream::CuStream], [pool::CuMemoryPool])

    Allocate bytesize bytes of memory on the device. This memory is only accessible on the GPU, and requires explicit calls to unsafe_copyto!, which wraps cuMemcpy, for access on the CPU.

    source
    CUDA.Mem.HostBufferType
    Mem.HostBuffer
    +Mem.Host

    A buffer of pinned memory on the CPU, possibly accessible on the GPU.

    source
    CUDA.Mem.allocMethod
    Mem.alloc(HostBuffer, bytesize::Integer, [flags])

    Allocate bytesize bytes of page-locked memory on the host. This memory is accessible from the CPU, and makes it possible to perform faster memory copies to the GPU. Furthermore, if flags is set to HOSTALLOC_DEVICEMAP the memory is also accessible from the GPU. These accesses are direct, and go through the PCI bus. If flags is set to HOSTALLOC_PORTABLE, the memory is considered mapped by all CUDA contexts, not just the one that created the memory, which is useful if the memory needs to be accessed from multiple devices. Multiple flags can be set at one time using a bytewise OR:

    flags = HOSTALLOC_PORTABLE | HOSTALLOC_DEVICEMAP
    source
    CUDA.Mem.registerMethod
    Mem.register(HostBuffer, ptr::Ptr, bytesize::Integer, [flags])

    Page-lock the host memory pointed to by ptr. Subsequent transfers to and from devices will be faster, and can be executed asynchronously. If the HOSTREGISTER_DEVICEMAP flag is specified, the buffer will also be accessible directly from the GPU. These accesses are direct, and go through the PCI bus. If the HOSTREGISTER_PORTABLE flag is specified, any CUDA context can access the memory.

    source
    CUDA.Mem.allocMethod
    Mem.alloc(UnifiedBuffer, bytesize::Integer, [flags::CUmemAttach_flags])

    Allocate bytesize bytes of unified memory. This memory is accessible from both the CPU and GPU, with the CUDA driver automatically copying upon first access.

    source
    CUDA.Mem.prefetchMethod
    prefetch(::UnifiedBuffer, [bytes::Integer]; [device::CuDevice], [stream::CuStream])

    Prefetches memory to the specified destination device.

    source
    CUDA.Mem.adviseMethod
    advise(::UnifiedBuffer, advice::CUDA.CUmem_advise, [bytes::Integer]; [device::CuDevice])

    Advise about the usage of a given memory range.

    source

    To work with these buffers, you need to convert them to a Ptr or CuPtr. Several methods then work with these raw pointers:

    Memory info

    CUDA.available_memoryFunction
    available_memory()

    Returns the available amount of memory (in bytes), available for allocation by the CUDA context.

    source
    CUDA.total_memoryFunction
    total_memory()

    Returns the total amount of memory (in bytes), available for allocation by the CUDA context.

    source

    Stream Management

    CUDA.CuStreamType
    CuStream(; flags=STREAM_DEFAULT, priority=nothing)

    Create a CUDA stream.

    source
    CUDA.isdoneMethod
    isdone(s::CuStream)

    Return false if a stream is busy (has task running or queued) and true if that stream is free.

    source
    CUDA.priority_rangeFunction
    priority_range()

    Return the valid range of stream priorities as a StepRange (with step size 1). The lower bound of the range denotes the least priority (typically 0), with the upper bound representing the greatest possible priority (typically -1).

    source
    CUDA.synchronizeMethod
    synchronize([stream::CuStream])

    Wait until stream has finished executing, with stream defaulting to the stream associated with the current Julia task.

    See also: device_synchronize

    source

    For specific use cases, special streams are available:

    CUDA.default_streamFunction
    default_stream()

    Return the default stream.

    Note

    It is generally better to use stream() to get a stream object that's local to the current task. That way, operations scheduled in other tasks can overlap.

    source
    CUDA.legacy_streamFunction
    legacy_stream()

    Return a special object to use use an implicit stream with legacy synchronization behavior.

    You can use this stream to perform operations that should block on all streams (with the exception of streams created with STREAM_NON_BLOCKING). This matches the old pre-CUDA 7 global stream behavior.

    source
    CUDA.per_thread_streamFunction
    per_thread_stream()

    Return a special object to use an implicit stream with per-thread synchronization behavior. This stream object is normally meant to be used with APIs that do not have per-thread versions of their APIs (i.e. without a ptsz or ptds suffix).

    Note

    It is generally not needed to use this type of stream. With CUDA.jl, each task already gets its own non-blocking stream, and multithreading in Julia is typically accomplished using tasks.

    source

    Event Management

    CUDA.recordFunction
    record(e::CuEvent, [stream::CuStream])

    Record an event on a stream.

    source
    CUDA.isdoneMethod
    isdone(e::CuEvent)

    Return false if there is outstanding work preceding the most recent call to record(e) and true if all captured work has been completed.

    source
    CUDA.elapsedFunction
    elapsed(start::CuEvent, stop::CuEvent)

    Computes the elapsed time between two events (in seconds).

    source
    CUDA.@elapsedMacro
    @elapsed ex

    A macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute on the GPU, as a floating-point number.

    source

    Execution Control

    CUDA.CuDim3Type
    CuDim3(x)
    +
    +CuDim3((x,))
    +CuDim3((x, y))
    +CuDim3((x, y, x))

    A type used to specify dimensions, consisting of 3 integers for respectively the x, y and z dimension. Unspecified dimensions default to 1.

    Often accepted as argument through the CuDim type alias, eg. in the case of cudacall or CUDA.launch, allowing to pass dimensions as a plain integer or a tuple without having to construct an explicit CuDim3 object.

    source
    CUDA.cudacallFunction
    cudacall(f, types, values...; blocks::CuDim, threads::CuDim,
    +         cooperative=false, shmem=0, stream=stream())

    ccall-like interface for launching a CUDA function f on a GPU.

    For example:

    vadd = CuFunction(md, "vadd")
    +a = rand(Float32, 10)
    +b = rand(Float32, 10)
    +ad = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))
    +unsafe_copyto!(ad, convert(Ptr{Cvoid}, a), 10*sizeof(Float32)))
    +bd = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))
    +unsafe_copyto!(bd, convert(Ptr{Cvoid}, b), 10*sizeof(Float32)))
    +c = zeros(Float32, 10)
    +cd = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))
    +
    +cudacall(vadd, (CuPtr{Cfloat},CuPtr{Cfloat},CuPtr{Cfloat}), ad, bd, cd; threads=10)
    +unsafe_copyto!(convert(Ptr{Cvoid}, c), cd, 10*sizeof(Float32)))

    The blocks and threads arguments control the launch configuration, and should both consist of either an integer, or a tuple of 1 to 3 integers (omitted dimensions default to 1). The types argument can contain both a tuple of types, and a tuple type, the latter being slightly faster.

    source
    CUDA.launchFunction
    launch(f::CuFunction; args...; blocks::CuDim=1, threads::CuDim=1,
    +       cooperative=false, shmem=0, stream=stream())

    Low-level call to launch a CUDA function f on the GPU, using blocks and threads as respectively the grid and block configuration. Dynamic shared memory is allocated according to shmem, and the kernel is launched on stream stream.

    Arguments to a kernel should either be bitstype, in which case they will be copied to the internal kernel parameter buffer, or a pointer to device memory.

    This is a low-level call, prefer to use cudacall instead.

    source
    launch(exec::CuGraphExec, [stream::CuStream])

    Launches an executable graph, by default in the currently-active stream.

    source

    Profiler Control

    CUDA.@profileMacro
    @profile ex

    Run expressions while activating the CUDA profiler.

    Note that this API is used to programmatically control the profiling granularity by allowing profiling to be done only on selective pieces of code. It does not perform any profiling on itself, you need external tools for that.

    source
    CUDA.Profile.startFunction
    start()

    Enables profile collection by the active profiling tool for the current context. If profiling is already enabled, then this call has no effect.

    source
    CUDA.Profile.stopFunction
    stop()

    Disables profile collection by the active profiling tool for the current context. If profiling is already disabled, then this call has no effect.

    source

    Texture Memory

    Textures are represented by objects of type CuTexture which are bound to some underlying memory, either CuArrays or CuTextureArrays:

    CUDA.CuTextureType
    CuTexture{T,N,P}

    N-dimensional texture object with elements of type T. These objects do not store data themselves, but are bounds to another source of device memory. Texture objects can be passed to CUDA kernels, where they will be accessible through the CuDeviceTexture type.

    Warning

    Experimental API. Subject to change without deprecation.

    source
    CUDA.CuTextureMethod
    CuTexture{T,N,P}(parent::P; address_mode, filter_mode, normalized_coordinates)

    Construct a N-dimensional texture object with elements of type T as stored in parent.

    Several keyword arguments alter the behavior of texture objects:

    • address_mode (wrap, clamp, mirror): how out-of-bounds values are accessed. Can be specified as a value for all dimensions, or as a tuple of N entries.
    • interpolation (nearest neighbour, linear, bilinear): how non-integral indices are fetched. Nearest-neighbour fetches a single value, others interpolate between multiple.
    • normalized_coordinates (true, false): whether indices are expected to fall in the normalized [0:1) range.

    !!! warning Experimental API. Subject to change without deprecation.

    source
    CuTexture(x::CuTextureArray{T,N})

    Create a N-dimensional texture object withelements of type T that will be read from x.

    Warning

    Experimental API. Subject to change without deprecation.

    source
    CuTexture(x::CuArray{T,N})

    Create a N-dimensional texture object that reads from a CuArray.

    Note that it is necessary the their memory is well aligned and strided (good pitch). Currently, that is not being enforced.

    Warning

    Experimental API. Subject to change without deprecation.

    source

    You can create CuTextureArray objects from both host and device memory:

    CUDA.CuTextureArrayType
    CuTextureArray{T,N}(undef, dims)

    N-dimensional dense texture array with elements of type T. These arrays are optimized for texture fetching, and are only meant to be used as a source for CuTexture{T,N,P} objects.

    Warning

    Experimental API. Subject to change without deprecation.

    source
    CUDA.CuTextureArrayMethod
    CuTextureArray(A::AbstractArray)

    Allocate and initialize a texture buffer from host memory in A.

    Warning

    Experimental API. Subject to change without deprecation.

    source
    CuTextureArray(A::CuArray)

    Allocate and initialize a texture buffer from device memory in A.

    Warning

    Experimental API. Subject to change without deprecation.

    source

    Occupancy API

    The occupancy API can be used to figure out an appropriate launch configuration for a compiled kernel (represented as a CuFunction) on the current device:

    CUDA.launch_configurationFunction
    launch_configuration(fun::CuFunction; shmem=0, max_threads=0)

    Calculate a suggested launch configuration for kernel fun requiring shmem bytes of dynamic shared memory. Returns a tuple with a suggested amount of threads, and the minimal amount of blocks to reach maximal occupancy. Optionally, the maximum amount of threads can be constrained using max_threads.

    In the case of a variable amount of shared memory, pass a callable object for shmem instead, taking a single integer representing the block size and returning the amount of dynamic shared memory for that configuration.

    source
    CUDA.active_blocksFunction
    active_blocks(fun::CuFunction, threads; shmem=0)

    Calculate the maximum number of active blocks per multiprocessor when running threads threads of a kernel fun requiring shmem bytes of dynamic shared memory.

    source
    CUDA.occupancyFunction
    occupancy(fun::CuFunction, threads; shmem=0)

    Calculate the theoretical occupancy of launching threads threads of a kernel fun requiring shmem bytes of dynamic shared memory.

    source

    Graph Execution

    CUDA graphs can be easily recorded and executed using the high-level @captured macro:

    CUDA.@capturedMacro
    for ...
    +    @captured begin
    +        # code that executes several kernels or CUDA operations
    +    end
    +end

    A convenience macro for recording a graph of CUDA operations and automatically cache and update the execution. This can improve performance when executing kernels in a loop, where the launch overhead might dominate the execution.

    Warning

    For this to be effective, the kernels and operations executed inside of the captured region should not signficantly change across iterations of the loop. It is allowed to, e.g., change kernel arguments or inputs to operations, as this will be processed by updating the cached executable graph. However, significant changes will result in an instantiation of the graph from scratch, which is an expensive operation.

    See also: capture.

    source

    Low-level operations are available too:

    CUDA.CuGraphType
    CuGraph([flags])

    Create an empty graph for use with low-level graph operations. If you want to create a graph while directly recording operations, use capture. For a high-level interface that also automatically executes the graph, use the @captured macro.

    source
    CUDA.captureFunction
    capture([flags], [throw_error::Bool=true]) do
    +    ...
    +end

    Capture a graph of CUDA operations. The returned graph can then be instantiated and executed repeatedly for improved performance.

    Note that many operations, like initial kernel compilation or memory allocations, cannot be captured. To work around this, you can set the throw_error keyword to false, which will cause this function to return nothing if such a failure happens. You can then try to evaluate the function in a regular way, and re-record afterwards.

    See also: instantiate.

    source
    CUDA.instantiateFunction
    instantiate(graph::CuGraph)

    Creates an executable graph from a graph. This graph can then be launched, or updated with an other graph.

    See also: launch, update.

    source
    CUDA.launchMethod
    launch(f::CuFunction; args...; blocks::CuDim=1, threads::CuDim=1,
    +       cooperative=false, shmem=0, stream=stream())

    Low-level call to launch a CUDA function f on the GPU, using blocks and threads as respectively the grid and block configuration. Dynamic shared memory is allocated according to shmem, and the kernel is launched on stream stream.

    Arguments to a kernel should either be bitstype, in which case they will be copied to the internal kernel parameter buffer, or a pointer to device memory.

    This is a low-level call, prefer to use cudacall instead.

    source
    launch(exec::CuGraphExec, [stream::CuStream])

    Launches an executable graph, by default in the currently-active stream.

    source
    CUDA.updateFunction
    update(exec::CuGraphExec, graph::CuGraph; [throw_error::Bool=true])

    Check whether an executable graph can be updated with a graph and perform the update if possible. Returns a boolean indicating whether the update was successful. Unless throw_error is set to false, also throws an error if the update failed.

    source
    diff --git a/previews/PR2003/search/index.html b/previews/PR2003/search/index.html new file mode 100644 index 0000000000..27ceeb471b --- /dev/null +++ b/previews/PR2003/search/index.html @@ -0,0 +1,6 @@ + +Search · CUDA.jl

    Loading search...

      diff --git a/previews/PR2003/search_index.js b/previews/PR2003/search_index.js new file mode 100644 index 0000000000..091b4ec5d2 --- /dev/null +++ b/previews/PR2003/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"installation/conditional/#Conditional-use","page":"Conditional use","title":"Conditional use","text":"","category":"section"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"CUDA.jl is special in that developers may want to depend on the GPU toolchain even though users might not have a GPU. In this section, we describe two different usage scenarios and how to implement them. Key to remember is that CUDA.jl will always load, which means you need to manually check if the package is functional.","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"Because CUDA.jl always loads, even if the user doesn't have a GPU or CUDA, you should just depend on it like any other package (and not use, e.g., Requires.jl). This ensures that breaking changes to the GPU stack will be taken into account by the package resolver when installing your package.","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"If you unconditionally use the functionality from CUDA.jl, you will get a run-time error in the case the package failed to initialize. For example, on a system without CUDA:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"julia> using CUDA\njulia> CUDA.driver_version()\nERROR: UndefVarError: libcuda not defined","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"To avoid this, you should call CUDA.functional() to inspect whether the package is functional and condition your use of GPU functionality on that. Let's illustrate with two scenarios, one where having a GPU is required, and one where it's optional.","category":"page"},{"location":"installation/conditional/#Scenario-1:-GPU-is-required","page":"Conditional use","title":"Scenario 1: GPU is required","text":"","category":"section"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"If your application requires a GPU, and its functionality is not designed to work without CUDA, you should just import the necessary packages and inspect if they are functional:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"using CUDA\n@assert CUDA.functional(true)","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"Passing true as an argument makes CUDA.jl display why initialization might have failed.","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"If you are developing a package, you should take care only to perform this check at run time. This ensures that your module can always be precompiled, even on a system without a GPU:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"module MyApplication\n\nusing CUDA\n\n__init__() = @assert CUDA.functional(true)\n\nend","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"This of course also implies that you should avoid any calls to the GPU stack from global scope, since the package might not be functional.","category":"page"},{"location":"installation/conditional/#Scenario-2:-GPU-is-optional","page":"Conditional use","title":"Scenario 2: GPU is optional","text":"","category":"section"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"If your application does not require a GPU, and can work without the CUDA packages, there is a tradeoff. As an example, let's define a function that uploads an array to the GPU if available:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"module MyApplication\n\nusing CUDA\n\nif CUDA.functional()\n to_gpu_or_not_to_gpu(x::AbstractArray) = CuArray(x)\nelse\n to_gpu_or_not_to_gpu(x::AbstractArray) = x\nend\n\nend","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"This works, but cannot be simply adapted to a scenario with precompilation on a system without CUDA. One option is to evaluate code at run time:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"function __init__()\n if CUDA.functional()\n @eval to_gpu_or_not_to_gpu(x::AbstractArray) = CuArray(x)\n else\n @eval to_gpu_or_not_to_gpu(x::AbstractArray) = x\n end\nend","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"However, this causes compilation at run-time, and might negate much of the advantages that precompilation has to offer. Instead, you can use a global flag:","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"const use_gpu = Ref(false)\nto_gpu_or_not_to_gpu(x::AbstractArray) = use_gpu[] ? CuArray(x) : x\n\nfunction __init__()\n use_gpu[] = CUDA.functional()\nend","category":"page"},{"location":"installation/conditional/","page":"Conditional use","title":"Conditional use","text":"The disadvantage of this approach is the introduction of a type instability.","category":"page"},{"location":"usage/overview/#UsageOverview","page":"Overview","title":"Overview","text":"","category":"section"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"The CUDA.jl package provides three distinct, but related, interfaces for CUDA programming:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"the CuArray type: for programming with arrays;\nnative kernel programming capabilities: for writing CUDA kernels in Julia;\nCUDA API wrappers: for low-level interactions with the CUDA libraries.","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"Much of the Julia CUDA programming stack can be used by just relying on the CuArray type, and using platform-agnostic programming patterns like broadcast and other array abstractions. Only once you hit a performance bottleneck, or some missing functionality, you might need to write a custom kernel or use the underlying CUDA APIs.","category":"page"},{"location":"usage/overview/#The-CuArray-type","page":"Overview","title":"The CuArray type","text":"","category":"section"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"The CuArray type is an essential part of the toolchain. Primarily, it is used to manage GPU memory, and copy data from and back to the CPU:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"a = CuArray{Int}(undef, 1024)\n\n# essential memory operations, like copying, filling, reshaping, ...\nb = copy(a)\nfill!(b, 0)\n@test b == CUDA.zeros(Int, 1024)\n\n# automatic memory management\na = nothing","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"Beyond memory management, there are a whole range of array operations to process your data. This includes several higher-order operations that take other code as arguments, such as map, reduce or broadcast. With these, it is possible to perform kernel-like operations without actually writing your own GPU kernels:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"a = CUDA.zeros(1024)\nb = CUDA.ones(1024)\na.^2 .+ sin.(b)","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"When possible, these operations integrate with existing vendor libraries such as CUBLAS and CURAND. For example, multiplying matrices or generating random numbers will automatically dispatch to these high-quality libraries, if types are supported, and fall back to generic implementations otherwise.","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"For more details, refer to the section on Array programming.","category":"page"},{"location":"usage/overview/#Kernel-programming-with-@cuda","page":"Overview","title":"Kernel programming with @cuda","text":"","category":"section"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"If an operation cannot be expressed with existing functionality for CuArray, or you need to squeeze every last drop of performance out of your GPU, you can always write a custom kernel. Kernels are functions that are executed in a massively parallel fashion, and are launched by using the @cuda macro:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"a = CUDA.zeros(1024)\n\nfunction kernel(a)\n i = threadIdx().x\n a[i] += 1\n return\nend\n\n@cuda threads=length(a) kernel(a)","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"These kernels give you all the flexibility and performance a GPU has to offer, within a familiar language. However, not all of Julia is supported: you (generally) cannot allocate memory, I/O is disallowed, and badly-typed code will not compile. As a general rule of thumb, keep kernels simple, and only incrementally port code while continuously verifying that it still compiles and executes as expected.","category":"page"},{"location":"usage/overview/#CUDA-API-wrappers","page":"Overview","title":"CUDA API wrappers","text":"","category":"section"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"For advanced use of the CUDA, you can use the driver API wrappers in CUDA.jl. Common operations include synchronizing the GPU, inspecting its properties, starting the profiler, etc. These operations are low-level, but for your convenience wrapped using high-level constructs. For example:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"CUDA.@profile begin\n # code that runs under the profiler\nend\n\n# or\n\nfor device in CUDA.devices()\n @show capability(device)\nend","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"If such high-level wrappers are missing, you can always access the underling C API (functions and structures prefixed with cu) without having to ever exit Julia:","category":"page"},{"location":"usage/overview/","page":"Overview","title":"Overview","text":"version = Ref{Cint}()\nCUDA.cuDriverGetVersion(version)\n@show version[]","category":"page"},{"location":"usage/array/#Array-programming","page":"Array programming","title":"Array programming","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"DocTestSetup = quote\n using CUDA\n\n import Random\n Random.seed!(0)\n\n CURAND.seed!(0)\nend","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"The easiest way to use the GPU's massive parallelism, is by expressing operations in terms of arrays: CUDA.jl provides an array type, CuArray, and many specialized array operations that execute efficiently on the GPU hardware. In this section, we will briefly demonstrate use of the CuArray type. Since we expose CUDA's functionality by implementing existing Julia interfaces on the CuArray type, you should refer to the upstream Julia documentation for more information on these operations.","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"If you encounter missing functionality, or are running into operations that trigger so-called \"scalar iteration\", have a look at the issue tracker and file a new issue if there's none. Do note that you can always access the underlying CUDA APIs by calling into the relevant submodule. For example, if parts of the Random interface isn't properly implemented by CUDA.jl, you can look at the CURAND documentation and possibly call methods from the CURAND submodule directly. These submodules are available after importing the CUDA package.","category":"page"},{"location":"usage/array/#Construction-and-Initialization","page":"Array programming","title":"Construction and Initialization","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"The CuArray type aims to implement the AbstractArray interface, and provide implementations of methods that are commonly used when working with arrays. That means you can construct CuArrays in the same way as regular Array objects:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> CuArray{Int}(undef, 2)\n2-element CuArray{Int64, 1}:\n 0\n 0\n\njulia> CuArray{Int}(undef, (1,2))\n1×2 CuArray{Int64, 2}:\n 0 0\n\njulia> similar(ans)\n1×2 CuArray{Int64, 2}:\n 0 0","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Copying memory to or from the GPU can be expressed using constructors as well, or by calling copyto!:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CuArray([1,2])\n2-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 1\n 2\n\njulia> b = Array(a)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> copyto!(b, a)\n2-element Vector{Int64}:\n 1\n 2","category":"page"},{"location":"usage/array/#Higher-order-abstractions","page":"Array programming","title":"Higher-order abstractions","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"The real power of programming GPUs with arrays comes from Julia's higher-order array abstractions: Operations that take user code as an argument, and specialize execution on it. With these functions, you can often avoid having to write custom kernels. For example, to perform simple element-wise operations you can use map or broadcast:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CuArray{Float32}(undef, (1,2));\n\njulia> a .= 5\n1×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 5.0 5.0\n\njulia> map(sin, a)\n1×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n -0.958924 -0.958924","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"To reduce the dimensionality of arrays, CUDA.jl implements the various flavours of (map)reduce(dim):","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CUDA.ones(2,3)\n2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 1.0 1.0 1.0\n 1.0 1.0 1.0\n\njulia> reduce(+, a)\n6.0f0\n\njulia> mapreduce(sin, *, a; dims=2)\n2×1 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.59582335\n 0.59582335\n\njulia> b = CUDA.zeros(1)\n1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.0\n\njulia> Base.mapreducedim!(identity, +, b, a)\n1×1 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 6.0","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"To retain intermediate values, you can use accumulate:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CUDA.ones(2,3)\n2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 1.0 1.0 1.0\n 1.0 1.0 1.0\n\njulia> accumulate(+, a; dims=2)\n2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 1.0 2.0 3.0\n 1.0 2.0 3.0","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Be wary that the operator f of accumulate, accumulate!, scan and scan! must be associative since the operation is performed in parallel. That is f(f(a,b)c) must be equivalent to f(a,f(b,c)). Accumulating with a non-associative operator on a CuArray will not produce the same result as on an Array.","category":"page"},{"location":"usage/array/#Logical-operations","page":"Array programming","title":"Logical operations","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"CuArrays can also be indexed with arrays of boolean values to select items:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CuArray([1,2,3])\n3-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 1\n 2\n 3\n\njulia> a[[false,true,false]]\n1-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 2","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Built on top of this, are several functions with higher-level semantics:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CuArray([11,12,13])\n3-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 11\n 12\n 13\n\njulia> findall(isodd, a)\n2-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 1\n 3\n\njulia> findfirst(isodd, a)\n1\n\njulia> b = CuArray([11 12 13; 21 22 23])\n2×3 CuArray{Int64, 2, CUDA.Mem.DeviceBuffer}:\n 11 12 13\n 21 22 23\n\njulia> findmin(b)\n(11, CartesianIndex(1, 1))\n\njulia> findmax(b; dims=2)\n([13; 23;;], CartesianIndex{2}[CartesianIndex(1, 3); CartesianIndex(2, 3);;])","category":"page"},{"location":"usage/array/#Array-wrappers","page":"Array programming","title":"Array wrappers","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"To some extent, CUDA.jl also supports well-known array wrappers from the standard library:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CuArray(collect(1:10))\n10-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n\njulia> a = CuArray(collect(1:6))\n6-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 1\n 2\n 3\n 4\n 5\n 6\n\njulia> b = reshape(a, (2,3))\n2×3 CuArray{Int64, 2, CUDA.Mem.DeviceBuffer}:\n 1 3 5\n 2 4 6\n\njulia> c = view(a, 2:5)\n4-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 2\n 3\n 4\n 5","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"The above contiguous view and reshape have been specialized to return new objects of type CuArray. Other wrappers, such as non-contiguous views or the LinearAlgebra wrappers that will be discussed below, are implemented using their own type (e.g. SubArray or Transpose). This can cause problems, as calling methods with these wrapped objects will not dispatch to specialized CuArray methods anymore. That may result in a call to fallback functionality that performs scalar iteration.","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Certain common operations, like broadcast or matrix multiplication, do know how to deal with array wrappers by using the Adapt.jl package. This is still not a complete solution though, e.g. new array wrappers are not covered, and only one level of wrapping is supported. Sometimes the only solution is to materialize the wrapper to a CuArray again.","category":"page"},{"location":"usage/array/#Random-numbers","page":"Array programming","title":"Random numbers","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Base's convenience functions for generating random numbers are available in the CUDA module as well:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> CUDA.rand(2)\n2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.74021935\n 0.9209938\n\njulia> CUDA.randn(Float64, 2, 1)\n2×1 CuArray{Float64, 2, CUDA.Mem.DeviceBuffer}:\n -0.3893830994647195\n 1.618410515635752","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Behind the scenes, these random numbers come from two different generators: one backed by CURAND, another by kernels defined in CUDA.jl. Operations on these generators are implemented using methods from the Random standard library:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> using Random\n\njulia> a = Random.rand(CURAND.default_rng(), Float32, 1)\n1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.74021935\n\njulia> a = Random.rand!(CUDA.default_rng(), a)\n1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.46691537","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"CURAND also supports generating lognormal and Poisson-distributed numbers:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> CUDA.rand_logn(Float32, 1, 5; mean=2, stddev=20)\n1×5 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 2567.61 4.256f-6 54.5948 0.00283999 9.81175f22\n\njulia> CUDA.rand_poisson(UInt32, 1, 10; lambda=100)\n1×10 CuArray{UInt32, 2, CUDA.Mem.DeviceBuffer}:\n 0x00000058 0x00000066 0x00000061 … 0x0000006b 0x0000005f 0x00000069","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Note that these custom operations are only supported on a subset of types.","category":"page"},{"location":"usage/array/#Linear-algebra","page":"Array programming","title":"Linear algebra","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"CUDA's linear algebra functionality from the CUBLAS library is exposed by implementing methods in the LinearAlgebra standard library:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> # enable logging to demonstrate a CUBLAS kernel is used\n CUBLAS.cublasLoggerConfigure(1, 0, 1, C_NULL)\n\njulia> CUDA.rand(2,2) * CUDA.rand(2,2)\nI! cuBLAS (v10.2) function cublasStatus_t cublasSgemm_v2(cublasContext*, cublasOperation_t, cublasOperation_t, int, int, int, const float*, const float*, int, const float*, int, const float*, float*, int) called\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.295727 0.479395\n 0.624576 0.557361","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Certain operations, like the above matrix-matrix multiplication, also have a native fallback written in Julia for the purpose of working with types that are not supported by CUBLAS:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> # enable logging to demonstrate no CUBLAS kernel is used\n CUBLAS.cublasLoggerConfigure(1, 0, 1, C_NULL)\n\njulia> CUDA.rand(Int128, 2, 2) * CUDA.rand(Int128, 2, 2)\n2×2 CuArray{Int128, 2, CUDA.Mem.DeviceBuffer}:\n -147256259324085278916026657445395486093 -62954140705285875940311066889684981211\n -154405209690443624360811355271386638733 -77891631198498491666867579047988353207","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Operations that exist in CUBLAS, but are not (yet) covered by high-level constructs in the LinearAlgebra standard library, can be accessed directly from the CUBLAS submodule. Note that you do not need to call the C wrappers directly (e.g. cublasDdot), as many operations have more high-level wrappers available as well (e.g. dot):","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> x = CUDA.rand(2)\n2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.74021935\n 0.9209938\n\njulia> y = CUDA.rand(2)\n2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:\n 0.03902049\n 0.9689629\n\njulia> CUBLAS.dot(2, x, y)\n0.92129254f0\n\njulia> using LinearAlgebra\n\njulia> dot(Array(x), Array(y))\n0.92129254f0","category":"page"},{"location":"usage/array/#Solver","page":"Array programming","title":"Solver","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"LAPACK-like functionality as found in the CUSOLVER library can be accessed through methods in the LinearAlgebra standard library too:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> using LinearAlgebra\n\njulia> a = CUDA.rand(2,2)\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.740219 0.0390205\n 0.920994 0.968963\n\njulia> a = a * a'\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.549447 0.719547\n 0.719547 1.78712\n\njulia> cholesky(a)\nCholesky{Float32, CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}}\nU factor:\n2×2 UpperTriangular{Float32, CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}}:\n 0.741247 0.970725\n ⋅ 0.919137","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Other operations are bound to the left-division operator:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CUDA.rand(2,2)\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.740219 0.0390205\n 0.920994 0.968963\n\njulia> b = CUDA.rand(2,2)\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.925141 0.667319\n 0.44635 0.109931\n\njulia> a \\ b\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 1.29018 0.942772\n -0.765663 -0.782648\n\njulia> Array(a) \\ Array(b)\n2×2 Matrix{Float32}:\n 1.29018 0.942773\n -0.765663 -0.782648","category":"page"},{"location":"usage/array/#Sparse-arrays","page":"Array programming","title":"Sparse arrays","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Sparse array functionality from the CUSPARSE library is mainly available through functionality from the SparseArrays package applied to CuSparseArray objects:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> using SparseArrays\n\njulia> x = sprand(10,0.2)\n10-element SparseVector{Float64, Int64} with 5 stored entries:\n [2 ] = 0.538639\n [4 ] = 0.89699\n [6 ] = 0.258478\n [7 ] = 0.338949\n [10] = 0.424742\n\njulia> using CUDA.CUSPARSE\n\njulia> d_x = CuSparseVector(x)\n10-element CuSparseVector{Float64, Int32} with 5 stored entries:\n [2 ] = 0.538639\n [4 ] = 0.89699\n [6 ] = 0.258478\n [7 ] = 0.338949\n [10] = 0.424742\n\njulia> nonzeros(d_x)\n5-element CuArray{Float64, 1, CUDA.Mem.DeviceBuffer}:\n 0.538639413965653\n 0.8969897902567084\n 0.25847781536337067\n 0.3389490517221738\n 0.4247416640213063\n\njulia> nnz(d_x)\n5","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"For 2-D arrays the CuSparseMatrixCSC and CuSparseMatrixCSR can be used.","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Non-integrated functionality can be access directly in the CUSPARSE submodule again.","category":"page"},{"location":"usage/array/#FFTs","page":"Array programming","title":"FFTs","text":"","category":"section"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"Functionality from CUFFT is integrated with the interfaces from the AbstractFFTs.jl package:","category":"page"},{"location":"usage/array/","page":"Array programming","title":"Array programming","text":"julia> a = CUDA.rand(2,2)\n2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:\n 0.740219 0.0390205\n 0.920994 0.968963\n\njulia> using CUDA.CUFFT\n\njulia> fft(a)\n2×2 CuArray{ComplexF32, 2, CUDA.Mem.DeviceBuffer}:\n 2.6692+0.0im 0.65323+0.0im\n -1.11072+0.0im 0.749168+0.0im","category":"page"},{"location":"usage/memory/#Memory-management","page":"Memory management","title":"Memory management","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"A crucial aspect of working with a GPU is managing the data on it. The CuArray type is the primary interface for doing so: Creating a CuArray will allocate data on the GPU, copying elements to it will upload, and converting back to an Array will download values to the CPU:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"# generate some data on the CPU\ncpu = rand(Float32, 1024)\n\n# allocate on the GPU\ngpu = CuArray{Float32}(undef, 1024)\n\n# copy from the CPU to the GPU\ncopyto!(gpu, cpu)\n\n# download and verify\n@test cpu == Array(gpu)","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"A shorter way to accomplish these operations is to call the copy constructor, i.e. CuArray(cpu).","category":"page"},{"location":"usage/memory/#Type-preserving-upload","page":"Memory management","title":"Type-preserving upload","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"In many cases, you might not want to convert your input data to a dense CuArray. For example, with array wrappers you will want to preserve that wrapper type on the GPU and only upload the contained data. The Adapt.jl package does exactly that, and contains a list of rules on how to unpack and reconstruct types like array wrappers so that we can preserve the type when, e.g., uploading data to the GPU:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> cpu = Diagonal([1,2]) # wrapped data on the CPU\n2×2 Diagonal{Int64,Array{Int64,1}}:\n 1 ⋅\n ⋅ 2\n\njulia> using Adapt\n\njulia> gpu = adapt(CuArray, cpu) # upload to the GPU, keeping the wrapper intact\n2×2 Diagonal{Int64,CuArray{Int64,1,Nothing}}:\n 1 ⋅\n ⋅ 2","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"Since this is a very common operation, the cu function conveniently does this for you:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> cu(cpu)\n2×2 Diagonal{Float32,CuArray{Float32,1,Nothing}}:\n 1.0 ⋅\n ⋅ 2.0","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"warning: Warning\nThe cu function is opinionated and converts input most floating-point scalars to Float32. This is often a good call, as Float64 and many other scalar types perform badly on the GPU. If this is unwanted, use adapt directly.","category":"page"},{"location":"usage/memory/#Garbage-collection","page":"Memory management","title":"Garbage collection","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"Instances of the CuArray type are managed by the Julia garbage collector. This means that they will be collected once they are unreachable, and the memory hold by it will be repurposed or freed. There is no need for manual memory management, just make sure your objects are not reachable (i.e., there are no instances or references).","category":"page"},{"location":"usage/memory/#Memory-pool","page":"Memory management","title":"Memory pool","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"Behind the scenes, a memory pool will hold on to your objects and cache the underlying memory to speed up future allocations. As a result, your GPU might seem to be running out of memory while it isn't. When memory pressure is high, the pool will automatically free cached objects:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> CUDA.memory_status() # initial state\nEffective GPU memory usage: 16.12% (2.537 GiB/15.744 GiB)\nMemory pool usage: 0 bytes (0 bytes reserved)\n\njulia> a = CuArray{Int}(undef, 1024); # allocate 8KB\n\njulia> CUDA.memory_status()\nEffective GPU memory usage: 16.35% (2.575 GiB/15.744 GiB)\nMemory pool usage: 8.000 KiB (32.000 MiB reserved)\n\njulia> a = nothing; GC.gc(true)\n\njulia> CUDA.memory_status() # 8KB is now cached\nEffective GPU memory usage: 16.34% (2.573 GiB/15.744 GiB)\nMemory pool usage: 0 bytes (32.000 MiB reserved)\n","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"If for some reason you need all cached memory to be reclaimed, call CUDA.reclaim():","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> CUDA.reclaim()\n\njulia> CUDA.memory_status()\nEffective GPU memory usage: 16.17% (2.546 GiB/15.744 GiB)\nMemory pool usage: 0 bytes (0 bytes reserved)","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"note: Note\nIt should never be required to manually reclaim memory before performing any high-level GPU array operation: Functionality that allocates should itself call into the memory pool and free any cached memory if necessary. It is a bug if that operation runs into an out-of-memory situation only if not manually reclaiming memory beforehand.","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"note: Note\nIf you need to disable the memory pool, e.g. because of incompatibility with certain CUDA APIs, set the environment variable JULIA_CUDA_MEMORY_POOL to none before importing CUDA.jl.","category":"page"},{"location":"usage/memory/#Memory-limits","page":"Memory management","title":"Memory limits","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"If you're sharing a GPU with other users or applications, you might want to limit how much memory is used. By default, CUDA.jl will configure the memory pool to use all available device memory. You can change this using two environment variables:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"JULIA_CUDA_SOFT_MEMORY_LIMIT: This is an advisory limit, used to configure the memory pool. If you set this to a nonzero value, the memory pool will attempt to release cached memory until memory use falls below this limit. Note that this only happens at specific synchronization points, so memory use may temporarily exceed this limit. In addition, this limit is incompatible with JULIA_CUDA_MEMORY_POOL=none.\nJULIA_CUDA_HARD_MEMORY_LIMIT: This is a hard limit, checked before every allocation. This incurs a certain cost, so it is recommended to first try to use the soft limit.","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"The value of these variables can be formatted as a numer of bytes, optionally followed by a unit, or as a percentage of the total device memory. Examples: 100M, 50%, 1.5GiB, 10000.","category":"page"},{"location":"usage/memory/#Avoiding-GC-pressure","page":"Memory management","title":"Avoiding GC pressure","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"When your application performs a lot of memory operations, the time spent during GC might increase significantly. This happens more often than it does on the CPU because GPUs tend to have smaller memories and more frequently run out of it. When that happens, CUDA invokes the Julia garbage collector, which then needs to scan objects to see if they can be freed to get back some GPU memory.","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"To avoid having to depend on the Julia GC to free up memory, you can directly inform CUDA.jl when an allocation can be freed (or reused) by calling the unsafe_free! method. Once you've done so, you cannot use that array anymore:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> a = CuArray([1])\n1-element CuArray{Int64,1,Nothing}:\n 1\n\njulia> CUDA.unsafe_free!(a)\n\njulia> a\n1-element CuArray{Int64,1,Nothing}:\nError showing value of type CuArray{Int64,1,Nothing}:\nERROR: AssertionError: Use of freed memory","category":"page"},{"location":"usage/memory/#Batching-iterator","page":"Memory management","title":"Batching iterator","text":"","category":"section"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"If you are dealing with data sets that are too large to fit on the GPU all at once, you can use CuIterator to batch operations:","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"julia> batches = [([1], [2]), ([3], [4])]\n\njulia> for (batch, (a,b)) in enumerate(CuIterator(batches))\n println(\"Batch $batch: \", a .+ b)\n end\nBatch 1: [3]\nBatch 2: [7]","category":"page"},{"location":"usage/memory/","page":"Memory management","title":"Memory management","text":"For each batch, every argument (assumed to be an array-like) is uploaded to the GPU using the adapt mechanism from above. Afterwards, the memory is eagerly put back in the CUDA memory pool using unsafe_free! to lower GC pressure.","category":"page"},{"location":"usage/workflow/#Workflow","page":"Workflow","title":"Workflow","text":"","category":"section"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"A typical approach for porting or developing an application for the GPU is as follows:","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"develop an application using generic array functionality, and test it on the CPU with the Array type\nport your application to the GPU by switching to the CuArray type\ndisallow the CPU fallback (\"scalar indexing\") to find operations that are not implemented for or incompatible with GPU execution\n(optional) use lower-level, CUDA-specific interfaces to implement missing functionality or optimize performance","category":"page"},{"location":"usage/workflow/#UsageWorkflowScalar","page":"Workflow","title":"Scalar indexing","text":"","category":"section"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"Many array operations in Julia are implemented using loops, processing one element at a time. Doing so with GPU arrays is very ineffective, as the loop won't actually execute on the GPU, but transfer one element at a time and process it on the CPU. As this wrecks performance, you will be warned when performing this kind of iteration:","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"julia> a = CuArray([1])\n1-element CuArray{Int64,1,Nothing}:\n 1\n\njulia> a[1] += 1\n┌ Warning: Performing scalar indexing.\n│ ...\n└ @ GPUArrays ~/Julia/pkg/GPUArrays/src/host/indexing.jl:57\n2","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"Scalar indexing is only allowed in an interactive session, e.g. the REPL, because it is convenient when porting CPU code to the GPU. If you want to disallow scalar indexing, e.g. to verify that your application executes correctly on the GPU, call the allowscalar function:","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"julia> CUDA.allowscalar(false)\n\njulia> a[1] .+ 1\nERROR: scalar getindex is disallowed\nStacktrace:\n [1] error(::String) at ./error.jl:33\n [2] assertscalar(::String) at GPUArrays/src/indexing.jl:14\n [3] getindex(::CuArray{Int64,1,Nothing}, ::Int64) at GPUArrays/src/indexing.jl:54\n [4] top-level scope at REPL[5]:1\n\njulia> a .+ 1\n1-element CuArray{Int64,1,Nothing}:\n 2","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"In a non-interactive session, e.g. when running code from a script or application, scalar indexing is disallowed by default. There is no global toggle to allow scalar indexing; if you really need it, you can mark expressions using allowscalar with do-block syntax or @allowscalar macro:","category":"page"},{"location":"usage/workflow/","page":"Workflow","title":"Workflow","text":"julia> a = CuArray([1])\n1-element CuArray{Int64, 1}:\n 1\n\njulia> CUDA.allowscalar(false)\n\njulia> CUDA.allowscalar() do\n a[1] += 1\n end\n2\n\njulia> CUDA.@allowscalar a[1] += 1\n3","category":"page"},{"location":"installation/overview/#InstallationOverview","page":"Overview","title":"Overview","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"The Julia CUDA stack requires users to have a functional NVIDIA driver and corresponding CUDA toolkit. The former should be installed by you or your system administrator, while the latter can be automatically downloaded by Julia using the artifact subsystem.","category":"page"},{"location":"installation/overview/#Package-installation","page":"Overview","title":"Package installation","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"For most users, installing the latest tagged version of CUDA.jl will be sufficient. You can easily do that using the package manager:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"pkg> add CUDA","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"Or, equivalently, via the Pkg API:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"julia> import Pkg; Pkg.add(\"CUDA\")","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"In some cases, you might need to use the master version of this package, e.g., because it includes a specific fix you need. Often, however, the development version of this package itself relies on unreleased versions of other packages. This information is recorded in the manifest at the root of the repository, which you can use by starting Julia from the CUDA.jl directory with the --project flag:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"$ cd .julia/dev/CUDA.jl # or wherever you have CUDA.jl checked out\n$ julia --project\npkg> instantiate # to install correct dependencies\njulia> using CUDA","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"In the case you want to use the development version of CUDA.jl with other packages, you cannot use the manifest and you need to manually install those dependencies from the master branch. Again, the exact requirements are recorded in CUDA.jl's manifest, but often the following instructions will work:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"pkg> add GPUCompiler#master\npkg> add GPUArrays#master\npkg> add LLVM#master","category":"page"},{"location":"installation/overview/#Platform-support","page":"Overview","title":"Platform support","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"We support the same operation systems that NVIDIA supports: Linux, and Windows. Similarly, we support x86, ARM, PPC, ... as long as Julia is supported on it and there exists an NVIDIA driver and CUDA toolkit for your platform. The main development platform (and the only CI system) however is x86_64 on Linux, so if you are using a more exotic combination there might be bugs.","category":"page"},{"location":"installation/overview/#NVIDIA-driver","page":"Overview","title":"NVIDIA driver","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"To use the Julia GPU stack, you need to install the NVIDIA driver for your system and GPU. You can find detailed instructions on the NVIDIA home page.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"If you're using Linux you should always consider installing the driver through the package manager of your distribution. In the case that driver is out of date or does not support your GPU, and you need to download a driver from the NVIDIA home page, similarly prefer a distribution-specific package (e.g., deb, rpm) instead of the generic runfile option.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"If you are using a shared system, ask your system administrator on how to install or load the NVIDIA driver. Generally, you should be able to find and use the CUDA driver library, called libcuda.so on Linux, libcuda.dylib on macOS and nvcuda64.dll on Windows. You should also be able to execute the nvidia-smi command, which lists all available GPUs you have access to.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"On some enterprise systems, CUDA.jl will be able to upgrade the driver for the duration of the session (using CUDA's Forward Compatibility mechanism). This will be mentioned in the CUDA.versioninfo() output, so be sure to verify that before asking your system administrator to upgrade:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"julia> CUDA.versioninfo()\nCUDA runtime 10.2\nCUDA driver 11.8\nNVIDIA driver 520.56.6, originally for CUDA 11.7","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"Finally, to be able to use all of the Julia GPU stack you need to have permission to profile GPU code. On Linux, that means loading the nvidia kernel module with the NVreg_RestrictProfilingToAdminUsers=0 option configured (e.g., in /etc/modprobe.d). Refer to the following document for more information.","category":"page"},{"location":"installation/overview/#CUDA-toolkit","page":"Overview","title":"CUDA toolkit","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"The recommended way to use CUDA.jl is to let it automatically download an appropriate CUDA toolkit. CUDA.jl will check your driver's capabilities, which versions of CUDA are available for your platform, and automatically download an appropriate artifact containing all the libraries that CUDA.jl supports.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"If you really need to use a different CUDA toolkit, it's possible (but not recommended) to load a different version of the CUDA runtime, or even an installation from your local system. Both are configured by setting the version preference (using Preferences.jl) on the CUDARuntimejll.jl package, but there is also a user-friendly API available in CUDA.jl.","category":"page"},{"location":"installation/overview/#Specifying-the-CUDA-version","page":"Overview","title":"Specifying the CUDA version","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"You can choose which version to (try to) download and use by calling CUDA.set_runtime_version!:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"julia> using CUDA\n\njulia> CUDA.set_runtime_version!(v\"11.8\")\n┌ Warning: CUDA Runtime version set to 11.8, please re-start Julia for this to take effect.\n└ @ CUDA /usr/local/share/julia/packages/CUDA/irdEw/lib/cudadrv/version.jl:54","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"This generates the following LocalPreferences.toml file in your active environment:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"[CUDA_Runtime_jll]\nversion = \"11.8\"","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"This preference is compatible with other CUDA JLLs, e.g., if you load CUDNN_jll it will only select artifacts that are compatible with the configured CUDA runtime.","category":"page"},{"location":"installation/overview/#Using-a-local-CUDA","page":"Overview","title":"Using a local CUDA","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"To use a local installation, you can invoke the same API but set the version to \"local\":","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"julia> using CUDA\n\njulia> CUDA.versioninfo()\nCUDA runtime 11.8, artifact installation\n...\n\njulia> CUDA.set_runtime_version!(\"local\")\n┌ Warning: CUDA Runtime version set to local, please re-start Julia for this to take effect.\n└ @ CUDA ~/Julia/pkg/CUDA/lib/cudadrv/version.jl:73","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"After re-launching Julia:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"julia> using CUDA\n\njulia> CUDA.versioninfo()\nCUDA runtime 11.8, local installation\n...","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"Calling the above helper function generates the following LocalPreferences.toml file in your active environment:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"[CUDA_Runtime_jll]\nversion = \"local\"","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"This preference not only configures CUDA.jl to use a local toolkit, it also prevents downloading any artifact, so it may be interesting to set this preference before ever importing CUDA.jl (e.g., by putting this preference file in a system-wide depot).","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"If CUDA.jl doesn't properly detect your local toolkit, it may be that certain libraries or binaries aren't on a globally-discoverable path. For more information, run Julia with the JULIA_DEBUG environment variable set to CUDA_Runtime_Discovery.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"Note that setting the version to \"local\" disables use of any CUDA-related JLL, not just of CUDA_Runtime_jll. This is out of necessity: JLLs are baked in the precompilation image at compile time, while local toolkit discovery happens at run time; this inconsistency makes it impossible to select a compatible artifact for the JLLs. If you care about other JLLs, use CUDA from artifacts.","category":"page"},{"location":"installation/overview/#Containers","page":"Overview","title":"Containers","text":"","category":"section"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"CUDA.jl is container friendly: You can install, precompile, and even import the package on a system without a GPU:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"$ docker run --rm -it julia # note how we're *not* using `--gpus=all` here,\n # so we won't have access to a GPU (or its driver)\n\npkg> add CUDA\n\npkg> precompile\nPrecompiling project...\n[ Info: Precompiling CUDA [052768ef-5323-5732-b1bb-66c8b64840ba]","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"The above is common when building a container (docker build does not take a --gpus argument). It does prevent CUDA.jl from downloading the toolkit artifacts that will be required at run time, because it cannot query the driver for the CUDA compatibility level.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"To avoid having to download the CUDA toolkit artifacts each time you restart your container, it's possible to inform CUDA.jl which toolkit to use. This can be done by calling CUDA.set_runtime_version! when building the container, after which a subsequent import of CUDA.jl will download the necessary artifacts.","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"At run time you obviously do need a CUDA-compatible GPU as well as the CUDA driver library to interface with it. Typically, that library is imported from the host system, e.g., by launching docker using the --gpus=all flag:","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"$ docker run --rm -it --gpus=all julia\n\njulia> using CUDA\n\njulia> CUDA.versioninfo()\nCUDA runtime 11.8\nCUDA driver 11.8\nNVIDIA driver 520.56.6\n\n...","category":"page"},{"location":"installation/overview/","page":"Overview","title":"Overview","text":"All of the above is demonstrated in the Dockerfile that's part of the CUDA.jl repository.","category":"page"},{"location":"api/kernel/#Kernel-programming","page":"Kernel programming","title":"Kernel programming","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"This section lists the package's public functionality that corresponds to special CUDA functions for use in device code. It is loosely organized according to the C language extensions appendix from the CUDA C programming guide. For more information about certain intrinsics, refer to the aforementioned NVIDIA documentation.","category":"page"},{"location":"api/kernel/#Indexing-and-dimensions","page":"Kernel programming","title":"Indexing and dimensions","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"gridDim\nblockIdx\nblockDim\nthreadIdx\nwarpsize\nlaneid\nactive_mask","category":"page"},{"location":"api/kernel/#CUDA.gridDim","page":"Kernel programming","title":"CUDA.gridDim","text":"gridDim()::NamedTuple\n\nReturns the dimensions of the grid.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.blockIdx","page":"Kernel programming","title":"CUDA.blockIdx","text":"blockIdx()::NamedTuple\n\nReturns the block index within the grid.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.blockDim","page":"Kernel programming","title":"CUDA.blockDim","text":"blockDim()::NamedTuple\n\nReturns the dimensions of the block.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.threadIdx","page":"Kernel programming","title":"CUDA.threadIdx","text":"threadIdx()::NamedTuple\n\nReturns the thread index within the block.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.warpsize","page":"Kernel programming","title":"CUDA.warpsize","text":"warpsize(dev::CuDevice)\n\nReturns the warp size (in threads) of the device.\n\n\n\n\n\nwarpsize()::Int32\n\nReturns the warp size (in threads).\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.laneid","page":"Kernel programming","title":"CUDA.laneid","text":"laneid()::Int32\n\nReturns the thread's lane within the warp.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.active_mask","page":"Kernel programming","title":"CUDA.active_mask","text":"active_mask()\n\nReturns a 32-bit mask indicating which threads in a warp are active with the current executing thread.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Device-arrays","page":"Kernel programming","title":"Device arrays","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CUDA.jl provides a primitive, lightweight array type to manage GPU data organized in an plain, dense fashion. This is the device-counterpart to the CuArray, and implements (part of) the array interface as well as other functionality for use on the GPU:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CuDeviceArray\nCUDA.Const","category":"page"},{"location":"api/kernel/#CUDA.CuDeviceArray","page":"Kernel programming","title":"CUDA.CuDeviceArray","text":"CuDeviceArray{T,N,A}(ptr, dims, [maxsize])\n\nConstruct an N-dimensional dense CUDA device array with element type T wrapping a pointer, where N is determined from the length of dims and T is determined from the type of ptr. dims may be a single scalar, or a tuple of integers corresponding to the lengths in each dimension). If the rank N is supplied explicitly as in Array{T,N}(dims), then it must match the length of dims. The same applies to the element type T, which should match the type of the pointer ptr.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA.Const","page":"Kernel programming","title":"CUDA.Const","text":"Const(A::CuDeviceArray)\n\nMark a CuDeviceArray as constant/read-only. The invariant guaranteed is that you will not modify an CuDeviceArray for the duration of the current kernel.\n\nThis API can only be used on devices with compute capability 3.5 or higher.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#Memory-types","page":"Kernel programming","title":"Memory types","text":"","category":"section"},{"location":"api/kernel/#Shared-memory","page":"Kernel programming","title":"Shared memory","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CuStaticSharedArray\nCuDynamicSharedArray","category":"page"},{"location":"api/kernel/#CUDA.CuStaticSharedArray","page":"Kernel programming","title":"CUDA.CuStaticSharedArray","text":"CuStaticSharedArray(T::Type, dims) -> CuDeviceArray{T,N,AS.Shared}\n\nGet an array of type T and dimensions dims (either an integer length or tuple shape) pointing to a statically-allocated piece of shared memory. The type should be statically inferable and the dimensions should be constant, or an error will be thrown and the generator function will be called dynamically.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.CuDynamicSharedArray","page":"Kernel programming","title":"CUDA.CuDynamicSharedArray","text":"CuDynamicSharedArray(T::Type, dims, offset::Integer=0) -> CuDeviceArray{T,N,AS.Shared}\n\nGet an array of type T and dimensions dims (either an integer length or tuple shape) pointing to a dynamically-allocated piece of shared memory. The type should be statically inferable or an error will be thrown and the generator function will be called dynamically.\n\nNote that the amount of dynamic shared memory needs to specified when launching the kernel.\n\nOptionally, an offset parameter indicating how many bytes to add to the base shared memory pointer can be specified. This is useful when dealing with a heterogeneous buffer of dynamic shared memory; in the case of a homogeneous multi-part buffer it is preferred to use view.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Texture-memory","page":"Kernel programming","title":"Texture memory","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CuDeviceTexture","category":"page"},{"location":"api/kernel/#CUDA.CuDeviceTexture","page":"Kernel programming","title":"CUDA.CuDeviceTexture","text":"CuDeviceTexture{T,N,M,NC,I}\n\nN-dimensional device texture with elements of type T. This type is the device-side counterpart of CuTexture{T,N,P}, and can be used to access textures using regular indexing notation. If NC is true, indices used by these accesses should be normalized, i.e., fall into the [0,1) domain. The I type parameter indicates the kind of interpolation that happens when indexing into this texture. The source memory of the texture is specified by the M parameter, either linear memory or a texture array.\n\nDevice-side texture objects cannot be created directly, but should be created host-side using CuTexture{T,N,P} and passed to the kernel as an argument.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#Synchronization","page":"Kernel programming","title":"Synchronization","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"sync_threads\nsync_threads_count\nsync_threads_and\nsync_threads_or\nsync_warp\nthreadfence_block\nthreadfence\nthreadfence_system","category":"page"},{"location":"api/kernel/#CUDA.sync_threads","page":"Kernel programming","title":"CUDA.sync_threads","text":"sync_threads()\n\nWaits until all threads in the thread block have reached this point and all global and shared memory accesses made by these threads prior to sync_threads() are visible to all threads in the block.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.sync_threads_count","page":"Kernel programming","title":"CUDA.sync_threads_count","text":"sync_threads_count(predicate::Int32)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns the number of threads for which predicate evaluates to non-zero.\n\n\n\n\n\nsync_threads_count(predicate::Bool)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns the number of threads for which predicate evaluates to true.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.sync_threads_and","page":"Kernel programming","title":"CUDA.sync_threads_and","text":"sync_threads_and(predicate::Int32)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns non-zero if and only if predicate evaluates to non-zero for all of them.\n\n\n\n\n\nsync_threads_and(predicate::Bool)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns true if and only if predicate evaluates to true for all of them.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.sync_threads_or","page":"Kernel programming","title":"CUDA.sync_threads_or","text":"sync_threads_or(predicate::Int32)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns non-zero if and only if predicate evaluates to non-zero for any of them.\n\n\n\n\n\nsync_threads_or(predicate::Bool)\n\nIdentical to __syncthreads() with the additional feature that it evaluates predicate for all threads of the block and returns true if and only if predicate evaluates to true for any of them.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.sync_warp","page":"Kernel programming","title":"CUDA.sync_warp","text":"sync_warp(mask::Integer=0xffffffff)\n\nWaits threads in the warp, selected by means of the bitmask mask, have reached this point and all global and shared memory accesses made by these threads prior to sync_warp() are visible to those threads in the warp. The default value for mask selects all threads in the warp.\n\nnote: Note\nRequires CUDA >= 9.0 and sm_6.2\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.threadfence_block","page":"Kernel programming","title":"CUDA.threadfence_block","text":"threadfence_block()\n\nA memory fence that ensures that:\n\nAll writes to all memory made by the calling thread before the call to threadfence_block() are observed by all threads in the block of the calling thread as occurring before all writes to all memory made by the calling thread after the call to threadfence_block()\nAll reads from all memory made by the calling thread before the call to threadfence_block() are ordered before all reads from all memory made by the calling thread after the call to threadfence_block().\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.threadfence","page":"Kernel programming","title":"CUDA.threadfence","text":"threadfence()\n\nA memory fence that acts as threadfence_block for all threads in the block of the calling thread and also ensures that no writes to all memory made by the calling thread after the call to threadfence() are observed by any thread in the device as occurring before any write to all memory made by the calling thread before the call to threadfence().\n\nNote that for this ordering guarantee to be true, the observing threads must truly observe the memory and not cached versions of it; this is requires the use of volatile loads and stores, which is not available from Julia right now.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.threadfence_system","page":"Kernel programming","title":"CUDA.threadfence_system","text":"threadfence_system()\n\nA memory fence that acts as threadfence_block for all threads in the block of the calling thread and also ensures that all writes to all memory made by the calling thread before the call to threadfence_system() are observed by all threads in the device, host threads, and all threads in peer devices as occurring before all writes to all memory made by the calling thread after the call to threadfence_system().\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Time-functions","page":"Kernel programming","title":"Time functions","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"clock\nnanosleep","category":"page"},{"location":"api/kernel/#CUDA.clock","page":"Kernel programming","title":"CUDA.clock","text":"clock(UInt32)\n\nReturns the value of a per-multiprocessor counter that is incremented every clock cycle.\n\n\n\n\n\nclock(UInt64)\n\nReturns the value of a per-multiprocessor counter that is incremented every clock cycle.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.nanosleep","page":"Kernel programming","title":"CUDA.nanosleep","text":"nanosleep(t)\n\nPuts a thread for a given amount t(in nanoseconds).\n\nnote: Note\nRequires CUDA >= 10.0 and sm_6.2\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Warp-level-functions","page":"Kernel programming","title":"Warp-level functions","text":"","category":"section"},{"location":"api/kernel/#Voting","page":"Kernel programming","title":"Voting","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The warp vote functions allow the threads of a given warp to perform a reduction-and-broadcast operation. These functions take as input a boolean predicate from each thread in the warp and evaluate it. The results of that evaluation are combined (reduced) across the active threads of the warp in one different ways, broadcasting a single return value to each participating thread.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"vote_all\nvote_any\nvote_uni\nvote_ballot","category":"page"},{"location":"api/kernel/#CUDA.vote_all","page":"Kernel programming","title":"CUDA.vote_all","text":"vote_all(predicate::Bool)\nvote_all_sync(mask::UInt32, predicate::Bool)\n\nEvaluate predicate for all active threads of the warp and return whether predicate is true for all of them.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.vote_any","page":"Kernel programming","title":"CUDA.vote_any","text":"vote_any(predicate::Bool)\nvote_any_sync(mask::UInt32, predicate::Bool)\n\nEvaluate predicate for all active threads of the warp and return whether predicate is true for any of them.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.vote_uni","page":"Kernel programming","title":"CUDA.vote_uni","text":"vote_uni(predicate::Bool)\nvote_uni_sync(mask::UInt32, predicate::Bool)\n\nEvaluate predicate for all active threads of the warp and return whether predicate is the same for any of them.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.vote_ballot","page":"Kernel programming","title":"CUDA.vote_ballot","text":"vote_ballot(predicate::Bool)\nvote_ballot_sync(mask::UInt32, predicate::Bool)\n\nEvaluate predicate for all active threads of the warp and return an integer whose Nth bit is set if and only if predicate is true for the Nth thread of the warp and the Nth thread is active.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Shuffle","page":"Kernel programming","title":"Shuffle","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"shfl_sync\nshfl_up_sync\nshfl_down_sync\nshfl_xor_sync","category":"page"},{"location":"api/kernel/#CUDA.shfl_sync","page":"Kernel programming","title":"CUDA.shfl_sync","text":"shfl_sync(threadmask::UInt32, val, lane::Integer, width::Integer=32)\n\nShuffle a value from a directly indexed lane lane, and synchronize threads according to threadmask.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.shfl_up_sync","page":"Kernel programming","title":"CUDA.shfl_up_sync","text":"shfl_up_sync(threadmask::UInt32, val, delta::Integer, width::Integer=32)\n\nShuffle a value from a lane with lower ID relative to caller, and synchronize threads according to threadmask.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.shfl_down_sync","page":"Kernel programming","title":"CUDA.shfl_down_sync","text":"shfl_down_sync(threadmask::UInt32, val, delta::Integer, width::Integer=32)\n\nShuffle a value from a lane with higher ID relative to caller, and synchronize threads according to threadmask.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.shfl_xor_sync","page":"Kernel programming","title":"CUDA.shfl_xor_sync","text":"shfl_xor_sync(threadmask::UInt32, val, mask::Integer, width::Integer=32)\n\nShuffle a value from a lane based on bitwise XOR of own lane ID with mask, and synchronize threads according to threadmask.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Formatted-Output","page":"Kernel programming","title":"Formatted Output","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"@cushow\n@cuprint\n@cuprintln\n@cuprintf","category":"page"},{"location":"api/kernel/#CUDA.@cushow","page":"Kernel programming","title":"CUDA.@cushow","text":"@cushow(ex)\n\nGPU analog of Base.@show. It comes with the same type restrictions as @cuprintf.\n\n@cushow threadIdx().x\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/#CUDA.@cuprint","page":"Kernel programming","title":"CUDA.@cuprint","text":"@cuprint(xs...)\n@cuprintln(xs...)\n\nPrint a textual representation of values xs to standard output from the GPU. The functionality builds on @cuprintf, and is intended as a more use friendly alternative of that API. However, that also means there's only limited support for argument types, handling 16/32/64 signed and unsigned integers, 32 and 64-bit floating point numbers, Cchars and pointers. For more complex output, use @cuprintf directly.\n\nLimited string interpolation is also possible:\n\n @cuprint(\"Hello, World \", 42, \"\\n\")\n @cuprint \"Hello, World $(42)\\n\"\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/#CUDA.@cuprintln","page":"Kernel programming","title":"CUDA.@cuprintln","text":"@cuprint(xs...)\n@cuprintln(xs...)\n\nPrint a textual representation of values xs to standard output from the GPU. The functionality builds on @cuprintf, and is intended as a more use friendly alternative of that API. However, that also means there's only limited support for argument types, handling 16/32/64 signed and unsigned integers, 32 and 64-bit floating point numbers, Cchars and pointers. For more complex output, use @cuprintf directly.\n\nLimited string interpolation is also possible:\n\n @cuprint(\"Hello, World \", 42, \"\\n\")\n @cuprint \"Hello, World $(42)\\n\"\n\n\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/#CUDA.@cuprintf","page":"Kernel programming","title":"CUDA.@cuprintf","text":"@cuprintf(\"%Fmt\", args...)\n\nPrint a formatted string in device context on the host standard output.\n\nNote that this is not a fully C-compliant printf implementation; see the CUDA documentation for supported options and inputs.\n\nAlso beware that it is an untyped, and unforgiving printf implementation. Type widths need to match, eg. printing a 64-bit Julia integer requires the %ld formatting string.\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/#Assertions","page":"Kernel programming","title":"Assertions","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"@cuassert","category":"page"},{"location":"api/kernel/#CUDA.@cuassert","page":"Kernel programming","title":"CUDA.@cuassert","text":"@assert cond [text]\n\nSignal assertion failure to the CUDA driver if cond is false. Preferred syntax for writing assertions, mimicking Base.@assert. Message text is optionally displayed upon assertion failure.\n\nwarning: Warning\nA failed assertion will crash the GPU, so use sparingly as a debugging tool. Furthermore, the assertion might be disabled at various optimization levels, and thus should not cause any side-effects.\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/#Atomics","page":"Kernel programming","title":"Atomics","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"A high-level macro is available to annotate expressions with:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CUDA.@atomic","category":"page"},{"location":"api/kernel/#CUDA.@atomic","page":"Kernel programming","title":"CUDA.@atomic","text":"@atomic a[I] = op(a[I], val)\n@atomic a[I] ...= val\n\nAtomically perform a sequence of operations that loads an array element a[I], performs the operation op on that value and a second value val, and writes the result back to the array. This sequence can be written out as a regular assignment, in which case the same array element should be used in the left and right hand side of the assignment, or as an in-place application of a known operator. In both cases, the array reference should be pure and not induce any side-effects.\n\nwarn: Warn\nThis interface is experimental, and might change without warning. Use the lower-level atomic_...! functions for a stable API, albeit one limited to natively-supported ops.\n\n\n\n\n\n","category":"macro"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"If your expression is not recognized, or you need more control, use the underlying functions:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"CUDA.atomic_cas!\nCUDA.atomic_xchg!\nCUDA.atomic_add!\nCUDA.atomic_sub!\nCUDA.atomic_and!\nCUDA.atomic_or!\nCUDA.atomic_xor!\nCUDA.atomic_min!\nCUDA.atomic_max!\nCUDA.atomic_inc!\nCUDA.atomic_dec!","category":"page"},{"location":"api/kernel/#CUDA.atomic_cas!","page":"Kernel programming","title":"CUDA.atomic_cas!","text":"atomic_cas!(ptr::LLVMPtr{T}, cmp::T, val::T)\n\nReads the value old located at address ptr and compare with cmp. If old equals to cmp, stores val at the same address. Otherwise, doesn't change the value old. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64. Additionally, on GPU hardware with compute capability 7.0+, values of type UInt16 are supported.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_xchg!","page":"Kernel programming","title":"CUDA.atomic_xchg!","text":"atomic_xchg!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr and stores val at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_add!","page":"Kernel programming","title":"CUDA.atomic_add!","text":"atomic_add!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes old + val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32, UInt64, and Float32. Additionally, on GPU hardware with compute capability 6.0+, values of type Float64 are supported.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_sub!","page":"Kernel programming","title":"CUDA.atomic_sub!","text":"atomic_sub!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes old - val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_and!","page":"Kernel programming","title":"CUDA.atomic_and!","text":"atomic_and!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes old & val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_or!","page":"Kernel programming","title":"CUDA.atomic_or!","text":"atomic_or!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes old | val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_xor!","page":"Kernel programming","title":"CUDA.atomic_xor!","text":"atomic_xor!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes old ⊻ val, and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_min!","page":"Kernel programming","title":"CUDA.atomic_min!","text":"atomic_min!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes min(old, val), and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_max!","page":"Kernel programming","title":"CUDA.atomic_max!","text":"atomic_max!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes max(old, val), and stores the result back to memory at the same address. These operations are performed in one atomic transaction. The function returns old.\n\nThis operation is supported for values of type Int32, Int64, UInt32 and UInt64.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_inc!","page":"Kernel programming","title":"CUDA.atomic_inc!","text":"atomic_inc!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes ((old >= val) ? 0 : (old+1)), and stores the result back to memory at the same address. These three operations are performed in one atomic transaction. The function returns old.\n\nThis operation is only supported for values of type Int32.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.atomic_dec!","page":"Kernel programming","title":"CUDA.atomic_dec!","text":"atomic_dec!(ptr::LLVMPtr{T}, val::T)\n\nReads the value old located at address ptr, computes (((old == 0) | (old > val)) ? val : (old-1) ), and stores the result back to memory at the same address. These three operations are performed in one atomic transaction. The function returns old.\n\nThis operation is only supported for values of type Int32.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Dynamic-parallelism","page":"Kernel programming","title":"Dynamic parallelism","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Similarly to launching kernels from the host, you can use @cuda while passing dynamic=true for launching kernels from the device. A lower-level API is available as well:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"dynamic_cufunction\nCUDA.DeviceKernel","category":"page"},{"location":"api/kernel/#CUDA.dynamic_cufunction","page":"Kernel programming","title":"CUDA.dynamic_cufunction","text":"dynamic_cufunction(f, tt=Tuple{})\n\nLow-level interface to compile a function invocation for the currently-active GPU, returning a callable kernel object. Device-side equivalent of CUDA.cufunction.\n\nNo keyword arguments are supported.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.DeviceKernel","page":"Kernel programming","title":"CUDA.DeviceKernel","text":"(::HostKernel)(args...; kwargs...)\n(::DeviceKernel)(args...; kwargs...)\n\nLow-level interface to call a compiled kernel, passing GPU-compatible arguments in args. For a higher-level interface, use @cuda.\n\nThe following keyword arguments are supported:\n\nthreads (defaults to 1)\nblocks (defaults to 1)\nshmem (defaults to 0)\nstream (defaults to the default stream)\n\n\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA-runtime","page":"Kernel programming","title":"CUDA runtime","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Certain parts of the CUDA API are available for use on the GPU, for example to launch dynamic kernels or set-up cooperative groups. Coverage of this part of the API, provided by the libcudadevrt library, is under development and contributions are welcome.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"device_synchronize\nthis_grid\nsync_grid","category":"page"},{"location":"api/kernel/#CUDA.device_synchronize","page":"Kernel programming","title":"CUDA.device_synchronize","text":"device_synchronize()\n\nBlock for the all operations on ctx to complete. This is a heavyweight operation, typically you only need to call synchronize which only synchronizes the stream associated with the current task.\n\nOn the device, device_synchronize acts as a synchronization point for child grids in the context of dynamic parallelism.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.this_grid","page":"Kernel programming","title":"CUDA.this_grid","text":"this_grid()\n\nReturns a grid_handle of the grid group this thread belongs to. Only available if a cooperative kernel is launched.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#CUDA.sync_grid","page":"Kernel programming","title":"CUDA.sync_grid","text":"sync_grid(grid_handle::Culonglong)\n\nWaits until all threads in all blocks in the grid grid_handle have reached this point and all global memory accesses made by these threads prior to sync_grid() are visible to all threads in the grid. A 32-bit integer cudaError_t is returned.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Math","page":"Kernel programming","title":"Math","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Many mathematical functions are provided by the libdevice library, and are wrapped by CUDA.jl. These functions are used to implement well-known functions from the Julia standard library and packages like SpecialFunctions.jl, e.g., calling the cos function will automatically use __nv_cos from libdevice if possible.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Some functions do not have a counterpart in the Julia ecosystem, those have to be called directly. For example, to call __nv_logb or __nv_logbf you use CUDA.logb in a kernel.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"For a list of available functions, look at src/device/intrinsics/math.jl.","category":"page"},{"location":"api/kernel/#WMMA","page":"Kernel programming","title":"WMMA","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Warp matrix multiply-accumulate (WMMA) is a CUDA API to access Tensor Cores, a new hardware feature in Volta GPUs to perform mixed precision matrix multiply-accumulate operations. The interface is split in two levels, both available in the WMMA submodule: low level wrappers around the LLVM intrinsics, and a higher-level API similar to that of CUDA C.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"note: Note\nRequires Julia v\"1.4.0-DEV.666\" or later, or you run into LLVM errors.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"note: Note\nFor optimal performance, you should use Julia v1.5.0-DEV.324 or later.","category":"page"},{"location":"api/kernel/#Terminology","page":"Kernel programming","title":"Terminology","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The WMMA operations perform a matrix multiply-accumulate. More concretely, it calculates D = A cdot B + C, where A is a M times K matrix, B is a K times N matrix, and C and D are M times N matrices.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"However, not all values of M, N and K are allowed. The tuple (M N K) is often called the \"shape\" of the multiply accumulate operation.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The multiply-accumulate consists of the following steps:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Load the matrices A, B and C from memory to registers using a WMMA load operation.\nPerform the matrix multiply-accumulate of A, B and C to obtain D using a WMMA MMA operation. D is stored in hardware registers after this step.\nStore the result D back to memory using a WMMA store operation.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Note that WMMA is a warp-wide operation, which means that all threads in a warp must cooperate, and execute the WMMA operations in lockstep. Failure to do so will result in undefined behaviour.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Each thread in a warp will hold a part of the matrix in its registers. In WMMA parlance, this part is referred to as a \"fragment\". Note that the exact mapping between matrix elements and fragment is unspecified, and subject to change in future versions.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Finally, it is important to note that the resultant D matrix can be used as a C matrix for a subsequent multiply-accumulate. This is useful if one needs to calculate a sum of the form sum_i=0^n A_i B_i, where A_i and B_i are matrices of the correct dimension.","category":"page"},{"location":"api/kernel/#LLVM-Intrinsics","page":"Kernel programming","title":"LLVM Intrinsics","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The LLVM intrinsics are accessible by using the one-to-one Julia wrappers. The return type of each wrapper is the Julia type that corresponds closest to the return type of the LLVM intrinsic. For example, LLVM's [8 x <2 x half>] becomes NTuple{8, NTuple{2, VecElement{Float16}}} in Julia. In essence, these wrappers return the SSA values returned by the LLVM intrinsic. Currently, all intrinsics that are available in LLVM 6, PTX 6.0 and SM 70 are implemented.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"These LLVM intrinsics are then lowered to the correct PTX instructions by the LLVM NVPTX backend. For more information about the PTX instructions, please refer to the PTX Instruction Set Architecture Manual.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The LLVM intrinsics are subdivided in three categories: load, store and multiply-accumulate. In what follows, each of these will be discussed.","category":"page"},{"location":"api/kernel/#Load-matrix","page":"Kernel programming","title":"Load matrix","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.llvm_wmma_load","category":"page"},{"location":"api/kernel/#CUDA.WMMA.llvm_wmma_load","page":"Kernel programming","title":"CUDA.WMMA.llvm_wmma_load","text":"WMMA.llvm_wmma_load_{matrix}_{layout}_{shape}_{addr_space}_stride_{elem_type}(src_addr, stride)\n\nWrapper around the LLVM intrinsic @llvm.nvvm.wmma.load.{matrix}.sync.{layout}.{shape}.{addr_space}.stride.{elem_type}.\n\nArguments\n\nsrc_addr: The memory address to load from.\nstride: The leading dimension of the matrix, in numbers of elements.\n\nPlaceholders\n\n{matrix}: The matrix to load. Can be a, b or c.\n{layout}: The storage layout for the matrix. Can be row or col, for row major (C style) or column major (Julia style), respectively.\n{shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.\n{addr_space}: The address space of src_addr. Can be empty (generic addressing), shared or global.\n{elem_type}: The type of each element in the matrix. For a and b matrices, valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point). For c and d matrices, valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Perform-multiply-accumulate","page":"Kernel programming","title":"Perform multiply-accumulate","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.llvm_wmma_mma","category":"page"},{"location":"api/kernel/#CUDA.WMMA.llvm_wmma_mma","page":"Kernel programming","title":"CUDA.WMMA.llvm_wmma_mma","text":"WMMA.llvm_wmma_mma_{a_layout}_{b_layout}_{shape}_{d_elem_type}_{c_elem_type}(a, b, c) or\nWMMA.llvm_wmma_mma_{a_layout}_{b_layout}_{shape}_{a_elem_type}(a, b, c)\n\nFor floating point operations: wrapper around the LLVM intrinsic @llvm.nvvm.wmma.mma.sync.{a_layout}.{b_layout}.{shape}.{d_elem_type}.{c_elem_type} For all other operations: wrapper around the LLVM intrinsic @llvm.nvvm.wmma.mma.sync.{a_layout}.{b_layout}.{shape}.{a_elem_type}\n\nArguments\n\na: The WMMA fragment corresponding to the matrix A.\nb: The WMMA fragment corresponding to the matrix B.\nc: The WMMA fragment corresponding to the matrix C.\n\nPlaceholders\n\n{a_layout}: The storage layout for matrix A. Can be row or col, for row major (C style) or column major (Julia style), respectively. Note that this must match the layout used in the load operation.\n{b_layout}: The storage layout for matrix B. Can be row or col, for row major (C style) or column major (Julia style), respectively. Note that this must match the layout used in the load operation.\n{shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.\n{a_elem_type}: The type of each element in the A matrix. Valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point).\n{d_elem_type}: The type of each element in the resultant D matrix. Valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).\n{c_elem_type}: The type of each element in the C matrix. Valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).\n\nwarning: Warning\nRemember that the shape, type and layout of all operations (be it MMA, load or store) MUST match. Otherwise, the behaviour is undefined!\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Store-matrix","page":"Kernel programming","title":"Store matrix","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.llvm_wmma_store","category":"page"},{"location":"api/kernel/#CUDA.WMMA.llvm_wmma_store","page":"Kernel programming","title":"CUDA.WMMA.llvm_wmma_store","text":"WMMA.llvm_wmma_store_d_{layout}_{shape}_{addr_space}_stride_{elem_type}(dst_addr, data, stride)\n\nWrapper around the LLVM intrinsic @llvm.nvvm.wmma.store.d.sync.{layout}.{shape}.{addr_space}.stride.{elem_type}.\n\nArguments\n\ndst_addr: The memory address to store to.\ndata: The D fragment to store.\nstride: The leading dimension of the matrix, in numbers of elements.\n\nPlaceholders\n\n{layout}: The storage layout for the matrix. Can be row or col, for row major (C style) or column major (Julia style), respectively.\n{shape}: The overall shape of the MAC operation. Valid values are m16n16k16, m32n8k16, and m8n32k16.\n{addr_space}: The address space of src_addr. Can be empty (generic addressing), shared or global.\n{elem_type}: The type of each element in the matrix. For a and b matrices, valid values are u8 (byte unsigned integer), s8 (byte signed integer), and f16 (half precision floating point). For c and d matrices, valid values are s32 (32-bit signed integer), f16 (half precision floating point), and f32 (full precision floating point).\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Example","page":"Kernel programming","title":"Example","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"lines = readlines(\"../../../examples/wmma/low-level.jl\")\nstart = findfirst(x -> x == \"### START\", lines) + 1\nstop = findfirst(x -> x == \"### END\", lines) - 1\nexample = join(lines[start:stop], '\\n')\n\nusing Markdown\nMarkdown.parse(\"\"\"\n```julia\n$(example)\n```\n\"\"\")","category":"page"},{"location":"api/kernel/#CUDA-C-like-API","page":"Kernel programming","title":"CUDA C-like API","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The main difference between the CUDA C-like API and the lower level wrappers, is that the former enforces several constraints when working with WMMA. For example, it ensures that the A fragment argument to the MMA instruction was obtained by a load_a call, and not by a load_b or load_c. Additionally, it makes sure that the data type and storage layout of the load/store operations and the MMA operation match.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"The CUDA C-like API heavily uses Julia's dispatch mechanism. As such, the method names are much shorter than the LLVM intrinsic wrappers, as most information is baked into the type of the arguments rather than the method name.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Note that, in CUDA C++, the fragment is responsible for both the storage of intermediate results and the WMMA configuration. All CUDA C++ WMMA calls are function templates that take the resultant fragment as a by-reference argument. As a result, the type of this argument can be used during overload resolution to select the correct WMMA instruction to call.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"In contrast, the API in Julia separates the WMMA storage (WMMA.Fragment) and configuration (WMMA.Config). Instead of taking the resultant fragment by reference, the Julia functions just return it. This makes the dataflow clearer, but it also means that the type of that fragment cannot be used for selection of the correct WMMA instruction. Thus, there is still a limited amount of information that cannot be inferred from the argument types, but must nonetheless match for all WMMA operations, such as the overall shape of the MMA. This is accomplished by a separate \"WMMA configuration\" (see WMMA.Config) that you create once, and then give as an argument to all intrinsics.","category":"page"},{"location":"api/kernel/#Fragment","page":"Kernel programming","title":"Fragment","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.RowMajor\nWMMA.ColMajor\nWMMA.Unspecified\nWMMA.FragmentLayout\nWMMA.Fragment","category":"page"},{"location":"api/kernel/#CUDA.WMMA.RowMajor","page":"Kernel programming","title":"CUDA.WMMA.RowMajor","text":"WMMA.RowMajor\n\nType that represents a matrix stored in row major (C style) order.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA.WMMA.ColMajor","page":"Kernel programming","title":"CUDA.WMMA.ColMajor","text":"WMMA.ColMajor\n\nType that represents a matrix stored in column major (Julia style) order.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA.WMMA.Unspecified","page":"Kernel programming","title":"CUDA.WMMA.Unspecified","text":"WMMA.Unspecified\n\nType that represents a matrix stored in an unspecified order.\n\nwarning: Warning\nThis storage format is not valid for all WMMA operations!\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA.WMMA.FragmentLayout","page":"Kernel programming","title":"CUDA.WMMA.FragmentLayout","text":"WMMA.FragmentLayout\n\nAbstract type that specifies the storage layout of a matrix.\n\nPossible values are WMMA.RowMajor, WMMA.ColMajor and WMMA.Unspecified.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#CUDA.WMMA.Fragment","page":"Kernel programming","title":"CUDA.WMMA.Fragment","text":"WMMA.Fragment\n\nType that represents per-thread intermediate results of WMMA operations.\n\nYou can access individual elements using the x member or [] operator, but beware that the exact ordering of elements is unspecified.\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#WMMA-configuration","page":"Kernel programming","title":"WMMA configuration","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.Config","category":"page"},{"location":"api/kernel/#CUDA.WMMA.Config","page":"Kernel programming","title":"CUDA.WMMA.Config","text":"WMMA.Config{M, N, K, d_type}\n\nType that contains all information for WMMA operations that cannot be inferred from the argument's types.\n\nWMMA instructions calculate the matrix multiply-accumulate operation D = A cdot B + C, where A is a M times K matrix, B a K times N matrix, and C and D are M times N matrices.\n\nd_type refers to the type of the elements of matrix D, and can be either Float16 or Float32.\n\nAll WMMA operations take a Config as their final argument.\n\nExamples\n\njulia> config = WMMA.Config{16, 16, 16, Float32}\nCUDA.WMMA.Config{16, 16, 16, Float32}\n\n\n\n\n\n","category":"type"},{"location":"api/kernel/#Load-matrix-2","page":"Kernel programming","title":"Load matrix","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.load_a","category":"page"},{"location":"api/kernel/#CUDA.WMMA.load_a","page":"Kernel programming","title":"CUDA.WMMA.load_a","text":"WMMA.load_a(addr, stride, layout, config)\nWMMA.load_b(addr, stride, layout, config)\nWMMA.load_c(addr, stride, layout, config)\n\nLoad the matrix a, b or c from the memory location indicated by addr, and return the resulting WMMA.Fragment.\n\nArguments\n\naddr: The address to load the matrix from.\nstride: The leading dimension of the matrix pointed to by addr, specified in number of elements.\nlayout: The storage layout of the matrix. Possible values are WMMA.RowMajor and WMMA.ColMajor.\nconfig: The WMMA configuration that should be used for loading this matrix. See WMMA.Config.\n\nSee also: WMMA.Fragment, WMMA.FragmentLayout, WMMA.Config\n\nwarning: Warning\nAll threads in a warp MUST execute the load operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.load_b and WMMA.load_c have the same signature.","category":"page"},{"location":"api/kernel/#Perform-multiply-accumulate-2","page":"Kernel programming","title":"Perform multiply-accumulate","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.mma","category":"page"},{"location":"api/kernel/#CUDA.WMMA.mma","page":"Kernel programming","title":"CUDA.WMMA.mma","text":"WMMA.mma(a, b, c, conf)\n\nPerform the matrix multiply-accumulate operation D = A cdot B + C.\n\nArguments\n\na: The WMMA.Fragment corresponding to the matrix A.\nb: The WMMA.Fragment corresponding to the matrix B.\nc: The WMMA.Fragment corresponding to the matrix C.\nconf: The WMMA.Config that should be used in this WMMA operation.\n\nwarning: Warning\nAll threads in a warp MUST execute the mma operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Store-matrix-2","page":"Kernel programming","title":"Store matrix","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.store_d","category":"page"},{"location":"api/kernel/#CUDA.WMMA.store_d","page":"Kernel programming","title":"CUDA.WMMA.store_d","text":"WMMA.store_d(addr, d, stride, layout, config)\n\nStore the result matrix d to the memory location indicated by addr.\n\nArguments\n\naddr: The address to store the matrix to.\nd: The WMMA.Fragment corresponding to the d matrix.\nstride: The leading dimension of the matrix pointed to by addr, specified in number of elements.\nlayout: The storage layout of the matrix. Possible values are WMMA.RowMajor and WMMA.ColMajor.\nconfig: The WMMA configuration that should be used for storing this matrix. See WMMA.Config.\n\nSee also: WMMA.Fragment, WMMA.FragmentLayout, WMMA.Config\n\nwarning: Warning\nAll threads in a warp MUST execute the store operation in lockstep, and have to use exactly the same arguments. Failure to do so will result in undefined behaviour.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Fill-fragment","page":"Kernel programming","title":"Fill fragment","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"WMMA.fill_c","category":"page"},{"location":"api/kernel/#CUDA.WMMA.fill_c","page":"Kernel programming","title":"CUDA.WMMA.fill_c","text":"WMMA.fill_c(value, config)\n\nReturn a WMMA.Fragment filled with the value value.\n\nThis operation is useful if you want to implement a matrix multiplication (and thus want to set C = O).\n\nArguments\n\nvalue: The value used to fill the fragment. Can be a Float16 or Float32.\nconfig: The WMMA configuration that should be used for this WMMA operation. See WMMA.Config.\n\n\n\n\n\n","category":"function"},{"location":"api/kernel/#Element-access-and-broadcasting","page":"Kernel programming","title":"Element access and broadcasting","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Similar to the CUDA C++ WMMA API, WMMA.Fragments have an x member that can be used to access individual elements. Note that, in contrast to the values returned by the LLVM intrinsics, the x member is flattened. For example, while the Float16 variants of the load_a instrinsics return NTuple{8, NTuple{2, VecElement{Float16}}}, the x member has type NTuple{16, Float16}.","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"Typically, you will only need to access the x member to perform elementwise operations. This can be more succinctly expressed using Julia's broadcast mechanism. For example, to double each element in a fragment, you can simply use:","category":"page"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"frag = 2.0f0 .* frag","category":"page"},{"location":"api/kernel/#Example-2","page":"Kernel programming","title":"Example","text":"","category":"section"},{"location":"api/kernel/","page":"Kernel programming","title":"Kernel programming","text":"lines = readlines(\"../../../examples/wmma/high-level.jl\")\nstart = findfirst(x -> x == \"### START\", lines) + 1\nstop = findfirst(x -> x == \"### END\", lines) - 1\nexample = join(lines[start:stop], '\\n')\n\nusing Markdown\nMarkdown.parse(\"\"\"\n```julia\n$(example)\n```\n\"\"\")","category":"page"},{"location":"usage/multitasking/#Tasks-and-threads","page":"Tasks and threads","title":"Tasks and threads","text":"","category":"section"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"CUDA.jl can be used with Julia tasks and threads, offering a convenient way to work with multiple devices, or to perform independent computations that may execute concurrently on the GPU.","category":"page"},{"location":"usage/multitasking/#Task-based-programming","page":"Tasks and threads","title":"Task-based programming","text":"","category":"section"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"Each Julia task gets its own local CUDA execution environment, with its own stream, library handles, and active device selection. That makes it easy to use one task per device, or to use tasks for independent operations that can be overlapped. At the same time, it's important to take care when sharing data between tasks.","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"For example, let's take some dummy expensive computation and execute it from two tasks:","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"# an expensive computation\nfunction compute(a, b)\n c = a * b # library call\n broadcast!(sin, c, c) # Julia kernel\n c\nend\n\nfunction run(a, b)\n results = Vector{Any}(undef, 2)\n\n # computation\n @sync begin\n @async begin\n results[1] = Array(compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n @async begin\n results[2] = Array(compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n end\n\n # comparison\n results[1] == results[2]\nend","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"We use familiar Julia constructs to create two tasks and re-synchronize afterwards (@async and @sync), while the dummy compute function demonstrates both the use of a library (matrix multiplication uses CUBLAS) and a native Julia kernel. The function is passed three GPU arrays filled with random numbers:","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"function main(N=1024)\n a = CUDA.rand(N,N)\n b = CUDA.rand(N,N)\n\n # make sure this data can be used by other tasks!\n synchronize()\n\n run(a, b)\nend","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"The main function illustrates how we need to take care when sharing data between tasks: GPU operations typically execute asynchronously, queued on an execution stream, so if we switch tasks and thus switch execution streams we need to synchronize() to ensure the data is actually available.","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"Using Nsight Systems, we can visualize the execution of this example:","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"(Image: \"Profiling overlapping execution using multiple tasks)","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"You can see how the two invocations of compute resulted in overlapping execution. The memory copies, however, were executed in serial. This is expected: Regular CPU arrays cannot be used for asynchronous operations, because their memory is not page-locked. For most applications, this does not matter as the time to compute will typically be much larger than the time to copy memory.","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"If your application needs to perform many copies between the CPU and GPU, it might be beneficial to \"pin\" the CPU memory so that asynchronous memory copies are possible. This operation is expensive though, and should only be used if you can pre-allocate and re-use your CPU buffers. Applied to the previous example:","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"function run(a, b)\n results = Vector{Any}(undef, 2)\n\n # pre-allocate and pin destination CPU memory\n results[1] = Mem.pin(Array{eltype(a)}(undef, size(a)))\n results[2] = Mem.pin(Array{eltype(a)}(undef, size(a)))\n\n # computation\n @sync begin\n @async begin\n copyto!(results[1], compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n @async begin\n copyto!(results[2], compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n end\n\n # comparison\n results[1] == results[2]\nend","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"(Image: \"Profiling overlapping execution using multiple tasks and pinned memory)","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"The profile reveals that the memory copies themselves could not be overlapped, but the first copy was executed while the GPU was still active with the second round of computations. Furthermore, the copies executed much quicker – if the memory were unpinned, it would first have to be staged to a pinned CPU buffer anyway.","category":"page"},{"location":"usage/multitasking/#Multithreading","page":"Tasks and threads","title":"Multithreading","text":"","category":"section"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"Use of tasks can be easily extended to multiple threads with functionality from the Threads standard library:","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"function run(a, b)\n results = Vector{Any}(undef, 2)\n\n # computation\n @sync begin\n Threads.@spawn begin\n results[1] = Array(compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n Threads.@spawn begin\n results[2] = Array(compute(a,b))\n nothing # JuliaLang/julia#40626\n end\n end\n\n # comparison\n results[1] == results[2]\nend","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"By using the Threads.@spawn macro, the tasks will be scheduled to be run on different CPU threads. This can be useful when you are calling a lot of operations that \"block\" in CUDA, e.g., memory copies to or from unpinned memory. Generally though, operations that synchronize GPU execution (including the call to synchronize itself) are implemented in a way that they yield back to the Julia scheduler, to enable concurrent execution without requiring the use of different CPU threads.","category":"page"},{"location":"usage/multitasking/","page":"Tasks and threads","title":"Tasks and threads","text":"warning: Warning\nUse of multiple threads with CUDA.jl is a recent addition, and there may still be bugs or performance issues.","category":"page"},{"location":"api/array/#Array-programming","page":"Array programming","title":"Array programming","text":"","category":"section"},{"location":"api/array/","page":"Array programming","title":"Array programming","text":"The CUDA array type, CuArray, generally implements the Base array interface and all of its expected methods.","category":"page"},{"location":"usage/multigpu/#Multiple-GPUs","page":"Multiple GPUs","title":"Multiple GPUs","text":"","category":"section"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"There are different ways of working with multiple GPUs: using one or more tasks, processes, or systems. Although all of these are compatible with the Julia CUDA toolchain, the support is a work in progress and the usability of some combinations can be significantly improved.","category":"page"},{"location":"usage/multigpu/#Scenario-1:-One-GPU-per-process","page":"Multiple GPUs","title":"Scenario 1: One GPU per process","text":"","category":"section"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"The easiest solution that maps well onto Julia's existing facilities for distributed programming, is to use one GPU per process","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"# spawn one worker per device\nusing Distributed, CUDA\naddprocs(length(devices()))\n@everywhere using CUDA\n\n# assign devices\nasyncmap((zip(workers(), devices()))) do (p, d)\n remotecall_wait(p) do\n @info \"Worker $p uses $d\"\n device!(d)\n end\nend","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"Communication between nodes should happen via the CPU (the CUDA IPC APIs are available as CUDA.cuIpcOpenMemHandle and friends, but not available through high-level wrappers).","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"Alternatively, one can use MPI.jl together with an CUDA-aware MPI implementation. In that case, CuArray objects can be passed as send and receive buffers to point-to-point and collective operations to avoid going through the CPU.","category":"page"},{"location":"usage/multigpu/#Scenario-2:-Multiple-GPUs-per-process","page":"Multiple GPUs","title":"Scenario 2: Multiple GPUs per process","text":"","category":"section"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"In a similar vein to the multi-process solution, one can work with multiple devices from within a single process by calling CUDA.device! to switch to a specific device. Furthermore, as the active device is a task-local property you can easily work with multiple devices using one task per device. For more details, refer to the section on Tasks and threads.","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"warning: Warning\nYou currently need to re-set the device at the start of every task, i.e., call device! as one of the first statement in your @async or @spawn block:@sync begin\n @async begin\n device!(0)\n # do work on GPU 0 here\n end\n @async begin\n device!(1)\n # do work on GPU 1 here\n end\nendWithout this, the newly-created task would use the same device as the previously-executing task, and not the parent task as could be expected. This is expected to be improved in the future using context variables.","category":"page"},{"location":"usage/multigpu/#Memory-management","page":"Multiple GPUs","title":"Memory management","text":"","category":"section"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"When working with multiple devices, you need to be careful with allocated memory: Allocations are tied to the device that was active when requesting the memory, and cannot be used with another device. That means you cannot allocate a CuArray, switch devices, and use that object. Similar restrictions apply to library objects, like CUFFT plans.","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"To avoid this difficulty, you can use unified memory that is accessible from all devices. These APIs are available through high-level wrappers, but not exposed by the CuArray constructors yet:","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"using CUDA\n\ngpus = Int(length(devices()))\n\n# generate CPU data\ndims = (3,4,gpus)\na = round.(rand(Float32, dims) * 100)\nb = round.(rand(Float32, dims) * 100)\n\n# CuArray doesn't support unified memory yet,\n# so allocate our own buffers\nbuf_a = Mem.alloc(Mem.Unified, sizeof(a))\nd_a = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_a), dims)\nfinalizer(d_a) do _\n Mem.free(buf_a)\nend\ncopyto!(d_a, a)\n\nbuf_b = Mem.alloc(Mem.Unified, sizeof(b))\nd_b = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_b), dims)\nfinalizer(d_b) do _\n Mem.free(buf_b)\nend\ncopyto!(d_b, b)\n\nbuf_c = Mem.alloc(Mem.Unified, sizeof(a))\nd_c = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_c), dims)\nfinalizer(d_c) do _\n Mem.free(buf_c)\nend","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"The data allocated here uses the GPU id as a the outermost dimension, which can be used to extract views of contiguous memory that represent the slice to be processed by a single GPU:","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"for (gpu, dev) in enumerate(devices())\n device!(dev)\n @views d_c[:, :, gpu] .= d_a[:, :, gpu] .+ d_b[:, :, gpu]\nend","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"Before downloading the data, make sure to synchronize the devices:","category":"page"},{"location":"usage/multigpu/","page":"Multiple GPUs","title":"Multiple GPUs","text":"for dev in devices()\n # NOTE: normally you'd use events and wait for them\n device!(dev)\n synchronize()\nend\n\nusing Test\nc = Array(d_c)\n@test a+b ≈ c","category":"page"},{"location":"api/essentials/#Essentials","page":"Essentials","title":"Essentials","text":"","category":"section"},{"location":"api/essentials/#Initialization","page":"Essentials","title":"Initialization","text":"","category":"section"},{"location":"api/essentials/","page":"Essentials","title":"Essentials","text":"CUDA.functional(::Bool)\nhas_cuda\nhas_cuda_gpu","category":"page"},{"location":"api/essentials/#CUDA.functional-Tuple{Bool}","page":"Essentials","title":"CUDA.functional","text":"functional(show_reason=false)\n\nCheck if the package has been configured successfully and is ready to use.\n\nThis call is intended for packages that support conditionally using an available GPU. If you fail to check whether CUDA is functional, actual use of functionality might warn and error.\n\n\n\n\n\n","category":"method"},{"location":"api/essentials/#CUDA.has_cuda","page":"Essentials","title":"CUDA.has_cuda","text":"has_cuda()::Bool\n\nCheck whether the local system provides an installation of the CUDA driver and runtime. Use this function if your code loads packages that require CUDA.jl. ```\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.has_cuda_gpu","page":"Essentials","title":"CUDA.has_cuda_gpu","text":"has_cuda_gpu()::Bool\n\nCheck whether the local system provides an installation of the CUDA driver and runtime, and if it contains a CUDA-capable GPU. See has_cuda for more details.\n\nNote that this function initializes the CUDA API in order to check for the number of GPUs.\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#Global-state","page":"Essentials","title":"Global state","text":"","category":"section"},{"location":"api/essentials/","page":"Essentials","title":"Essentials","text":"context\ncontext!\ndevice\ndevice!\ndevice_reset!\nstream\nstream!","category":"page"},{"location":"api/essentials/#CUDA.context","page":"Essentials","title":"CUDA.context","text":"context(ptr)\n\nIdentify the context a CUDA memory buffer was allocated in.\n\n\n\n\n\ncontext()::CuContext\n\nGet or create a CUDA context for the current thread (as opposed to current_context which may return nothing if there is no context bound to the current thread).\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.context!","page":"Essentials","title":"CUDA.context!","text":"context!(ctx::CuContext)\ncontext!(ctx::CuContext) do ... end\n\nBind the current host thread to the context ctx. Returns the previously-bound context. If used with do-block syntax, the change is only temporary.\n\nNote that the contexts used with this call should be previously acquired by calling context, and not arbitrary contexts created by calling the CuContext constructor.\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.device","page":"Essentials","title":"CUDA.device","text":"device(::CuContext)\n\nReturns the device for a context.\n\n\n\n\n\ndevice(ptr)\n\nIdentify the device a CUDA memory buffer was allocated on.\n\n\n\n\n\ndevice()::CuDevice\n\nGet the CUDA device for the current thread, similar to how context() works compared to current_context().\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.device!","page":"Essentials","title":"CUDA.device!","text":"device!(dev::Integer)\ndevice!(dev::CuDevice)\ndevice!(dev) do ... end\n\nSets dev as the current active device for the calling host thread. Devices can be specified by integer id, or as a CuDevice (slightly faster). Both functions can be used with do-block syntax, in which case the device is only changed temporarily, without changing the default device used to initialize new threads or tasks.\n\nCalling this function at the start of a session will make sure CUDA is initialized (i.e., a primary context will be created and activated).\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.device_reset!","page":"Essentials","title":"CUDA.device_reset!","text":"device_reset!(dev::CuDevice=device())\n\nReset the CUDA state associated with a device. This call with release the underlying context, at which point any objects allocated in that context will be invalidated.\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.stream","page":"Essentials","title":"CUDA.stream","text":"stream()\n\nGet the CUDA stream that should be used as the default one for the currently executing task.\n\n\n\n\n\n","category":"function"},{"location":"api/essentials/#CUDA.stream!","page":"Essentials","title":"CUDA.stream!","text":"stream!(::CuStream)\nstream!(::CuStream) do ... end\n\nChange the default CUDA stream for the currently executing task, temporarily if using the do-block version of this function.\n\n\n\n\n\n","category":"function"},{"location":"faq/#Frequently-Asked-Questions","page":"FAQ","title":"Frequently Asked Questions","text":"","category":"section"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"This page is a compilation of frequently asked questions and answers.","category":"page"},{"location":"faq/#An-old-version-of-CUDA.jl-keeps-getting-installed!","page":"FAQ","title":"An old version of CUDA.jl keeps getting installed!","text":"","category":"section"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"Sometimes it happens that a breaking version of CUDA.jl or one of its dependencies is released. If any package you use isn't yet compatible with this release, this will block automatic upgrade of CUDA.jl. For example, with Flux.jl v0.11.1 we get CUDA.jl v1.3.3 despite there being a v2.x release:","category":"page"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"pkg> add Flux\n [587475ba] + Flux v0.11.1\npkg> add CUDA\n [052768ef] + CUDA v1.3.3","category":"page"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"To examine which package is holding back CUDA.jl, you can \"force\" an upgrade by specifically requesting a newer version. The resolver will then complain, and explain why this upgrade isn't possible:","category":"page"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"pkg> add CUDA.jl@2\n Resolving package versions...\nERROR: Unsatisfiable requirements detected for package Adapt [79e6a3ab]:\n Adapt [79e6a3ab] log:\n ├─possible versions are: [0.3.0-0.3.1, 0.4.0-0.4.2, 1.0.0-1.0.1, 1.1.0, 2.0.0-2.0.2, 2.1.0, 2.2.0, 2.3.0] or uninstalled\n ├─restricted by compatibility requirements with CUDA [052768ef] to versions: [2.2.0, 2.3.0]\n │ └─CUDA [052768ef] log:\n │ ├─possible versions are: [0.1.0, 1.0.0-1.0.2, 1.1.0, 1.2.0-1.2.1, 1.3.0-1.3.3, 2.0.0-2.0.2] or uninstalled\n │ └─restricted to versions 2 by an explicit requirement, leaving only versions 2.0.0-2.0.2\n └─restricted by compatibility requirements with Flux [587475ba] to versions: [0.3.0-0.3.1, 0.4.0-0.4.2, 1.0.0-1.0.1, 1.1.0] — no versions left\n └─Flux [587475ba] log:\n ├─possible versions are: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4, 0.11.0-0.11.1] or uninstalled\n ├─restricted to versions * by an explicit requirement, leaving only versions [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4, 0.11.0-0.11.1]\n └─restricted by compatibility requirements with CUDA [052768ef] to versions: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4] or uninstalled, leaving only versions: [0.4.1, 0.5.0-0.5.4, 0.6.0-0.6.10, 0.7.0-0.7.3, 0.8.0-0.8.3, 0.9.0, 0.10.0-0.10.4]\n └─CUDA [052768ef] log: see above","category":"page"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"A common source of these incompatibilities is having both CUDA.jl and the older CUDAnative.jl/CuArrays.jl/CUDAdrv.jl stack installed: These are incompatible, and cannot coexist. You can inspect in the Pkg REPL which exact packages you have installed using the status --manifest option.","category":"page"},{"location":"faq/#Can-you-wrap-this-or-that-CUDA-API?","page":"FAQ","title":"Can you wrap this or that CUDA API?","text":"","category":"section"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"If a certain API isn't wrapped with some high-level functionality, you can always use the underlying C APIs which are always available as unexported methods. For example, you can access the CUDA driver library as cu prefixed, unexported functions like CUDA.cuDriverGetVersion. Similarly, vendor libraries like CUBLAS are available through their exported submodule handles, e.g., CUBLAS.cublasGetVersion_v2.","category":"page"},{"location":"faq/","page":"FAQ","title":"FAQ","text":"Any help on designing or implementing high-level wrappers for this low-level functionality is greatly appreciated, so please consider contributing your uses of these APIs on the respective repositories.","category":"page"},{"location":"development/profiling/#Profiling","page":"Profiling","title":"Profiling","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Profiling GPU code is harder than profiling Julia code executing on the CPU. For one, kernels typically execute asynchronously, and thus require appropriate synchronization when measuring their execution time. Furthermore, because the code executes on a different processor, it is much harder to know what is currently executing. CUDA, and the Julia CUDA packages, provide several tools and APIs to remedy this.","category":"page"},{"location":"development/profiling/#Time-measurements","page":"Profiling","title":"Time measurements","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"To accurately measure execution time in the presence of asynchronously-executing kernels, CUDA.jl provides an @elapsed macro that, much like Base.@elapsed, measures the total execution time of a block of code on the GPU:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> a = CUDA.rand(1024,1024,1024);\n\njulia> Base.@elapsed sin.(a) # WRONG!\n0.008714211\n\njulia> CUDA.@elapsed sin.(a)\n0.051607586f0","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"This is a low-level utility, and measures time by submitting events to the GPU and measuring the time between them. As such, if the GPU was not idle in the first place, you may not get the expected result. The macro is mainly useful if your application needs to know about the time it took to complete certain GPU operations.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"For more convenient time reporting, you can use the CUDA.@time macro which mimics Base.@time by printing execution times as well as memory allocation stats, while making sure the GPU is idle before starting the measurement, as well as waiting for all asynchronous operations to complete:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> a = CUDA.rand(1024,1024,1024);\n\njulia> CUDA.@time sin.(a);\n 0.046063 seconds (96 CPU allocations: 3.750 KiB) (1 GPU allocation: 4.000 GiB, 14.33% gc time of which 99.89% spent allocating)","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"The @time macro is more user-friendly and is a generally more useful tool when measuring the end-to-end performance characteristics of a GPU application.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"For robust measurements however, it is advised to use the BenchmarkTools.jl package which goes to great lengths to perform accurate measurements. Due to the asynchronous nature of GPUs, you need to ensure the GPU is synchronized at the end of every sample, e.g. by calling synchronize() or, even better, wrapping your code in CUDA.@sync:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> a = CUDA.rand(1024,1024,1024);\n\njulia> @benchmark CUDA.@sync sin.($a)\nBenchmarkTools.Trial:\n memory estimate: 3.73 KiB\n allocs estimate: 95\n --------------\n minimum time: 46.341 ms (0.00% GC)\n median time: 133.302 ms (0.50% GC)\n mean time: 130.087 ms (0.49% GC)\n maximum time: 153.465 ms (0.43% GC)\n --------------\n samples: 39\n evals/sample: 1","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Note that the allocations as reported by BenchmarkTools are CPU allocations. For the GPU allocation behavior you need to consult CUDA.@time.","category":"page"},{"location":"development/profiling/#Application-profiling","page":"Profiling","title":"Application profiling","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"For profiling large applications, simple timings are insufficient. Instead, we want a overview of how and when the GPU was active, to avoid times where the device was idle and/or find which kernels needs optimization.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"As we cannot use the Julia profiler for this task, we will be using external profiling software as part of the CUDA toolkit. To inform those external tools which code needs to be profiled (e.g., to exclude warm-up iterations or other noninteresting elements) you can use the CUDA.@profile macro to surround interesting code with. Again, this macro mimics an equivalent from the standard library, but this time requires external software to actually perform the profiling:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> a = CUDA.rand(1024,1024,1024);\n\njulia> sin.(a); # warmup\n\njulia> CUDA.@profile sin.(a);\n┌ Warning: Calling CUDA.@profile only informs an external profiler to start.\n│ The user is responsible for launching Julia under a CUDA profiler like `nvprof`.\n└ @ CUDA.Profile ~/Julia/pkg/CUDA/src/profile.jl:42","category":"page"},{"location":"development/profiling/#nvprof-and-nvvp","page":"Profiling","title":"nvprof and nvvp","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"warning: Warning\nThese tools are deprecated, and will be removed from future versions of CUDA. Prefer to use the Nsight tools described below.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"For simple profiling, prefix your Julia command-line invocation with the nvprof utility. For a better timeline, be sure to use CUDA.@profile to delimit interesting code and start nvprof with the option --profile-from-start off:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"$ nvprof --profile-from-start off julia\n\njulia> using CUDA\n\njulia> a = CUDA.rand(1024,1024,1024);\n\njulia> sin.(a);\n\njulia> CUDA.@profile sin.(a);\n\njulia> exit()\n==156406== Profiling application: julia\n==156406== Profiling result:\n Type Time(%) Time Calls Avg Min Max Name\n GPU activities: 100.00% 44.777ms 1 44.777ms 44.777ms 44.777ms ptxcall_broadcast_1\n API calls: 56.46% 6.6544ms 1 6.6544ms 6.6544ms 6.6544ms cuMemAlloc\n 43.52% 5.1286ms 1 5.1286ms 5.1286ms 5.1286ms cuLaunchKernel\n 0.01% 1.3200us 1 1.3200us 1.3200us 1.3200us cuDeviceGetCount\n 0.01% 725ns 3 241ns 196ns 301ns cuCtxGetCurrent","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"info: Info\nIf nvprof crashes, reporting that the application returned non-zero code 12, try starting nvprof with --openacc-profiling off.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"For a visual overview of these results, you can use the NVIDIA Visual Profiler (nvvp):","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"(Image: \"NVIDIA Visual Profiler\")","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Note however that both nvprof and nvvp are deprecated, and will be removed from future versions of the CUDA toolkit.","category":"page"},{"location":"development/profiling/#NVIDIA-Nsight-Systems","page":"Profiling","title":"NVIDIA Nsight Systems","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Following the deprecation of above tools, NVIDIA published the Nsight Systems and Nsight Compute tools for respectively timeline profiling and more detailed kernel analysis. The former is well-integrated with the Julia GPU packages, and makes it possible to iteratively profile without having to restart Julia as was the case with nvvp and nvprof.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"After downloading and installing NSight Systems (a version might have been installed alongside with the CUDA toolkit, but it is recommended to download and install the latest version from the NVIDIA website), you need to launch Julia from the command-line, wrapped by the nsys utility from NSight Systems:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"$ nsys launch julia","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"You can then execute whatever code you want in the REPL, including e.g. loading Revise so that you can modify your application as you go. When you call into code that is wrapped by CUDA.@profile, the profiler will become active and generate a profile output file in the current folder:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> using CUDA\n\njulia> a = CUDA.rand(1024,1024,1024);\n\njulia> sin.(a);\n\njulia> CUDA.@profile sin.(a);\nstart executed\nProcessing events...\nCapturing symbol files...\nSaving intermediate \"report.qdstrm\" file to disk...\n\nImporting [===============================================================100%]\nSaved report file to \"report.qdrep\"\nstop executed","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"note: Note\nEven with a warm-up iteration, the first kernel or API call might seem to take significantly longer in the profiler. If you are analyzing short executions, instead of whole applications, repeat the operation twice (optionally separated by a call to synchronize() or wrapping in CUDA.@sync)","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"You can open the resulting .qdrep file with nsight-sys:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"(Image: \"NVIDIA Nsight Systems\")","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"info: Info\nIf NSight Systems does not capture any kernel launch, even though you have used CUDA.@profile, try starting nsys with --trace cuda.","category":"page"},{"location":"development/profiling/#NVIDIA-Nsight-Compute","page":"Profiling","title":"NVIDIA Nsight Compute","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"If you want details on the execution properties of a kernel, or inspect API interactions, Nsight Compute is the tool for you. It is again possible to use this profiler with an interactive session of Julia, and debug or profile only those sections of your application that are marked with CUDA.@profile.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Start with launching Julia under the Nsight Compute CLI tool:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"$ ncu --mode=launch julia","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"You will get an interactive REPL, where you can execute whatever code you want:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> using CUDA\n\njulia> CUDA.driver_version()\n\n# Julia hangs!","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"As soon as you use CUDA.jl, your Julia process will hang. This is expected, as the tool breaks upon the very first call to the CUDA API, at which point you are expected to launch the Nsight Compute GUI utility and attach to the running session:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"(Image: \"NVIDIA Nsight Compute - Attaching to a session\")","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"You will see that the tool has stopped execution on the call to cuInit. Now check Profile > Auto Profile to make Nsight Compute gather statistics on our kernels, and clock Debug > Resume to resume your session.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Now our CLI session comes to life again, and we can enter the rest of our script:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"julia> a = CUDA.rand(1024,1024,1024);\n\njulia> sin.(a);\n\njulia> CUDA.@profile sin.(a);","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Once that's finished, the Nsight Compute GUI window will have plenty details on our kernel:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"(Image: \"NVIDIA Nsight Compute - Kernel profiling\")","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"At any point in time, you can also pause your application from the debug menu, and inspect the API calls that have been made:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"(Image: \"NVIDIA Nsight Compute - API inspection\")","category":"page"},{"location":"development/profiling/#Source-code-annotations","page":"Profiling","title":"Source-code annotations","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"If you want to put additional information in the profile, e.g. phases of your application, or expensive CPU operations, you can use the NVTX library via the NVTX.jl package:","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"using CUDA, NVTX\n\nNVTX.@range \"doing X\" begin\n ...\nend\n\nNVTX.@mark \"reached Y\"","category":"page"},{"location":"development/profiling/#Compiler-options","page":"Profiling","title":"Compiler options","text":"","category":"section"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"Some tools, like nvvp and NSight Systems Compute, also make it possible to do source-level profiling. CUDA.jl will by default emit the necessary source line information, which you can disable by launching Julia with -g0. Conversely, launching with -g2 will emit additional debug information, which can be useful in combination with tools like cuda-gdb, but might hurt performance or code size.","category":"page"},{"location":"development/profiling/","page":"Profiling","title":"Profiling","text":"warning: Warning\nDue to bugs in LLVM and CUDA, debug info emission is unavailable in Julia 1.4 and higher.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"EditURL = \"https://github.com/JuliaGPU/CUDA.jl/blob/master/docs/src/tutorials/introduction.jl\"","category":"page"},{"location":"tutorials/introduction/#Introduction","page":"Introduction","title":"Introduction","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"A gentle introduction to parallelization and GPU programming in Julia","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Julia has first-class support for GPU programming: you can use high-level abstractions or obtain fine-grained control, all without ever leaving your favorite programming language. The purpose of this tutorial is to help Julia users take their first step into GPU computing. In this tutorial, you'll compare CPU and GPU implementations of a simple calculation, and learn about a few of the factors that influence the performance you obtain.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"This tutorial is inspired partly by a blog post by Mark Harris, An Even Easier Introduction to CUDA, which introduced CUDA using the C++ programming language. You do not need to read that tutorial, as this one starts from the beginning.","category":"page"},{"location":"tutorials/introduction/#A-simple-example-on-the-CPU","page":"Introduction","title":"A simple example on the CPU","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"We'll consider the following demo, a simple calculation on the CPU.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"N = 2^20\nx = fill(1.0f0, N) # a vector filled with 1.0 (Float32)\ny = fill(2.0f0, N) # a vector filled with 2.0\n\ny .+= x # increment each element of y with the corresponding element of x","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"check that we got the right answer","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"using Test\n@test all(y .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"From the Test Passed line we know everything is in order. We used Float32 numbers in preparation for the switch to GPU computations: GPUs are faster (sometimes, much faster) when working with Float32 than with Float64.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"A distinguishing feature of this calculation is that every element of y is being updated using the same operation. This suggests that we might be able to parallelize this.","category":"page"},{"location":"tutorials/introduction/#Parallelization-on-the-CPU","page":"Introduction","title":"Parallelization on the CPU","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"First let's do the parallelization on the CPU. We'll create a \"kernel function\" (the computational core of the algorithm) in two implementations, first a sequential version:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function sequential_add!(y, x)\n for i in eachindex(y, x)\n @inbounds y[i] += x[i]\n end\n return nothing\nend\n\nfill!(y, 2)\nsequential_add!(y, x)\n@test all(y .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"And now a parallel implementation:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function parallel_add!(y, x)\n Threads.@threads for i in eachindex(y, x)\n @inbounds y[i] += x[i]\n end\n return nothing\nend\n\nfill!(y, 2)\nparallel_add!(y, x)\n@test all(y .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Now if I've started Julia with JULIA_NUM_THREADS=4 on a machine with at least 4 cores, I get the following:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"using BenchmarkTools\n@btime sequential_add!($y, $x)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 487.303 μs (0 allocations: 0 bytes)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"versus","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime parallel_add!($y, $x)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 259.587 μs (13 allocations: 1.48 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"You can see there's a performance benefit to parallelization, though not by a factor of 4 due to the overhead for starting threads. With larger arrays, the overhead would be \"diluted\" by a larger amount of \"real work\"; these would demonstrate scaling that is closer to linear in the number of cores. Conversely, with small arrays, the parallel version might be slower than the serial version.","category":"page"},{"location":"tutorials/introduction/#Your-first-GPU-computation","page":"Introduction","title":"Your first GPU computation","text":"","category":"section"},{"location":"tutorials/introduction/#Installation","page":"Introduction","title":"Installation","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"For most of this tutorial you need to have a computer with a compatible GPU and have installed CUDA. You should also install the following packages using Julia's package manager:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"pkg> add CUDA","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"If this is your first time, it's not a bad idea to test whether your GPU is working by testing the CUDA.jl package:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"pkg> add CUDA\npkg> test CUDA","category":"page"},{"location":"tutorials/introduction/#Parallelization-on-the-GPU","page":"Introduction","title":"Parallelization on the GPU","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"We'll first demonstrate GPU computations at a high level using the CuArray type, without explicitly writing a kernel function:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"using CUDA\n\nx_d = CUDA.fill(1.0f0, N) # a vector stored on the GPU filled with 1.0 (Float32)\ny_d = CUDA.fill(2.0f0, N) # a vector stored on the GPU filled with 2.0","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Here the d means \"device,\" in contrast with \"host\". Now let's do the increment:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"y_d .+= x_d\n@test all(Array(y_d) .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The statement Array(y_d) moves the data in y_d back to the host for testing. If we want to benchmark this, let's put it in a function:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function add_broadcast!(y, x)\n CUDA.@sync y .+= x\n return\nend","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime add_broadcast!($y_d, $x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 67.047 μs (84 allocations: 2.66 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The most interesting part of this is the call to CUDA.@sync. The CPU can assign jobs to the GPU and then go do other stuff (such as assigning more jobs to the GPU) while the GPU completes its tasks. Wrapping the execution in a CUDA.@sync block will make the CPU block until the queued GPU tasks are done, similar to how Base.@sync waits for distributed CPU tasks. Without such synchronization, you'd be measuring the time takes to launch the computation, not the time to perform the computation. But most of the time you don't need to synchronize explicitly: many operations, like copying memory from the GPU to the CPU, implicitly synchronize execution.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"For this particular computer and GPU, you can see the GPU computation was significantly faster than the single-threaded CPU computation, and that the use of multiple CPU threads makes the CPU implementation competitive. Depending on your hardware you may get different results.","category":"page"},{"location":"tutorials/introduction/#Writing-your-first-GPU-kernel","page":"Introduction","title":"Writing your first GPU kernel","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Using the high-level GPU array functionality made it easy to perform this computation on the GPU. However, we didn't learn about what's going on under the hood, and that's the main goal of this tutorial. So let's implement the same functionality with a GPU kernel:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function gpu_add1!(y, x)\n for i = 1:length(y)\n @inbounds y[i] += x[i]\n end\n return nothing\nend\n\nfill!(y_d, 2)\n@cuda gpu_add1!(y_d, x_d)\n@test all(Array(y_d) .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Aside from using the CuArrays x_d and y_d, the only GPU-specific part of this is the kernel launch via @cuda. The first time you issue this @cuda statement, it will compile the kernel (gpu_add1!) for execution on the GPU. Once compiled, future invocations are fast. You can see what @cuda expands to using ?@cuda from the Julia prompt.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Let's benchmark this:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function bench_gpu1!(y, x)\n CUDA.@sync begin\n @cuda gpu_add1!(y, x)\n end\nend","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime bench_gpu1!($y_d, $x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 119.783 ms (47 allocations: 1.23 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"That's a lot slower than the version above based on broadcasting. What happened?","category":"page"},{"location":"tutorials/introduction/#Profiling","page":"Introduction","title":"Profiling","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"When you don't get the performance you expect, usually your first step should be to profile the code and see where it's spending its time. For that, you'll need to be able to run NVIDIA's nvprof tool. On Unix systems, launch Julia this way:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"$ nvprof --profile-from-start off --openacc-profiling off /path/to/julia","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"replacing the /path/to/julia with the path to your Julia binary. Note that we don't immediately start the profiler, but instead call into the CUDA APIs and manually start the profiler with CUDA.@profile (thus excluding the time to compile our kernel):","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"bench_gpu1!(y_d, x_d) # run it once to force compilation\nCUDA.@profile bench_gpu1!(y_d, x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"When we quit the Julia REPL, the profiler process will print information about the executed kernels and API calls:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"==2574== Profiling result:\n Type Time(%) Time Calls Avg Min Max Name\n GPU activities: 100.00% 247.61ms 1 247.61ms 247.61ms 247.61ms ptxcall_gpu_add1__1\n API calls: 99.54% 247.83ms 1 247.83ms 247.83ms 247.83ms cuEventSynchronize\n 0.46% 1.1343ms 1 1.1343ms 1.1343ms 1.1343ms cuLaunchKernel\n 0.00% 4.9490us 1 4.9490us 4.9490us 4.9490us cuEventRecord\n 0.00% 4.4190us 1 4.4190us 4.4190us 4.4190us cuEventCreate\n 0.00% 960ns 2 480ns 358ns 602ns cuCtxGetCurrent","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"You can see that 100% of the time was spent in ptxcall_gpu_add1__1, the name of the kernel that CUDA.jl assigned when compiling gpu_add1! for these inputs. (Had you created arrays of multiple data types, e.g., xu_d = CUDA.fill(0x01, N), you might have also seen ptxcall_gpu_add1__2 and so on. Like the rest of Julia, you can define a single method and it will be specialized at compile time for the particular data types you're using.)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"For further insight, run the profiling with the option --print-gpu-trace. You can also invoke Julia with as argument the path to a file containing all commands you want to run (including a call to CUDA.@profile):","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"$ nvprof --profile-from-start off --openacc-profiling off --print-gpu-trace /path/to/julia /path/to/script.jl\n Start Duration Grid Size Block Size Regs* SSMem* DSMem* Device Context Stream Name\n 13.3134s 245.04ms (1 1 1) (1 1 1) 20 0B 0B GeForce GTX TIT 1 7 ptxcall_gpu_add1__1 [34]","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The key thing to note here is the (1 1 1) in the \"Grid Size\" and \"Block Size\" columns. These terms will be explained shortly, but for now, suffice it to say that this is an indication that this computation ran sequentially. Of note, sequential processing with GPUs is much slower than with CPUs; where GPUs shine is with large-scale parallelism.","category":"page"},{"location":"tutorials/introduction/#Writing-a-parallel-GPU-kernel","page":"Introduction","title":"Writing a parallel GPU kernel","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"To speed up the kernel, we want to parallelize it, which means assigning different tasks to different threads. To facilitate the assignment of work, each CUDA thread gets access to variables that indicate its own unique identity, much as Threads.threadid() does for CPU threads. The CUDA analogs of threadid and nthreads are called threadIdx and blockDim, respectively; one difference is that these return a 3-dimensional structure with fields x, y, and z to simplify cartesian indexing for up to 3-dimensional arrays. Consequently we can assign unique work in the following way:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function gpu_add2!(y, x)\n index = threadIdx().x # this example only requires linear indexing, so just use `x`\n stride = blockDim().x\n for i = index:stride:length(y)\n @inbounds y[i] += x[i]\n end\n return nothing\nend\n\nfill!(y_d, 2)\n@cuda threads=256 gpu_add2!(y_d, x_d)\n@test all(Array(y_d) .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Note the threads=256 here, which divides the work among 256 threads numbered in a linear pattern. (For a two-dimensional array, we might have used threads=(16, 16) and then both x and y would be relevant.)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Now let's try benchmarking it:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function bench_gpu2!(y, x)\n CUDA.@sync begin\n @cuda threads=256 gpu_add2!(y, x)\n end\nend","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime bench_gpu2!($y_d, $x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 1.873 ms (47 allocations: 1.23 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Much better!","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"But obviously we still have a ways to go to match the initial broadcasting result. To do even better, we need to parallelize more. GPUs have a limited number of threads they can run on a single streaming multiprocessor (SM), but they also have multiple SMs. To take advantage of them all, we need to run a kernel with multiple blocks. We'll divide up the work like this:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"(Image: block grid)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"This diagram was borrowed from a description of the C/C++ library; in Julia, threads and blocks begin numbering with 1 instead of 0. In this diagram, the 4096 blocks of 256 threads (making 1048576 = 2^20 threads) ensures that each thread increments just a single entry; however, to ensure that arrays of arbitrary size can be handled, let's still use a loop:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function gpu_add3!(y, x)\n index = (blockIdx().x - 1) * blockDim().x + threadIdx().x\n stride = gridDim().x * blockDim().x\n for i = index:stride:length(y)\n @inbounds y[i] += x[i]\n end\n return\nend\n\nnumblocks = ceil(Int, N/256)\n\nfill!(y_d, 2)\n@cuda threads=256 blocks=numblocks gpu_add3!(y_d, x_d)\n@test all(Array(y_d) .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The benchmark:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function bench_gpu3!(y, x)\n numblocks = ceil(Int, length(y)/256)\n CUDA.@sync begin\n @cuda threads=256 blocks=numblocks gpu_add3!(y, x)\n end\nend","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime bench_gpu3!($y_d, $x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 67.268 μs (52 allocations: 1.31 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Finally, we've achieved the similar performance to what we got with the broadcasted version. Let's run nvprof again to confirm this launch configuration:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"==23972== Profiling result:\n Start Duration Grid Size Block Size Regs* SSMem* DSMem* Device Context Stream Name\n13.3526s 101.22us (4096 1 1) (256 1 1) 32 0B 0B GeForce GTX TIT 1 7 ptxcall_gpu_add3__1 [34]","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"In the previous example, the number of threads was hard-coded to 256. This is not ideal, as using more threads generally improves performance, but the maximum number of allowed threads to launch depends on your GPU as well as on the kernel. To automatically select an appropriate number of threads, it is recommended to use the launch configuration API. This API takes a compiled (but not launched) kernel, returns a tuple with an upper bound on the number of threads, and the minimum number of blocks that are required to fully saturate the GPU:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"kernel = @cuda launch=false gpu_add3!(y_d, x_d)\nconfig = launch_configuration(kernel.fun)\nthreads = min(N, config.threads)\nblocks = cld(N, threads)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The compiled kernel is callable, and we can pass the computed launch configuration as keyword arguments:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"fill!(y_d, 2)\nkernel(y_d, x_d; threads, blocks)\n@test all(Array(y_d) .== 3.0f0)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Now let's benchmark this:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function bench_gpu4!(y, x)\n kernel = @cuda launch=false gpu_add3!(y, x)\n config = launch_configuration(kernel.fun)\n threads = min(length(y), config.threads)\n blocks = cld(length(y), threads)\n\n CUDA.@sync begin\n kernel(y, x; threads, blocks)\n end\nend","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"@btime bench_gpu4!($y_d, $x_d)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":" 70.826 μs (99 allocations: 3.44 KiB)","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"A comparable performance; slightly slower due to the use of the occupancy API, but that will not matter with more complex kernels.","category":"page"},{"location":"tutorials/introduction/#Printing","page":"Introduction","title":"Printing","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"When debugging, it's not uncommon to want to print some values. This is achieved with @cuprint:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"function gpu_add2_print!(y, x)\n index = threadIdx().x # this example only requires linear indexing, so just use `x`\n stride = blockDim().x\n @cuprintln(\"thread $index, block $stride\")\n for i = index:stride:length(y)\n @inbounds y[i] += x[i]\n end\n return nothing\nend\n\n@cuda threads=16 gpu_add2_print!(y_d, x_d)\nsynchronize()","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Note that the printed output is only generated when synchronizing the entire GPU with synchronize(). This is similar to CUDA.@sync, and is the counterpart of cudaDeviceSynchronize in CUDA C++.","category":"page"},{"location":"tutorials/introduction/#Error-handling","page":"Introduction","title":"Error-handling","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"The final topic of this intro concerns the handling of errors. Note that the kernels above used @inbounds, but did not check whether y and x have the same length. If your kernel does not respect these bounds, you will run into nasty errors:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"ERROR: CUDA error: an illegal memory access was encountered (code #700, ERROR_ILLEGAL_ADDRESS)\nStacktrace:\n [1] ...","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"If you remove the @inbounds annotation, instead you get","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"ERROR: a exception was thrown during kernel execution.\n Run Julia on debug level 2 for device stack traces.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"As the error message mentions, a higher level of debug information will result in a more detailed report. Let's run the same code with with -g2:","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"ERROR: a exception was thrown during kernel execution.\nStacktrace:\n [1] throw_boundserror at abstractarray.jl:484\n [2] checkbounds at abstractarray.jl:449\n [3] setindex! at /home/tbesard/Julia/CUDA/src/device/array.jl:79\n [4] some_kernel at /tmp/tmpIMYANH:6","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"warning: Warning\nOn older GPUs (with a compute capability below sm_70) these errors are fatal, and effectively kill the CUDA environment. On such GPUs, it's often a good idea to perform your \"sanity checks\" using code that runs on the CPU and only turn over the computation to the GPU once you've deemed it to be safe.","category":"page"},{"location":"tutorials/introduction/#Summary","page":"Introduction","title":"Summary","text":"","category":"section"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"Keep in mind that the high-level functionality of CUDA often means that you don't need to worry about writing kernels at such a low level. However, there are many cases where computations can be optimized using clever low-level manipulations. Hopefully, you now feel comfortable taking the plunge.","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"tutorials/introduction/","page":"Introduction","title":"Introduction","text":"This page was generated using Literate.jl.","category":"page"},{"location":"api/compiler/#Compiler","page":"Compiler","title":"Compiler","text":"","category":"section"},{"location":"api/compiler/#Execution","page":"Compiler","title":"Execution","text":"","category":"section"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"The main entry-point to the compiler is the @cuda macro:","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"@cuda","category":"page"},{"location":"api/compiler/#CUDA.@cuda","page":"Compiler","title":"CUDA.@cuda","text":"@cuda [kwargs...] func(args...)\n\nHigh-level interface for executing code on a GPU. The @cuda macro should prefix a call, with func a callable function or object that should return nothing. It will be compiled to a CUDA function upon first use, and to a certain extent arguments will be converted and managed automatically using cudaconvert. Finally, a call to cudacall is performed, scheduling a kernel launch on the current CUDA context.\n\nSeveral keyword arguments are supported that influence the behavior of @cuda.\n\nlaunch: whether to launch this kernel, defaults to true. If false the returned kernel object should be launched by calling it and passing arguments again.\ndynamic: use dynamic parallelism to launch device-side kernels, defaults to false.\narguments that influence kernel compilation: see cufunction and dynamic_cufunction\narguments that influence kernel launch: see CUDA.HostKernel and CUDA.DeviceKernel\n\n\n\n\n\n","category":"macro"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"If needed, you can use a lower-level API that lets you inspect the compiler kernel:","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"cudaconvert\ncufunction\nCUDA.HostKernel\nCUDA.version\nCUDA.maxthreads\nCUDA.registers\nCUDA.memory","category":"page"},{"location":"api/compiler/#CUDA.cudaconvert","page":"Compiler","title":"CUDA.cudaconvert","text":"cudaconvert(x)\n\nThis function is called for every argument to be passed to a kernel, allowing it to be converted to a GPU-friendly format. By default, the function does nothing and returns the input object x as-is.\n\nDo not add methods to this function, but instead extend the underlying Adapt.jl package and register methods for the the CUDA.Adaptor type.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#CUDA.cufunction","page":"Compiler","title":"CUDA.cufunction","text":"cufunction(f, tt=Tuple{}; kwargs...)\n\nLow-level interface to compile a function invocation for the currently-active GPU, returning a callable kernel object. For a higher-level interface, use @cuda.\n\nThe following keyword arguments are supported:\n\nminthreads: the required number of threads in a thread block\nmaxthreads: the maximum number of threads in a thread block\nblocks_per_sm: a minimum number of thread blocks to be scheduled on a single multiprocessor\nmaxregs: the maximum number of registers to be allocated to a single thread (only supported on LLVM 4.0+)\nname: override the name that the kernel will have in the generated code\nalways_inline: inline all function calls in the kernel\n\nThe output of this function is automatically cached, i.e. you can simply call cufunction in a hot path without degrading performance. New code will be generated automatically, when when function changes, or when different types or keyword arguments are provided.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#CUDA.HostKernel","page":"Compiler","title":"CUDA.HostKernel","text":"(::HostKernel)(args...; kwargs...)\n(::DeviceKernel)(args...; kwargs...)\n\nLow-level interface to call a compiled kernel, passing GPU-compatible arguments in args. For a higher-level interface, use @cuda.\n\nThe following keyword arguments are supported:\n\nthreads (defaults to 1)\nblocks (defaults to 1)\nshmem (defaults to 0)\nstream (defaults to the default stream)\n\n\n\n\n\n\n\n","category":"type"},{"location":"api/compiler/#CUDA.version","page":"Compiler","title":"CUDA.version","text":"version(k::HostKernel)\n\nQueries the PTX and SM versions a kernel was compiled for. Returns a named tuple.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#CUDA.maxthreads","page":"Compiler","title":"CUDA.maxthreads","text":"maxthreads(k::HostKernel)\n\nQueries the maximum amount of threads a kernel can use in a single block.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#CUDA.registers","page":"Compiler","title":"CUDA.registers","text":"registers(k::HostKernel)\n\nQueries the register usage of a kernel.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#CUDA.memory","page":"Compiler","title":"CUDA.memory","text":"memory(k::HostKernel)\n\nQueries the local, shared and constant memory usage of a compiled kernel in bytes. Returns a named tuple.\n\n\n\n\n\n","category":"function"},{"location":"api/compiler/#Reflection","page":"Compiler","title":"Reflection","text":"","category":"section"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"If you want to inspect generated code, you can use macros that resemble functionality from the InteractiveUtils standard library:","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"@device_code_lowered\n@device_code_typed\n@device_code_warntype\n@device_code_llvm\n@device_code_ptx\n@device_code_sass\n@device_code","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"These macros are also available in function-form:","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"CUDA.code_typed\nCUDA.code_warntype\nCUDA.code_llvm\nCUDA.code_ptx\nCUDA.code_sass","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"For more information, please consult the GPUCompiler.jl documentation. Only the code_sass functionality is actually defined in CUDA.jl:","category":"page"},{"location":"api/compiler/","page":"Compiler","title":"Compiler","text":"@device_code_sass\nCUDA.code_sass","category":"page"},{"location":"api/compiler/#CUDA.@device_code_sass","page":"Compiler","title":"CUDA.@device_code_sass","text":"@device_code_sass [io::IO=stdout, ...] ex\n\nEvaluates the expression ex and prints the result of CUDA.code_sass to io for every compiled CUDA kernel. For other supported keywords, see CUDA.code_sass.\n\n\n\n\n\n","category":"macro"},{"location":"api/compiler/#CUDA.code_sass","page":"Compiler","title":"CUDA.code_sass","text":"code_sass([io], f, types; verbose=false)\n\nPrints the SASS code generated for the method matching the given generic function and type signature to io which defaults to stdout.\n\nThe following keyword arguments are supported:\n\nverbose: enable verbose mode, which displays code generation statistics\nall keyword arguments from cufunction\n\nSee also: @device_code_sass\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA-driver","page":"CUDA driver","title":"CUDA driver","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"This section lists the package's public functionality that directly corresponds to functionality of the CUDA driver API. In general, the abstractions stay close to those of the CUDA driver API, so for more information on certain library calls you can consult the CUDA driver API reference.","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"The documentation is grouped according to the modules of the driver API.","category":"page"},{"location":"lib/driver/#Error-Handling","page":"CUDA driver","title":"Error Handling","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuError\nname(::CuError)\nCUDA.description(::CuError)","category":"page"},{"location":"lib/driver/#CUDA.CuError","page":"CUDA driver","title":"CUDA.CuError","text":"CuError(code)\nCuError(code, meta)\n\nCreate a CUDA error object with error code code. The optional meta parameter indicates whether extra information, such as error logs, is known.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.name-Tuple{CuError}","page":"CUDA driver","title":"CUDA.name","text":"name(err::CuError)\n\nGets the string representation of an error code.\n\njulia> err = CuError(CUDA.cudaError_enum(1))\nCuError(CUDA_ERROR_INVALID_VALUE)\n\njulia> name(err)\n\"ERROR_INVALID_VALUE\"\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.description-Tuple{CuError}","page":"CUDA driver","title":"CUDA.description","text":"description(err::CuError)\n\nGets the string description of an error code.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Version-Management","page":"CUDA driver","title":"Version Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.driver_version()\nCUDA.system_driver_version()\nCUDA.runtime_version()\nCUDA.set_runtime_version!","category":"page"},{"location":"lib/driver/#CUDA.driver_version-Tuple{}","page":"CUDA driver","title":"CUDA.driver_version","text":"driver_version()\n\nReturns the latest version of CUDA supported by the loaded driver.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.system_driver_version-Tuple{}","page":"CUDA driver","title":"CUDA.system_driver_version","text":"system_driver_version()\n\nReturns the latest version of CUDA supported by the original system driver, or nothing if the driver was not upgraded.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.runtime_version-Tuple{}","page":"CUDA driver","title":"CUDA.runtime_version","text":"runtime_version()\n\nReturns the CUDA Runtime version.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.set_runtime_version!","page":"CUDA driver","title":"CUDA.set_runtime_version!","text":"set_runtime_version!([version])\n\nSets the CUDA Runtime version preference to version. This can be a version number, in which case such a versioned artifact will be attempted to be used; or \"local\" for using a runtime from the local system. Invoke this function without an argument to reset the preference, in which case CUDA.jl will use the most recent compatible runtime available.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Device-Management","page":"CUDA driver","title":"Device Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuDevice\ndevices\ncurrent_device\nname(::CuDevice)\ntotalmem(::CuDevice)\nattribute","category":"page"},{"location":"lib/driver/#CUDA.CuDevice","page":"CUDA driver","title":"CUDA.CuDevice","text":"CuDevice(ordinal::Integer)\n\nGet a handle to a compute device.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.devices","page":"CUDA driver","title":"CUDA.devices","text":"devices()\n\nGet an iterator for the compute devices.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.current_device","page":"CUDA driver","title":"CUDA.current_device","text":"current_device()\n\nReturns the current device.\n\nwarning: Warning\nThis is a low-level API, returning the current device as known to the CUDA driver. For most users, it is recommended to use the device method instead.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.name-Tuple{CuDevice}","page":"CUDA driver","title":"CUDA.name","text":"name(dev::CuDevice)\n\nReturns an identifier string for the device.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.totalmem-Tuple{CuDevice}","page":"CUDA driver","title":"CUDA.totalmem","text":"totalmem(dev::CuDevice)\n\nReturns the total amount of memory (in bytes) on the device.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.attribute","page":"CUDA driver","title":"CUDA.attribute","text":"attribute(dev::CuDevice, code)\n\nReturns information about the device.\n\n\n\n\n\nattribute(X, pool::CuMemoryPool, attr)\n\nReturns attribute attr about pool. The type of the returned value depends on the attribute, and as such must be passed as the X parameter.\n\n\n\n\n\nattribute(X, ptr::Union{Ptr,CuPtr}, attr)\n\nReturns attribute attr about pointer ptr. The type of the returned value depends on the attribute, and as such must be passed as the X parameter.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Certain common attributes are exposed by additional convenience functions:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"capability(::CuDevice)\nwarpsize(::CuDevice)","category":"page"},{"location":"lib/driver/#CUDA.capability-Tuple{CuDevice}","page":"CUDA driver","title":"CUDA.capability","text":"capability(dev::CuDevice)\n\nReturns the compute capability of the device.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.warpsize-Tuple{CuDevice}","page":"CUDA driver","title":"CUDA.warpsize","text":"warpsize(dev::CuDevice)\n\nReturns the warp size (in threads) of the device.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Context-Management","page":"CUDA driver","title":"Context Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuContext\nCUDA.unsafe_destroy!(::CuContext)\ncurrent_context\nactivate(::CuContext)\nsynchronize(::CuContext)\ndevice_synchronize","category":"page"},{"location":"lib/driver/#CUDA.CuContext","page":"CUDA driver","title":"CUDA.CuContext","text":"CuContext(dev::CuDevice, flags=CTX_SCHED_AUTO)\nCuContext(f::Function, ...)\n\nCreate a CUDA context for device. A context on the GPU is analogous to a process on the CPU, with its own distinct address space and allocated resources. When a context is destroyed, the system cleans up the resources allocated to it.\n\nWhen you are done using the context, call CUDA.unsafe_destroy! to mark it for deletion, or use do-block syntax with this constructor.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.unsafe_destroy!-Tuple{CuContext}","page":"CUDA driver","title":"CUDA.unsafe_destroy!","text":"unsafe_destroy!(ctx::CuContext)\n\nImmediately destroy a context, freeing up all resources associated with it. This does not respect any users of the context, and might make other objects unusable.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.current_context","page":"CUDA driver","title":"CUDA.current_context","text":"current_context()\n\nReturns the current context.\n\nwarning: Warning\nThis is a low-level API, returning the current context as known to the CUDA driver. For most users, it is recommended to use the context method instead.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.activate-Tuple{CuContext}","page":"CUDA driver","title":"CUDA.activate","text":"activate(ctx::CuContext)\n\nBinds the specified CUDA context to the calling CPU thread.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.synchronize-Tuple{CuContext}","page":"CUDA driver","title":"CUDA.synchronize","text":"synchronize(ctx::Context)\n\nBlock for the all operations on ctx to complete. This is a heavyweight operation, typically you only need to call synchronize which only synchronizes the stream associated with the current task.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Primary-Context-Management","page":"CUDA driver","title":"Primary Context Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuPrimaryContext\nCuContext(::CuPrimaryContext)\nisactive(::CuPrimaryContext)\nflags(::CuPrimaryContext)\nsetflags!(::CuPrimaryContext, ::CUDA.CUctx_flags)\nunsafe_reset!(::CuPrimaryContext)\nCUDA.unsafe_release!(::CuContext)","category":"page"},{"location":"lib/driver/#CUDA.CuPrimaryContext","page":"CUDA driver","title":"CUDA.CuPrimaryContext","text":"CuPrimaryContext(dev::CuDevice)\n\nCreate a primary CUDA context for a given device.\n\nEach primary context is unique per device and is shared with CUDA runtime API. It is meant for interoperability with (applications using) the runtime API.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.CuContext-Tuple{CuPrimaryContext}","page":"CUDA driver","title":"CUDA.CuContext","text":"CuContext(pctx::CuPrimaryContext)\n\nRetain the primary context on the GPU, returning a context compatible with the driver API. The primary context will be released when the returned driver context is finalized.\n\nAs these contexts are refcounted by CUDA, you should not call CUDA.unsafe_destroy! on them but use CUDA.unsafe_release! instead (available with do-block syntax as well).\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.isactive-Tuple{CuPrimaryContext}","page":"CUDA driver","title":"CUDA.isactive","text":"isactive(pctx::CuPrimaryContext)\n\nQuery whether a primary context is active.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.flags-Tuple{CuPrimaryContext}","page":"CUDA driver","title":"CUDA.flags","text":"flags(pctx::CuPrimaryContext)\n\nQuery the flags of a primary context.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.setflags!-Tuple{CuPrimaryContext, CUDA.CUctx_flags_enum}","page":"CUDA driver","title":"CUDA.setflags!","text":"setflags!(pctx::CuPrimaryContext)\n\nSet the flags of a primary context.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.unsafe_reset!-Tuple{CuPrimaryContext}","page":"CUDA driver","title":"CUDA.unsafe_reset!","text":"unsafe_reset!(pctx::CuPrimaryContext)\n\nExplicitly destroys and cleans up all resources associated with a device's primary context in the current process. Note that this forcibly invalidates all contexts derived from this primary context, and as a result outstanding resources might become invalid.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.unsafe_release!-Tuple{CuContext}","page":"CUDA driver","title":"CUDA.unsafe_release!","text":"CUDA.unsafe_release!(ctx::CuContext)\n\nLower the refcount of a context, possibly freeing up all resources associated with it. This does not respect any users of the context, and might make other objects unusable.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Module-Management","page":"CUDA driver","title":"Module Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuModule","category":"page"},{"location":"lib/driver/#CUDA.CuModule","page":"CUDA driver","title":"CUDA.CuModule","text":"CuModule(data, options::Dict{CUjit_option,Any})\nCuModuleFile(path, options::Dict{CUjit_option,Any})\n\nCreate a CUDA module from a data, or a file containing data. The data may be PTX code, a CUBIN, or a FATBIN.\n\nThe options is an optional dictionary of JIT options and their respective value.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#Function-Management","page":"CUDA driver","title":"Function Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuFunction","category":"page"},{"location":"lib/driver/#CUDA.CuFunction","page":"CUDA driver","title":"CUDA.CuFunction","text":"CuFunction(mod::CuModule, name::String)\n\nAcquires a function handle from a named function in a module.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#Global-Variable-Management","page":"CUDA driver","title":"Global Variable Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuGlobal\neltype(::CuGlobal)\nBase.getindex(::CuGlobal)\nBase.setindex!(::CuGlobal{T}, ::T) where {T}","category":"page"},{"location":"lib/driver/#CUDA.CuGlobal","page":"CUDA driver","title":"CUDA.CuGlobal","text":"CuGlobal{T}(mod::CuModule, name::String)\n\nAcquires a typed global variable handle from a named global in a module.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#Base.eltype-Tuple{CuGlobal}","page":"CUDA driver","title":"Base.eltype","text":"eltype(var::CuGlobal)\n\nReturn the element type of a global variable object.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Base.getindex-Tuple{CuGlobal}","page":"CUDA driver","title":"Base.getindex","text":"Base.getindex(var::CuGlobal)\n\nReturn the current value of a global variable.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Base.setindex!-Union{Tuple{T}, Tuple{CuGlobal{T}, T}} where T","page":"CUDA driver","title":"Base.setindex!","text":"Base.setindex(var::CuGlobal{T}, val::T)\n\nSet the value of a global variable to val\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Linker","page":"CUDA driver","title":"Linker","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuLink\nadd_data!\nadd_file!\nCuLinkImage\ncomplete\nCuModule(::CuLinkImage, args...)","category":"page"},{"location":"lib/driver/#CUDA.CuLink","page":"CUDA driver","title":"CUDA.CuLink","text":"CuLink()\n\nCreates a pending JIT linker invocation.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.add_data!","page":"CUDA driver","title":"CUDA.add_data!","text":"add_data!(link::CuLink, name::String, code::String)\n\nAdd PTX code to a pending link operation.\n\n\n\n\n\nadd_data!(link::CuLink, name::String, data::Vector{UInt8}, type::CUjitInputType)\n\nAdd object code to a pending link operation.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.add_file!","page":"CUDA driver","title":"CUDA.add_file!","text":"add_file!(link::CuLink, path::String, typ::CUjitInputType)\n\nAdd data from a file to a link operation. The argument typ indicates the type of the contained data.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.CuLinkImage","page":"CUDA driver","title":"CUDA.CuLinkImage","text":"The result of a linking operation.\n\nThis object keeps its parent linker object alive, as destroying a linker destroys linked images too.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.complete","page":"CUDA driver","title":"CUDA.complete","text":"complete(link::CuLink)\n\nComplete a pending linker invocation, returning an output image.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.CuModule-Tuple{CuLinkImage, Vararg{Any}}","page":"CUDA driver","title":"CUDA.CuModule","text":"CuModule(img::CuLinkImage, ...)\n\nCreate a CUDA module from a completed linking operation. Options from CuModule apply.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Memory-Management","page":"CUDA driver","title":"Memory Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Three kinds of memory buffers can be allocated: device memory, host memory, and unified memory. Each of these buffers can be allocated by calling alloc with the type of buffer as first argument, and freed by calling free. Certain buffers have specific methods defined.","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Mem.DeviceBuffer\nMem.alloc(::Type{Mem.DeviceBuffer}, ::Integer)","category":"page"},{"location":"lib/driver/#CUDA.Mem.DeviceBuffer","page":"CUDA driver","title":"CUDA.Mem.DeviceBuffer","text":"Mem.DeviceBuffer\nMem.Device\n\nA buffer of device memory residing on the GPU.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.Mem.alloc-Tuple{Type{CUDA.Mem.DeviceBuffer}, Integer}","page":"CUDA driver","title":"CUDA.Mem.alloc","text":"Mem.alloc(DeviceBuffer, bytesize::Integer;\n [async=false], [stream::CuStream], [pool::CuMemoryPool])\n\nAllocate bytesize bytes of memory on the device. This memory is only accessible on the GPU, and requires explicit calls to unsafe_copyto!, which wraps cuMemcpy, for access on the CPU.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Mem.HostBuffer\nMem.alloc(::Type{Mem.HostBuffer}, ::Integer, flags)\nMem.register(::Type{Mem.HostBuffer}, ::Ptr, ::Integer, flags)\nMem.unregister(::Mem.HostBuffer)","category":"page"},{"location":"lib/driver/#CUDA.Mem.HostBuffer","page":"CUDA driver","title":"CUDA.Mem.HostBuffer","text":"Mem.HostBuffer\nMem.Host\n\nA buffer of pinned memory on the CPU, possibly accessible on the GPU.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.Mem.alloc-Tuple{Type{CUDA.Mem.HostBuffer}, Integer, Any}","page":"CUDA driver","title":"CUDA.Mem.alloc","text":"Mem.alloc(HostBuffer, bytesize::Integer, [flags])\n\nAllocate bytesize bytes of page-locked memory on the host. This memory is accessible from the CPU, and makes it possible to perform faster memory copies to the GPU. Furthermore, if flags is set to HOSTALLOC_DEVICEMAP the memory is also accessible from the GPU. These accesses are direct, and go through the PCI bus. If flags is set to HOSTALLOC_PORTABLE, the memory is considered mapped by all CUDA contexts, not just the one that created the memory, which is useful if the memory needs to be accessed from multiple devices. Multiple flags can be set at one time using a bytewise OR:\n\nflags = HOSTALLOC_PORTABLE | HOSTALLOC_DEVICEMAP\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.Mem.register-Tuple{Type{CUDA.Mem.HostBuffer}, Ptr, Integer, Any}","page":"CUDA driver","title":"CUDA.Mem.register","text":"Mem.register(HostBuffer, ptr::Ptr, bytesize::Integer, [flags])\n\nPage-lock the host memory pointed to by ptr. Subsequent transfers to and from devices will be faster, and can be executed asynchronously. If the HOSTREGISTER_DEVICEMAP flag is specified, the buffer will also be accessible directly from the GPU. These accesses are direct, and go through the PCI bus. If the HOSTREGISTER_PORTABLE flag is specified, any CUDA context can access the memory.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.Mem.unregister-Tuple{CUDA.Mem.HostBuffer}","page":"CUDA driver","title":"CUDA.Mem.unregister","text":"Mem.unregister(HostBuffer)\n\nUnregisters a memory range that was registered with Mem.register.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Mem.UnifiedBuffer\nMem.alloc(::Type{Mem.UnifiedBuffer}, ::Integer, ::CUDA.CUmemAttach_flags)\nMem.prefetch(::Mem.UnifiedBuffer, bytes::Integer; device, stream)\nMem.advise(::Mem.UnifiedBuffer, ::CUDA.CUmem_advise, ::Integer; device)","category":"page"},{"location":"lib/driver/#CUDA.Mem.UnifiedBuffer","page":"CUDA driver","title":"CUDA.Mem.UnifiedBuffer","text":"Mem.UnifiedBuffer\nMem.Unified\n\nA managed buffer that is accessible on both the CPU and GPU.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.Mem.alloc-Tuple{Type{CUDA.Mem.UnifiedBuffer}, Integer, CUDA.CUmemAttach_flags_enum}","page":"CUDA driver","title":"CUDA.Mem.alloc","text":"Mem.alloc(UnifiedBuffer, bytesize::Integer, [flags::CUmemAttach_flags])\n\nAllocate bytesize bytes of unified memory. This memory is accessible from both the CPU and GPU, with the CUDA driver automatically copying upon first access.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.Mem.prefetch-Tuple{CUDA.Mem.UnifiedBuffer, Integer}","page":"CUDA driver","title":"CUDA.Mem.prefetch","text":"prefetch(::UnifiedBuffer, [bytes::Integer]; [device::CuDevice], [stream::CuStream])\n\nPrefetches memory to the specified destination device.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.Mem.advise-Tuple{CUDA.Mem.UnifiedBuffer, CUDA.CUmem_advise_enum, Integer}","page":"CUDA driver","title":"CUDA.Mem.advise","text":"advise(::UnifiedBuffer, advice::CUDA.CUmem_advise, [bytes::Integer]; [device::CuDevice])\n\nAdvise about the usage of a given memory range.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"To work with these buffers, you need to convert them to a Ptr or CuPtr. Several methods then work with these raw pointers:","category":"page"},{"location":"lib/driver/#Memory-info","page":"CUDA driver","title":"Memory info","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.available_memory\nCUDA.total_memory","category":"page"},{"location":"lib/driver/#CUDA.available_memory","page":"CUDA driver","title":"CUDA.available_memory","text":"available_memory()\n\nReturns the available amount of memory (in bytes), available for allocation by the CUDA context.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.total_memory","page":"CUDA driver","title":"CUDA.total_memory","text":"total_memory()\n\nReturns the total amount of memory (in bytes), available for allocation by the CUDA context.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Stream-Management","page":"CUDA driver","title":"Stream Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuStream\nCUDA.isdone(::CuStream)\npriority_range\npriority\nsynchronize(::CuStream)\nCUDA.@sync","category":"page"},{"location":"lib/driver/#CUDA.CuStream","page":"CUDA driver","title":"CUDA.CuStream","text":"CuStream(; flags=STREAM_DEFAULT, priority=nothing)\n\nCreate a CUDA stream.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.isdone-Tuple{CuStream}","page":"CUDA driver","title":"CUDA.isdone","text":"isdone(s::CuStream)\n\nReturn false if a stream is busy (has task running or queued) and true if that stream is free.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.priority_range","page":"CUDA driver","title":"CUDA.priority_range","text":"priority_range()\n\nReturn the valid range of stream priorities as a StepRange (with step size 1). The lower bound of the range denotes the least priority (typically 0), with the upper bound representing the greatest possible priority (typically -1).\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.priority","page":"CUDA driver","title":"CUDA.priority","text":"priority_range(s::CuStream)\n\nReturn the priority of a stream s.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.synchronize-Tuple{CuStream}","page":"CUDA driver","title":"CUDA.synchronize","text":"synchronize([stream::CuStream])\n\nWait until stream has finished executing, with stream defaulting to the stream associated with the current Julia task.\n\nSee also: device_synchronize\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.@sync","page":"CUDA driver","title":"CUDA.@sync","text":"@sync ex\n\nRun expression ex and synchronize the GPU afterwards.\n\nSee also: synchronize.\n\n\n\n\n\n","category":"macro"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"For specific use cases, special streams are available:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"default_stream\nlegacy_stream\nper_thread_stream","category":"page"},{"location":"lib/driver/#CUDA.default_stream","page":"CUDA driver","title":"CUDA.default_stream","text":"default_stream()\n\nReturn the default stream.\n\nnote: Note\nIt is generally better to use stream() to get a stream object that's local to the current task. That way, operations scheduled in other tasks can overlap.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.legacy_stream","page":"CUDA driver","title":"CUDA.legacy_stream","text":"legacy_stream()\n\nReturn a special object to use use an implicit stream with legacy synchronization behavior.\n\nYou can use this stream to perform operations that should block on all streams (with the exception of streams created with STREAM_NON_BLOCKING). This matches the old pre-CUDA 7 global stream behavior.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.per_thread_stream","page":"CUDA driver","title":"CUDA.per_thread_stream","text":"per_thread_stream()\n\nReturn a special object to use an implicit stream with per-thread synchronization behavior. This stream object is normally meant to be used with APIs that do not have per-thread versions of their APIs (i.e. without a ptsz or ptds suffix).\n\nnote: Note\nIt is generally not needed to use this type of stream. With CUDA.jl, each task already gets its own non-blocking stream, and multithreading in Julia is typically accomplished using tasks.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Event-Management","page":"CUDA driver","title":"Event Management","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuEvent\nrecord\nsynchronize(::CuEvent)\nCUDA.isdone(::CuEvent)\nCUDA.wait(::CuEvent)\nelapsed\nCUDA.@elapsed","category":"page"},{"location":"lib/driver/#CUDA.CuEvent","page":"CUDA driver","title":"CUDA.CuEvent","text":"CuEvent()\n\nCreate a new CUDA event.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.record","page":"CUDA driver","title":"CUDA.record","text":"record(e::CuEvent, [stream::CuStream])\n\nRecord an event on a stream.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.synchronize-Tuple{CuEvent}","page":"CUDA driver","title":"CUDA.synchronize","text":"synchronize(e::CuEvent)\n\nWaits for an event to complete.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.isdone-Tuple{CuEvent}","page":"CUDA driver","title":"CUDA.isdone","text":"isdone(e::CuEvent)\n\nReturn false if there is outstanding work preceding the most recent call to record(e) and true if all captured work has been completed.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.wait-Tuple{CuEvent}","page":"CUDA driver","title":"CUDA.wait","text":"wait(e::CuEvent, [stream::CuStream])\n\nMake a stream wait on a event. This only makes the stream wait, and not the host; use synchronize(::CuEvent) for that.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.elapsed","page":"CUDA driver","title":"CUDA.elapsed","text":"elapsed(start::CuEvent, stop::CuEvent)\n\nComputes the elapsed time between two events (in seconds).\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.@elapsed","page":"CUDA driver","title":"CUDA.@elapsed","text":"@elapsed ex\n\nA macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute on the GPU, as a floating-point number.\n\n\n\n\n\n","category":"macro"},{"location":"lib/driver/#Execution-Control","page":"CUDA driver","title":"Execution Control","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuDim3\ncudacall\nCUDA.launch","category":"page"},{"location":"lib/driver/#CUDA.CuDim3","page":"CUDA driver","title":"CUDA.CuDim3","text":"CuDim3(x)\n\nCuDim3((x,))\nCuDim3((x, y))\nCuDim3((x, y, x))\n\nA type used to specify dimensions, consisting of 3 integers for respectively the x, y and z dimension. Unspecified dimensions default to 1.\n\nOften accepted as argument through the CuDim type alias, eg. in the case of cudacall or CUDA.launch, allowing to pass dimensions as a plain integer or a tuple without having to construct an explicit CuDim3 object.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.cudacall","page":"CUDA driver","title":"CUDA.cudacall","text":"cudacall(f, types, values...; blocks::CuDim, threads::CuDim,\n cooperative=false, shmem=0, stream=stream())\n\nccall-like interface for launching a CUDA function f on a GPU.\n\nFor example:\n\nvadd = CuFunction(md, \"vadd\")\na = rand(Float32, 10)\nb = rand(Float32, 10)\nad = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))\nunsafe_copyto!(ad, convert(Ptr{Cvoid}, a), 10*sizeof(Float32)))\nbd = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))\nunsafe_copyto!(bd, convert(Ptr{Cvoid}, b), 10*sizeof(Float32)))\nc = zeros(Float32, 10)\ncd = Mem.alloc(DeviceBuffer, 10*sizeof(Float32))\n\ncudacall(vadd, (CuPtr{Cfloat},CuPtr{Cfloat},CuPtr{Cfloat}), ad, bd, cd; threads=10)\nunsafe_copyto!(convert(Ptr{Cvoid}, c), cd, 10*sizeof(Float32)))\n\nThe blocks and threads arguments control the launch configuration, and should both consist of either an integer, or a tuple of 1 to 3 integers (omitted dimensions default to 1). The types argument can contain both a tuple of types, and a tuple type, the latter being slightly faster.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.launch","page":"CUDA driver","title":"CUDA.launch","text":"launch(f::CuFunction; args...; blocks::CuDim=1, threads::CuDim=1,\n cooperative=false, shmem=0, stream=stream())\n\nLow-level call to launch a CUDA function f on the GPU, using blocks and threads as respectively the grid and block configuration. Dynamic shared memory is allocated according to shmem, and the kernel is launched on stream stream.\n\nArguments to a kernel should either be bitstype, in which case they will be copied to the internal kernel parameter buffer, or a pointer to device memory.\n\nThis is a low-level call, prefer to use cudacall instead.\n\n\n\n\n\nlaunch(exec::CuGraphExec, [stream::CuStream])\n\nLaunches an executable graph, by default in the currently-active stream.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Profiler-Control","page":"CUDA driver","title":"Profiler Control","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.@profile\nCUDA.Profile.start\nCUDA.Profile.stop","category":"page"},{"location":"lib/driver/#CUDA.@profile","page":"CUDA driver","title":"CUDA.@profile","text":"@profile ex\n\nRun expressions while activating the CUDA profiler.\n\nNote that this API is used to programmatically control the profiling granularity by allowing profiling to be done only on selective pieces of code. It does not perform any profiling on itself, you need external tools for that.\n\n\n\n\n\n","category":"macro"},{"location":"lib/driver/#CUDA.Profile.start","page":"CUDA driver","title":"CUDA.Profile.start","text":"start()\n\nEnables profile collection by the active profiling tool for the current context. If profiling is already enabled, then this call has no effect.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.Profile.stop","page":"CUDA driver","title":"CUDA.Profile.stop","text":"stop()\n\nDisables profile collection by the active profiling tool for the current context. If profiling is already disabled, then this call has no effect.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Texture-Memory","page":"CUDA driver","title":"Texture Memory","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Textures are represented by objects of type CuTexture which are bound to some underlying memory, either CuArrays or CuTextureArrays:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.CuTexture\nCUDA.CuTexture(array)","category":"page"},{"location":"lib/driver/#CUDA.CuTexture","page":"CUDA driver","title":"CUDA.CuTexture","text":"CuTexture{T,N,P}\n\nN-dimensional texture object with elements of type T. These objects do not store data themselves, but are bounds to another source of device memory. Texture objects can be passed to CUDA kernels, where they will be accessible through the CuDeviceTexture type.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.CuTexture-Tuple{Any}","page":"CUDA driver","title":"CUDA.CuTexture","text":"CuTexture{T,N,P}(parent::P; address_mode, filter_mode, normalized_coordinates)\n\nConstruct a N-dimensional texture object with elements of type T as stored in parent.\n\nSeveral keyword arguments alter the behavior of texture objects:\n\naddress_mode (wrap, clamp, mirror): how out-of-bounds values are accessed. Can be specified as a value for all dimensions, or as a tuple of N entries.\ninterpolation (nearest neighbour, linear, bilinear): how non-integral indices are fetched. Nearest-neighbour fetches a single value, others interpolate between multiple.\nnormalized_coordinates (true, false): whether indices are expected to fall in the normalized [0:1) range.\n\n!!! warning Experimental API. Subject to change without deprecation.\n\n\n\n\n\nCuTexture(x::CuTextureArray{T,N})\n\nCreate a N-dimensional texture object withelements of type T that will be read from x.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\nCuTexture(x::CuArray{T,N})\n\nCreate a N-dimensional texture object that reads from a CuArray.\n\nNote that it is necessary the their memory is well aligned and strided (good pitch). Currently, that is not being enforced.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"You can create CuTextureArray objects from both host and device memory:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.CuTextureArray\nCUDA.CuTextureArray(array)","category":"page"},{"location":"lib/driver/#CUDA.CuTextureArray","page":"CUDA driver","title":"CUDA.CuTextureArray","text":"CuTextureArray{T,N}(undef, dims)\n\nN-dimensional dense texture array with elements of type T. These arrays are optimized for texture fetching, and are only meant to be used as a source for CuTexture{T,N,P} objects.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.CuTextureArray-Tuple{Any}","page":"CUDA driver","title":"CUDA.CuTextureArray","text":"CuTextureArray(A::AbstractArray)\n\nAllocate and initialize a texture buffer from host memory in A.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\nCuTextureArray(A::CuArray)\n\nAllocate and initialize a texture buffer from device memory in A.\n\nwarning: Warning\nExperimental API. Subject to change without deprecation.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#Occupancy-API","page":"CUDA driver","title":"Occupancy API","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"The occupancy API can be used to figure out an appropriate launch configuration for a compiled kernel (represented as a CuFunction) on the current device:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"launch_configuration\nactive_blocks\noccupancy","category":"page"},{"location":"lib/driver/#CUDA.launch_configuration","page":"CUDA driver","title":"CUDA.launch_configuration","text":"launch_configuration(fun::CuFunction; shmem=0, max_threads=0)\n\nCalculate a suggested launch configuration for kernel fun requiring shmem bytes of dynamic shared memory. Returns a tuple with a suggested amount of threads, and the minimal amount of blocks to reach maximal occupancy. Optionally, the maximum amount of threads can be constrained using max_threads.\n\nIn the case of a variable amount of shared memory, pass a callable object for shmem instead, taking a single integer representing the block size and returning the amount of dynamic shared memory for that configuration.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.active_blocks","page":"CUDA driver","title":"CUDA.active_blocks","text":"active_blocks(fun::CuFunction, threads; shmem=0)\n\nCalculate the maximum number of active blocks per multiprocessor when running threads threads of a kernel fun requiring shmem bytes of dynamic shared memory.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.occupancy","page":"CUDA driver","title":"CUDA.occupancy","text":"occupancy(fun::CuFunction, threads; shmem=0)\n\nCalculate the theoretical occupancy of launching threads threads of a kernel fun requiring shmem bytes of dynamic shared memory.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#Graph-Execution","page":"CUDA driver","title":"Graph Execution","text":"","category":"section"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA graphs can be easily recorded and executed using the high-level @captured macro:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CUDA.@captured","category":"page"},{"location":"lib/driver/#CUDA.@captured","page":"CUDA driver","title":"CUDA.@captured","text":"for ...\n @captured begin\n # code that executes several kernels or CUDA operations\n end\nend\n\nA convenience macro for recording a graph of CUDA operations and automatically cache and update the execution. This can improve performance when executing kernels in a loop, where the launch overhead might dominate the execution.\n\nwarning: Warning\nFor this to be effective, the kernels and operations executed inside of the captured region should not signficantly change across iterations of the loop. It is allowed to, e.g., change kernel arguments or inputs to operations, as this will be processed by updating the cached executable graph. However, significant changes will result in an instantiation of the graph from scratch, which is an expensive operation.\n\nSee also: capture.\n\n\n\n\n\n","category":"macro"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"Low-level operations are available too:","category":"page"},{"location":"lib/driver/","page":"CUDA driver","title":"CUDA driver","text":"CuGraph\ncapture\ninstantiate\nlaunch(::CUDA.CuGraphExec)\nupdate","category":"page"},{"location":"lib/driver/#CUDA.CuGraph","page":"CUDA driver","title":"CUDA.CuGraph","text":"CuGraph([flags])\n\nCreate an empty graph for use with low-level graph operations. If you want to create a graph while directly recording operations, use capture. For a high-level interface that also automatically executes the graph, use the @captured macro.\n\n\n\n\n\n","category":"type"},{"location":"lib/driver/#CUDA.capture","page":"CUDA driver","title":"CUDA.capture","text":"capture([flags], [throw_error::Bool=true]) do\n ...\nend\n\nCapture a graph of CUDA operations. The returned graph can then be instantiated and executed repeatedly for improved performance.\n\nNote that many operations, like initial kernel compilation or memory allocations, cannot be captured. To work around this, you can set the throw_error keyword to false, which will cause this function to return nothing if such a failure happens. You can then try to evaluate the function in a regular way, and re-record afterwards.\n\nSee also: instantiate.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.instantiate","page":"CUDA driver","title":"CUDA.instantiate","text":"instantiate(graph::CuGraph)\n\nCreates an executable graph from a graph. This graph can then be launched, or updated with an other graph.\n\nSee also: launch, update.\n\n\n\n\n\n","category":"function"},{"location":"lib/driver/#CUDA.launch-Tuple{CuGraphExec}","page":"CUDA driver","title":"CUDA.launch","text":"launch(f::CuFunction; args...; blocks::CuDim=1, threads::CuDim=1,\n cooperative=false, shmem=0, stream=stream())\n\nLow-level call to launch a CUDA function f on the GPU, using blocks and threads as respectively the grid and block configuration. Dynamic shared memory is allocated according to shmem, and the kernel is launched on stream stream.\n\nArguments to a kernel should either be bitstype, in which case they will be copied to the internal kernel parameter buffer, or a pointer to device memory.\n\nThis is a low-level call, prefer to use cudacall instead.\n\n\n\n\n\nlaunch(exec::CuGraphExec, [stream::CuStream])\n\nLaunches an executable graph, by default in the currently-active stream.\n\n\n\n\n\n","category":"method"},{"location":"lib/driver/#CUDA.update","page":"CUDA driver","title":"CUDA.update","text":"update(exec::CuGraphExec, graph::CuGraph; [throw_error::Bool=true])\n\nCheck whether an executable graph can be updated with a graph and perform the update if possible. Returns a boolean indicating whether the update was successful. Unless throw_error is set to false, also throws an error if the update failed.\n\n\n\n\n\n","category":"function"},{"location":"development/troubleshooting/#Troubleshooting","page":"Troubleshooting","title":"Troubleshooting","text":"","category":"section"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"This section deals with common errors you might run into while writing GPU code, preventing the code to compile.","category":"page"},{"location":"development/troubleshooting/#InvalidIRError:-compiling-...-resulted-in-invalid-LLVM-IR","page":"Troubleshooting","title":"InvalidIRError: compiling ... resulted in invalid LLVM IR","text":"","category":"section"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Not all of Julia is supported by CUDA.jl. Several commonly-used features, like strings or exceptions, will not compile to GPU code, because of their interactions with the CPU-only runtime library.","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"For example, say we define and try to execute the following kernel:","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"julia> function kernel(a)\n @inbounds a[threadId().x] = 0\n return\n end\n\njulia> @cuda kernel(CuArray([1]))\nERROR: InvalidIRError: compiling kernel kernel(CuDeviceArray{Int64,1,1}) resulted in invalid LLVM IR\nReason: unsupported dynamic function invocation (call to setindex!)\nStacktrace:\n [1] kernel at REPL[2]:2\nReason: unsupported dynamic function invocation (call to getproperty)\nStacktrace:\n [1] kernel at REPL[2]:2\nReason: unsupported use of an undefined name (use of 'threadId')\nStacktrace:\n [1] kernel at REPL[2]:2","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"CUDA.jl does its best to decode the unsupported IR and figure out where it came from. In this case, there's two so-called dynamic invocations, which happen when a function call cannot be statically resolved (often because the compiler could not fully infer the call, e.g., due to inaccurate or instable type information). These are a red herring, and the real cause is listed last: a typo in the use of the threadIdx function! If we fix this, the IR error disappears and our kernel successfully compiles and executes.","category":"page"},{"location":"development/troubleshooting/#KernelError:-kernel-returns-a-value-of-type-Union{}","page":"Troubleshooting","title":"KernelError: kernel returns a value of type Union{}","text":"","category":"section"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Where the previous section clearly pointed to the source of invalid IR, in other cases your function will return an error. This is encoded by the Julia compiler as a return value of type Union{}:","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"julia> function kernel(a)\n @inbounds a[threadId().x] = CUDA.sin(a[threadIdx().x])\n return\n end\n\njulia> @cuda kernel(CuArray([1]))\nERROR: GPU compilation of kernel kernel(CuDeviceArray{Int64,1,1}) failed\nKernelError: kernel returns a value of type `Union{}`","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Now we don't know where this error came from, and we will have to take a look ourselves at the generated code. This is easily done using the @device_code introspection macros, which mimic their Base counterparts (e.g. @device_code_llvm instead of @code_llvm, etc).","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"To debug an error returned by a kernel, we should use @device_code_warntype to inspect the Julia IR. Furthermore, this macro has an interactive mode, which further facilitates inspecting this IR using Cthulhu.jl. First, install and import this package, and then try to execute the kernel again prefixed by @device_code_warntype interactive=true:","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"julia> using Cthulhu\n\njulia> @device_code_warntype interactive=true @cuda kernel(CuArray([1]))\nVariables\n #self#::Core.Compiler.Const(kernel, false)\n a::CuDeviceArray{Int64,1,1}\n val::Union{}\n\nBody::Union{}\n1 ─ %1 = CUDA.sin::Core.Compiler.Const(CUDA.sin, false)\n│ ...\n│ %14 = (...)::Int64\n└── goto #2\n2 ─ (%1)(%14)\n└── $(Expr(:unreachable))\n\nSelect a call to descend into or ↩ to ascend.\n • %17 = call CUDA.sin(::Int64)::Union{}","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Both from the IR and the list of calls Cthulhu offers to inspect further, we can see that the call to CUDA.sin(::Int64) results in an error: in the IR it is immediately followed by an unreachable, while in the list of calls it is inferred to return Union{}. Now we know where to look, it's easy to figure out what's wrong:","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"help?> CUDA.sin\n # 2 methods for generic function \"sin\":\n [1] sin(x::Float32) in CUDA at /home/tim/Julia/pkg/CUDA/src/device/intrinsics/math.jl:13\n [2] sin(x::Float64) in CUDA at /home/tim/Julia/pkg/CUDA/src/device/intrinsics/math.jl:12","category":"page"},{"location":"development/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"There's no method of CUDA.sin that accepts an Int64, and thus the function was determined to unconditionally throw a method error. For now, we disallow these situations and refuse to compile, but in the spirit of dynamic languages we might change this behavior to just throw an error at run time.","category":"page"},{"location":"installation/troubleshooting/#Troubleshooting","page":"Troubleshooting","title":"Troubleshooting","text":"","category":"section"},{"location":"installation/troubleshooting/#UndefVarError:-libcuda-not-defined","page":"Troubleshooting","title":"UndefVarError: libcuda not defined","text":"","category":"section"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"This means that CUDA.jl could not find a suitable CUDA driver. For more information, re-run with the JULIA_DEBUG environment variable set to CUDA_Driver_jll.","category":"page"},{"location":"installation/troubleshooting/#UNKNOWN_ERROR(999)","page":"Troubleshooting","title":"UNKNOWN_ERROR(999)","text":"","category":"section"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"If you encounter this error, there are several known issues that may be causing it:","category":"page"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"a mismatch between the CUDA driver and driver library: on Linux, look for clues in dmesg\nthe CUDA driver is in a bad state: this can happen after resume. Try rebooting.","category":"page"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Generally though, it's impossible to say what's the reason for the error, but Julia is likely not to blame. Make sure your set-up works (e.g., try executing nvidia-smi, a CUDA C binary, etc), and if everything looks good file an issue.","category":"page"},{"location":"installation/troubleshooting/#NVML-library-not-found-(on-Windows)","page":"Troubleshooting","title":"NVML library not found (on Windows)","text":"","category":"section"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Check and make sure the NVSMI folder is in your PATH. By default it may not be. Look in C:\\Program Files\\NVIDIA Corporation for the NVSMI folder - you should see nvml.dll within it. You can add this folder to your PATH and check that nvidia-smi runs properly.","category":"page"},{"location":"installation/troubleshooting/#The-specified-module-could-not-be-found-(on-Windows)","page":"Troubleshooting","title":"The specified module could not be found (on Windows)","text":"","category":"section"},{"location":"installation/troubleshooting/","page":"Troubleshooting","title":"Troubleshooting","text":"Ensure the Visual C++ Redistributable is installed.","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"EditURL = \"https://github.com/JuliaGPU/CUDA.jl/blob/master/docs/src/tutorials/custom_structs.jl\"","category":"page"},{"location":"tutorials/custom_structs/#Using-custom-structs","page":"Using custom structs","title":"Using custom structs","text":"","category":"section"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"This tutorial shows how to use custom structs on the GPU. Our example will be a one dimensional interpolation. Lets start with the CPU version:","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"using CUDA\n\nstruct Interpolate{A}\n xs::A\n ys::A\nend\n\nfunction (itp::Interpolate)(x)\n i = searchsortedfirst(itp.xs, x)\n i = clamp(i, firstindex(itp.ys), lastindex(itp.ys))\n @inbounds itp.ys[i]\nend\n\nxs_cpu = [1.0, 2.0, 3.0]\nys_cpu = [10.0,20.0,30.0]\nitp_cpu = Interpolate(xs_cpu, ys_cpu)\npts_cpu = [1.1,2.3]\nresult_cpu = itp_cpu.(pts_cpu)","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"Ok the CPU code works, let's move our data to the GPU:","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"itp = Interpolate(CuArray(xs_cpu), CuArray(ys_cpu))\npts = CuArray(pts_cpu);\nnothing #hide","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"If we try to call our interpolate itp.(pts), we get an error however:","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"...\nKernelError: passing and using non-bitstype argument\n...","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"Why does it throw an error? Our calculation involves a custom type Interpolate{CuArray{Float64, 1}}. At the end of the day all arguments of a CUDA kernel need to be bitstypes. However we have","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"isbitstype(typeof(itp))","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"How to fix this? The answer is, that there is a conversion mechanism, which adapts objects into CUDA compatible bitstypes. It is based on the Adapt.jl package and basic types like CuArray already participate in this mechanism. For custom types, we just need to add a conversion rule like so:","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"import Adapt\nfunction Adapt.adapt_structure(to, itp::Interpolate)\n xs = Adapt.adapt_structure(to, itp.xs)\n ys = Adapt.adapt_structure(to, itp.ys)\n Interpolate(xs, ys)\nend","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"Now our struct plays nicely with CUDA.jl:","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"result = itp.(pts)","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"It works, we get the same result as on the CPU.","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"@assert CuArray(result_cpu) == result","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"Alternatively instead of defining Adapt.adapt_structure explictly, we could have done","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"Adapt.@adapt_structure Interpolate","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"which expands to the same code that we wrote manually.","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"","category":"page"},{"location":"tutorials/custom_structs/","page":"Using custom structs","title":"Using custom structs","text":"This page was generated using Literate.jl.","category":"page"},{"location":"development/debugging/#Debugging","page":"Debugging","title":"Debugging","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"Even if your kernel executes, it may be computing the wrong values, or even error at run time. To debug these issues, both CUDA.jl and the CUDA toolkit provide several utilities. These are generally low-level, since we generally cannot use the full extend of the Julia programming language and its tools within GPU kernels.","category":"page"},{"location":"development/debugging/#Adding-output-statements","page":"Debugging","title":"Adding output statements","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"The easiest, and often reasonably effective way to debug GPU code is to visualize intermediary computations using output functions. CUDA.jl provides several macros that facilitate this style of debugging:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"@cushow (like @show): to visualize an expression, its result, and return that value. This makes it easy to wrap expressions without disturbing their execution.\n@cuprintln (like println): to print text and values. This macro does support string interpolation, but the types it can print are restricted to C primitives.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"The @cuaassert macro (like @assert) can also be useful to find issues and abort execution.","category":"page"},{"location":"development/debugging/#Stack-trace-information","page":"Debugging","title":"Stack trace information","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"If you run into run-time exceptions, stack trace information will by default be very limited. For example, given the following out-of-bounds access:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"julia> function kernel(a)\n a[threadIdx().x] = 0\n return\n end\nkernel (generic function with 1 method)\n\njulia> @cuda threads=2 kernel(CuArray([1]))","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"If we execute this code, we'll get a very short error message:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"ERROR: a exception was thrown during kernel execution.\nRun Julia on debug level 2 for device stack traces.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"As the message suggests, we can have CUDA.jl emit more rich stack trace information by setting Julia's debug level to 2 or higher by passing -g2 to the julia invocation:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"ERROR: a exception was thrown during kernel execution.\nStacktrace:\n [1] throw_boundserror at abstractarray.jl:541\n [2] checkbounds at abstractarray.jl:506\n [3] arrayset at /home/tim/Julia/pkg/CUDA/src/device/array.jl:84\n [4] setindex! at /home/tim/Julia/pkg/CUDA/src/device/array.jl:101\n [5] kernel at REPL[4]:2","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"Note that these messages are embedded in the module (CUDA does not support stack unwinding), and thus bloat its size. To avoid any overhead, you can disable these messages by setting the debug level to 0 (passing -g0 to julia). This disabled any device-side message, but retains the host-side detection:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"julia> @cuda threads=2 kernel(CuArray([1]))\n# no device-side error message!\n\njulia> synchronize()\nERROR: KernelException: exception thrown during kernel execution","category":"page"},{"location":"development/debugging/#Debug-info-and-line-number-information","page":"Debugging","title":"Debug info and line-number information","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"Setting the debug level does not only enrich stack traces, it also changes the debug info emitted in the CUDA module. On debug level 1, which is the default setting if unspecified, CUDA.jl emits line number information corresponding to nvcc -lineinfo. This information does not hurt performance, and is used by a variety of tools to improve the debugging experience.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To emit actual debug info as nvcc -G does, you need to start Julia on debug level 2 by passing the flag -g2. Support for emitting PTX-compatible debug info is a recent addition to the NVPTX LLVM back-end, so it's possible this information is incorrect or otherwise affects compilation.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"warning: Warning\nDue to bugs in ptxas, you need CUDA 11.5 or higher for debug info support.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To disable all debug info emission, start Julia with the flag -g0.","category":"page"},{"location":"development/debugging/#compute-sanitizer","page":"Debugging","title":"compute-sanitizer","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To debug kernel issues like memory errors or race conditions, you can use CUDA's compute-sanitizer tool. Refer to the manual for more information.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To facilitate using the compute sanitizer, CUDA.jl ships the tool as part of its artifacts. You can get the path to the tool using the following function:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"julia> using CUDA\n\njulia> CUDA.compute_sanitizer()\n\".julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer\"\n\n# including recommended options for use with Julia and CUDA.jl\njulia> CUDA.compute_sanitizer_cmd()\n`.julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer --tool memcheck --launch-timeout=0 --target-processes=all --report-api-errors=no`","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To quickly spawn a new Julia session under compute-sanitizer, another helper function is provided:","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"julia> CUDA.run_compute_sanitizer()\nRe-starting your active Julia session...\n\n========= COMPUTE-SANITIZER\njulia> using CUDA\n\njulia> CuArray([1]) .+ 1\n1-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:\n 2\n\njulia> exit()\n========= ERROR SUMMARY: 0 errors\nProcess(`.julia/artifacts/7b09e1deca842d1e5467b6f7a8ec5a96d47ae0b4/bin/compute-sanitizer --tool memcheck --launch-timeout=0 --target-processes=all --report-api-errors=no julia -g1`, ProcessExited(0))","category":"page"},{"location":"development/debugging/#cuda-gdb","page":"Debugging","title":"cuda-gdb","text":"","category":"section"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"To debug Julia code, you can use the CUDA debugger cuda-gdb. When using this tool, it is recommended to enable Julia debug mode 2 so that debug information is emitted. Do note that the DWARF info emitted by Julia is currently insufficient to e.g. inspect variables, so the debug experience will not be pleasant.","category":"page"},{"location":"development/debugging/","page":"Debugging","title":"Debugging","text":"If you encounter the CUDBG_ERROR_UNINITIALIZED error, ensure all your devices are supported by cuda-gdb (e.g., Kepler-era devices aren't). If some aren't, re-start Julia with CUDA_VISIBLE_DEVICES set to ignore that device.","category":"page"},{"location":"#CUDA-programming-in-Julia","page":"Home","title":"CUDA programming in Julia","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The CUDA.jl package is the main entrypoint for programming NVIDIA GPUs in Julia. The package makes it possible to do so at various abstraction levels, from easy-to-use arrays down to hand-written kernels using low-level CUDA APIs.","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you have any questions, please feel free to use the #gpu channel on the Julia slack, or the GPU domain of the Julia Discourse.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For information on recent or upcoming changes, consult the NEWS.md document in the CUDA.jl repository.","category":"page"},{"location":"#Quick-Start","page":"Home","title":"Quick Start","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The Julia CUDA stack only requires a working NVIDIA driver; you don't need to install the entire CUDA toolkit, as it will automatically be downloaded when you first use the package:","category":"page"},{"location":"","page":"Home","title":"Home","text":"# install the package\nusing Pkg\nPkg.add(\"CUDA\")\n\n# smoke test (this will download the CUDA toolkit)\nusing CUDA\nCUDA.versioninfo()","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you want to ensure everything works as expected, you can execute the test suite. Note that this test suite is fairly exhaustive, taking around an hour to complete when using a single thread (multiple processes are used automatically based on the number of threads Julia is started with), and requiring significant amounts of CPU and GPU memory.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg\nPkg.test(\"CUDA\")\n\n# the test suite takes command-line options that allow customization; pass --help for details:\n#Pkg.test(\"CUDA\"; test_args=`--help`)","category":"page"},{"location":"","page":"Home","title":"Home","text":"For more details on the installation process, consult the Installation section. To understand the toolchain in more detail, have a look at the tutorials in this manual. It is highly recommended that new users start with the Introduction tutorial. For an overview of the available functionality, read the Usage section. The following resources may also be of interest:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Effectively using GPUs with Julia: video, slides\nHow Julia is compiled to GPUs: video","category":"page"},{"location":"#Acknowledgements","page":"Home","title":"Acknowledgements","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The Julia CUDA stack has been a collaborative effort by many individuals. Significant contributions have been made by the following individuals:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Tim Besard (@maleadt) (lead developer)\nValentin Churavy (@vchuravy)\nMike Innes (@MikeInnes)\nKatharine Hyatt (@kshyatt)\nSimon Danisch (@SimonDanisch)","category":"page"},{"location":"#Supporting-and-Citing","page":"Home","title":"Supporting and Citing","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Much of the software in this ecosystem was developed as part of academic research. If you would like to help support it, please star the repository as such metrics may help us secure funding in the future. If you use our software as part of your research, teaching, or other activities, we would be grateful if you could cite our work. The CITATION.bib file in the root of this repository lists the relevant papers.","category":"page"}] +} diff --git a/previews/PR2003/siteinfo.js b/previews/PR2003/siteinfo.js new file mode 100644 index 0000000000..4ca0a106e2 --- /dev/null +++ b/previews/PR2003/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR2003"; diff --git a/previews/PR2003/tutorials/common.jl b/previews/PR2003/tutorials/common.jl new file mode 100644 index 0000000000..4cbf1fec6f --- /dev/null +++ b/previews/PR2003/tutorials/common.jl @@ -0,0 +1,11 @@ +# function to run a Julia script outside of the current environment +function script(code; wrapper=``, args=``) + mktemp() do path, io + write(io, code) + flush(io) + cmd = `$wrapper $(Base.julia_cmd()) --project=$(Base.active_project()) $args $path` + # redirect stderr to stdout to have it picked up by Weave.jl + run(pipeline(ignorestatus(cmd), stderr=stdout)) + end + nothing +end diff --git a/previews/PR2003/tutorials/custom_structs.jl b/previews/PR2003/tutorials/custom_structs.jl new file mode 100644 index 0000000000..0646aaf75d --- /dev/null +++ b/previews/PR2003/tutorials/custom_structs.jl @@ -0,0 +1,56 @@ +# # Using custom structs +# +# This tutorial shows how to use custom structs on the GPU. Our example will be a one dimensional +# interpolation. Lets start with the CPU version: +using CUDA + +struct Interpolate{A} + xs::A + ys::A +end + +function (itp::Interpolate)(x) + i = searchsortedfirst(itp.xs, x) + i = clamp(i, firstindex(itp.ys), lastindex(itp.ys)) + @inbounds itp.ys[i] +end + +xs_cpu = [1.0, 2.0, 3.0] +ys_cpu = [10.0,20.0,30.0] +itp_cpu = Interpolate(xs_cpu, ys_cpu) +pts_cpu = [1.1,2.3] +result_cpu = itp_cpu.(pts_cpu) + +# Ok the CPU code works, let's move our data to the GPU: +itp = Interpolate(CuArray(xs_cpu), CuArray(ys_cpu)) +pts = CuArray(pts_cpu); +# If we try to call our interpolate `itp.(pts)`, we get an error however: +# ``` +# ... +# KernelError: passing and using non-bitstype argument +# ... +# ``` +# Why does it throw an error? Our calculation involves +# a custom type `Interpolate{CuArray{Float64, 1}}`. +# At the end of the day all arguments of a CUDA kernel need to +# be bitstypes. However we have +isbitstype(typeof(itp)) +# How to fix this? The answer is, that there is a conversion mechanism, which adapts objects into +# CUDA compatible bitstypes. +# It is based on the [Adapt.jl](https://github.com/JuliaGPU/Adapt.jl) package and basic types like `CuArray` already participate in this mechanism. For custom types, +# we just need to add a conversion rule like so: +import Adapt +function Adapt.adapt_structure(to, itp::Interpolate) + xs = Adapt.adapt_structure(to, itp.xs) + ys = Adapt.adapt_structure(to, itp.ys) + Interpolate(xs, ys) +end +# Now our struct plays nicely with CUDA.jl: +result = itp.(pts) +# It works, we get the same result as on the CPU. +@assert CuArray(result_cpu) == result +# Alternatively instead of defining `Adapt.adapt_structure` explictly, we could have done +# ```julia +# Adapt.@adapt_structure Interpolate +# ``` +# which expands to the same code that we wrote manually. diff --git a/previews/PR2003/tutorials/custom_structs/index.html b/previews/PR2003/tutorials/custom_structs/index.html new file mode 100644 index 0000000000..7f1c3fad44 --- /dev/null +++ b/previews/PR2003/tutorials/custom_structs/index.html @@ -0,0 +1,35 @@ + +Using custom structs · CUDA.jl

      Using custom structs

      This tutorial shows how to use custom structs on the GPU. Our example will be a one dimensional interpolation. Lets start with the CPU version:

      using CUDA
      +
      +struct Interpolate{A}
      +    xs::A
      +    ys::A
      +end
      +
      +function (itp::Interpolate)(x)
      +    i = searchsortedfirst(itp.xs, x)
      +    i = clamp(i, firstindex(itp.ys), lastindex(itp.ys))
      +    @inbounds itp.ys[i]
      +end
      +
      +xs_cpu = [1.0, 2.0, 3.0]
      +ys_cpu = [10.0,20.0,30.0]
      +itp_cpu = Interpolate(xs_cpu, ys_cpu)
      +pts_cpu = [1.1,2.3]
      +result_cpu = itp_cpu.(pts_cpu)
      2-element Vector{Float64}:
      + 20.0
      + 30.0

      Ok the CPU code works, let's move our data to the GPU:

      itp = Interpolate(CuArray(xs_cpu), CuArray(ys_cpu))
      +pts = CuArray(pts_cpu);

      If we try to call our interpolate itp.(pts), we get an error however:

      ...
      +KernelError: passing and using non-bitstype argument
      +...

      Why does it throw an error? Our calculation involves a custom type Interpolate{CuArray{Float64, 1}}. At the end of the day all arguments of a CUDA kernel need to be bitstypes. However we have

      isbitstype(typeof(itp))
      false

      How to fix this? The answer is, that there is a conversion mechanism, which adapts objects into CUDA compatible bitstypes. It is based on the Adapt.jl package and basic types like CuArray already participate in this mechanism. For custom types, we just need to add a conversion rule like so:

      import Adapt
      +function Adapt.adapt_structure(to, itp::Interpolate)
      +    xs = Adapt.adapt_structure(to, itp.xs)
      +    ys = Adapt.adapt_structure(to, itp.ys)
      +    Interpolate(xs, ys)
      +end

      Now our struct plays nicely with CUDA.jl:

      result = itp.(pts)
      2-element CuArray{Float64, 1, CUDA.Mem.DeviceBuffer}:
      + 20.0
      + 30.0

      It works, we get the same result as on the CPU.

      @assert CuArray(result_cpu) == result

      Alternatively instead of defining Adapt.adapt_structure explictly, we could have done

      Adapt.@adapt_structure Interpolate

      which expands to the same code that we wrote manually.


      This page was generated using Literate.jl.

      diff --git a/previews/PR2003/tutorials/intro1.png b/previews/PR2003/tutorials/intro1.png new file mode 100644 index 0000000000..e08a9addf1 Binary files /dev/null and b/previews/PR2003/tutorials/intro1.png differ diff --git a/previews/PR2003/tutorials/introduction.jl b/previews/PR2003/tutorials/introduction.jl new file mode 100644 index 0000000000..15404ed232 --- /dev/null +++ b/previews/PR2003/tutorials/introduction.jl @@ -0,0 +1,484 @@ +# # Introduction +# +# *A gentle introduction to parallelization and GPU programming in Julia* +# +# [Julia](https://julialang.org/) has first-class support for GPU programming: you can use +# high-level abstractions or obtain fine-grained control, all without ever leaving your +# favorite programming language. The purpose of this tutorial is to help Julia users take +# their first step into GPU computing. In this tutorial, you'll compare CPU and GPU +# implementations of a simple calculation, and learn about a few of the factors that +# influence the performance you obtain. +# +# This tutorial is inspired partly by a blog post by Mark Harris, [An Even Easier +# Introduction to CUDA](https://devblogs.nvidia.com/even-easier-introduction-cuda/), which +# introduced CUDA using the C++ programming language. You do not need to read that +# tutorial, as this one starts from the beginning. + + + +# ## A simple example on the CPU + +# We'll consider the following demo, a simple calculation on the CPU. + +N = 2^20 +x = fill(1.0f0, N) # a vector filled with 1.0 (Float32) +y = fill(2.0f0, N) # a vector filled with 2.0 + +y .+= x # increment each element of y with the corresponding element of x + +# check that we got the right answer +using Test +@test all(y .== 3.0f0) + +# From the `Test Passed` line we know everything is in order. We used `Float32` numbers in +# preparation for the switch to GPU computations: GPUs are faster (sometimes, much faster) +# when working with `Float32` than with `Float64`. + +# A distinguishing feature of this calculation is that every element of `y` is being +# updated using the same operation. This suggests that we might be able to parallelize +# this. + + +# ### Parallelization on the CPU + +# First let's do the parallelization on the CPU. We'll create a "kernel function" (the +# computational core of the algorithm) in two implementations, first a sequential version: + +function sequential_add!(y, x) + for i in eachindex(y, x) + @inbounds y[i] += x[i] + end + return nothing +end + +fill!(y, 2) +sequential_add!(y, x) +@test all(y .== 3.0f0) + +# And now a parallel implementation: + +function parallel_add!(y, x) + Threads.@threads for i in eachindex(y, x) + @inbounds y[i] += x[i] + end + return nothing +end + +fill!(y, 2) +parallel_add!(y, x) +@test all(y .== 3.0f0) + +# Now if I've started Julia with `JULIA_NUM_THREADS=4` on a machine with at least 4 cores, +# I get the following: + +@assert Threads.nthreads() == 4 #src + +# ```julia +# using BenchmarkTools +# @btime sequential_add!($y, $x) +# ``` + +# ``` +# 487.303 μs (0 allocations: 0 bytes) +# ``` + +# versus + +# ```julia +# @btime parallel_add!($y, $x) +# ``` + +# ``` +# 259.587 μs (13 allocations: 1.48 KiB) +# ``` + +# You can see there's a performance benefit to parallelization, though not by a factor of 4 +# due to the overhead for starting threads. With larger arrays, the overhead would be +# "diluted" by a larger amount of "real work"; these would demonstrate scaling that is +# closer to linear in the number of cores. Conversely, with small arrays, the parallel +# version might be slower than the serial version. + + + +# ## Your first GPU computation + +# ### Installation + +# For most of this tutorial you need to have a computer with a compatible GPU and have +# installed [CUDA](https://developer.nvidia.com/cuda-downloads). You should also install +# the following packages using Julia's [package +# manager](https://docs.julialang.org/en/v1/stdlib/Pkg/): + +# ```julia +# pkg> add CUDA +# ``` + +# If this is your first time, it's not a bad idea to test whether your GPU is working by +# testing the CUDA.jl package: + +# ```julia +# pkg> add CUDA +# pkg> test CUDA +# ``` + + +# ### Parallelization on the GPU + +# We'll first demonstrate GPU computations at a high level using the `CuArray` type, +# without explicitly writing a kernel function: + +using CUDA + +x_d = CUDA.fill(1.0f0, N) # a vector stored on the GPU filled with 1.0 (Float32) +y_d = CUDA.fill(2.0f0, N) # a vector stored on the GPU filled with 2.0 + +# Here the `d` means "device," in contrast with "host". Now let's do the increment: + +y_d .+= x_d +@test all(Array(y_d) .== 3.0f0) + +# The statement `Array(y_d)` moves the data in `y_d` back to the host for testing. If we +# want to benchmark this, let's put it in a function: + +function add_broadcast!(y, x) + CUDA.@sync y .+= x + return +end + +# ```julia +# @btime add_broadcast!($y_d, $x_d) +# ``` + +# ``` +# 67.047 μs (84 allocations: 2.66 KiB) +# ``` + +# The most interesting part of this is the call to `CUDA.@sync`. The CPU can assign +# jobs to the GPU and then go do other stuff (such as assigning *more* jobs to the GPU) +# while the GPU completes its tasks. Wrapping the execution in a `CUDA.@sync` block +# will make the CPU block until the queued GPU tasks are done, similar to how `Base.@sync` +# waits for distributed CPU tasks. Without such synchronization, you'd be measuring the +# time takes to launch the computation, not the time to perform the computation. But most +# of the time you don't need to synchronize explicitly: many operations, like copying +# memory from the GPU to the CPU, implicitly synchronize execution. + +# For this particular computer and GPU, you can see the GPU computation was significantly +# faster than the single-threaded CPU computation, and that the use of multiple CPU threads makes +# the CPU implementation competitive. Depending on your hardware you may get different +# results. + + +# ### Writing your first GPU kernel + +# Using the high-level GPU array functionality made it easy to perform this computation +# on the GPU. However, we didn't learn about what's going on under the hood, and that's the +# main goal of this tutorial. So let's implement the same functionality with a GPU kernel: + +function gpu_add1!(y, x) + for i = 1:length(y) + @inbounds y[i] += x[i] + end + return nothing +end + +fill!(y_d, 2) +@cuda gpu_add1!(y_d, x_d) +@test all(Array(y_d) .== 3.0f0) + +# Aside from using the `CuArray`s `x_d` and `y_d`, the only GPU-specific part of this is the +# *kernel launch* via `@cuda`. The first time you issue this `@cuda` statement, it will +# compile the kernel (`gpu_add1!`) for execution on the GPU. Once compiled, future +# invocations are fast. You can see what `@cuda` expands to using `?@cuda` from the Julia +# prompt. + +# Let's benchmark this: + +function bench_gpu1!(y, x) + CUDA.@sync begin + @cuda gpu_add1!(y, x) + end +end + +# ```julia +# @btime bench_gpu1!($y_d, $x_d) +# ``` + +# ``` +# 119.783 ms (47 allocations: 1.23 KiB) +# ``` + +# That's a *lot* slower than the version above based on broadcasting. What happened? + + +# ### Profiling + +# When you don't get the performance you expect, usually your first step should be to +# profile the code and see where it's spending its time. For that, you'll need to be able to +# run NVIDIA's [`nvprof` +# tool](https://devblogs.nvidia.com/cuda-pro-tip-nvprof-your-handy-universal-gpu-profiler/). +# On Unix systems, launch Julia this way: +# +# ```sh +# $ nvprof --profile-from-start off --openacc-profiling off /path/to/julia +# ``` +# +# replacing the `/path/to/julia` with the path to your Julia binary. Note that we don't +# immediately start the profiler, but instead call into the CUDA APIs and manually start the +# profiler with `CUDA.@profile` (thus excluding the time to compile our kernel): + +bench_gpu1!(y_d, x_d) # run it once to force compilation +CUDA.@profile bench_gpu1!(y_d, x_d) + +# When we quit the Julia REPL, the profiler process will print information about the +# executed kernels and API calls: + +# ``` +# ==2574== Profiling result: +# Type Time(%) Time Calls Avg Min Max Name +# GPU activities: 100.00% 247.61ms 1 247.61ms 247.61ms 247.61ms ptxcall_gpu_add1__1 +# API calls: 99.54% 247.83ms 1 247.83ms 247.83ms 247.83ms cuEventSynchronize +# 0.46% 1.1343ms 1 1.1343ms 1.1343ms 1.1343ms cuLaunchKernel +# 0.00% 4.9490us 1 4.9490us 4.9490us 4.9490us cuEventRecord +# 0.00% 4.4190us 1 4.4190us 4.4190us 4.4190us cuEventCreate +# 0.00% 960ns 2 480ns 358ns 602ns cuCtxGetCurrent +# ``` + +# You can see that 100% of the time was spent in `ptxcall_gpu_add1__1`, the name of the +# kernel that CUDA.jl assigned when compiling `gpu_add1!` for these inputs. (Had you created +# arrays of multiple data types, e.g., `xu_d = CUDA.fill(0x01, N)`, you might have also seen +# `ptxcall_gpu_add1__2` and so on. Like the rest of Julia, you can define a single method +# and it will be specialized at compile time for the particular data types you're using.) + +# For further insight, run the profiling with the option `--print-gpu-trace`. You can also +# invoke Julia with as argument the path to a file containing all commands you want to run +# (including a call to `CUDA.@profile`): +# +# ```sh +# $ nvprof --profile-from-start off --openacc-profiling off --print-gpu-trace /path/to/julia /path/to/script.jl +# Start Duration Grid Size Block Size Regs* SSMem* DSMem* Device Context Stream Name +# 13.3134s 245.04ms (1 1 1) (1 1 1) 20 0B 0B GeForce GTX TIT 1 7 ptxcall_gpu_add1__1 [34] +# ``` + +# The key thing to note here is the `(1 1 1)` in the "Grid Size" and "Block Size" columns. +# These terms will be explained shortly, but for now, suffice it to say that this is an +# indication that this computation ran sequentially. Of note, sequential processing with +# GPUs is much slower than with CPUs; where GPUs shine is with large-scale parallelism. + + +# ### Writing a parallel GPU kernel + +# To speed up the kernel, we want to parallelize it, which means assigning different tasks +# to different threads. To facilitate the assignment of work, each CUDA thread gets access +# to variables that indicate its own unique identity, much as +# [`Threads.threadid()`](https://docs.julialang.org/en/latest/manual/parallel-computing/#Multi-Threading-(Experimental)-1) +# does for CPU threads. The CUDA analogs of `threadid` and `nthreads` are called +# `threadIdx` and `blockDim`, respectively; one difference is that these return a +# 3-dimensional structure with fields `x`, `y`, and `z` to simplify cartesian indexing for +# up to 3-dimensional arrays. Consequently we can assign unique work in the following way: + +function gpu_add2!(y, x) + index = threadIdx().x # this example only requires linear indexing, so just use `x` + stride = blockDim().x + for i = index:stride:length(y) + @inbounds y[i] += x[i] + end + return nothing +end + +fill!(y_d, 2) +@cuda threads=256 gpu_add2!(y_d, x_d) +@test all(Array(y_d) .== 3.0f0) + +# Note the `threads=256` here, which divides the work among 256 threads numbered in a +# linear pattern. (For a two-dimensional array, we might have used `threads=(16, 16)` and +# then both `x` and `y` would be relevant.) + +# Now let's try benchmarking it: + +function bench_gpu2!(y, x) + CUDA.@sync begin + @cuda threads=256 gpu_add2!(y, x) + end +end + +# ```julia +# @btime bench_gpu2!($y_d, $x_d) +# ``` + +# ``` +# 1.873 ms (47 allocations: 1.23 KiB) +# ``` + +# Much better! + +# But obviously we still have a ways to go to match the initial broadcasting result. To do +# even better, we need to parallelize more. GPUs have a limited number of threads they can +# run on a single *streaming multiprocessor* (SM), but they also have multiple SMs. To take +# advantage of them all, we need to run a kernel with multiple *blocks*. We'll divide up +# the work like this: +# +# ![block grid](intro1.png) +# +# This diagram was [borrowed from a description of the C/C++ +# library](https://devblogs.nvidia.com/even-easier-introduction-cuda/); in Julia, threads +# and blocks begin numbering with 1 instead of 0. In this diagram, the 4096 blocks of 256 +# threads (making 1048576 = 2^20 threads) ensures that each thread increments just a single +# entry; however, to ensure that arrays of arbitrary size can be handled, let's still use a +# loop: + +function gpu_add3!(y, x) + index = (blockIdx().x - 1) * blockDim().x + threadIdx().x + stride = gridDim().x * blockDim().x + for i = index:stride:length(y) + @inbounds y[i] += x[i] + end + return +end + +numblocks = ceil(Int, N/256) + +fill!(y_d, 2) +@cuda threads=256 blocks=numblocks gpu_add3!(y_d, x_d) +@test all(Array(y_d) .== 3.0f0) + +# The benchmark: + +function bench_gpu3!(y, x) + numblocks = ceil(Int, length(y)/256) + CUDA.@sync begin + @cuda threads=256 blocks=numblocks gpu_add3!(y, x) + end +end + +# ```julia +# @btime bench_gpu3!($y_d, $x_d) +# ``` + +# ``` +# 67.268 μs (52 allocations: 1.31 KiB) +# ``` + +# Finally, we've achieved the similar performance to what we got with the broadcasted +# version. Let's run `nvprof` again to confirm this launch configuration: +# +# ``` +# ==23972== Profiling result: +# Start Duration Grid Size Block Size Regs* SSMem* DSMem* Device Context Stream Name +# 13.3526s 101.22us (4096 1 1) (256 1 1) 32 0B 0B GeForce GTX TIT 1 7 ptxcall_gpu_add3__1 [34] +# ``` + + +# In the previous example, the number of threads was hard-coded to 256. This is not ideal, +# as using more threads generally improves performance, but the maximum number of allowed +# threads to launch depends on your GPU as well as on the kernel. To automatically select an +# appropriate number of threads, it is recommended to use the launch configuration API. This +# API takes a compiled (but not launched) kernel, returns a tuple with an upper bound on the +# number of threads, and the minimum number of blocks that are required to fully saturate +# the GPU: + +kernel = @cuda launch=false gpu_add3!(y_d, x_d) +config = launch_configuration(kernel.fun) +threads = min(N, config.threads) +blocks = cld(N, threads) + +# The compiled kernel is callable, and we can pass the computed launch configuration as +# keyword arguments: + +fill!(y_d, 2) +kernel(y_d, x_d; threads, blocks) +@test all(Array(y_d) .== 3.0f0) + +# Now let's benchmark this: + +function bench_gpu4!(y, x) + kernel = @cuda launch=false gpu_add3!(y, x) + config = launch_configuration(kernel.fun) + threads = min(length(y), config.threads) + blocks = cld(length(y), threads) + + CUDA.@sync begin + kernel(y, x; threads, blocks) + end +end + +# ```julia +# @btime bench_gpu4!($y_d, $x_d) +# ``` + +# ``` +# 70.826 μs (99 allocations: 3.44 KiB) +# ``` + +# A comparable performance; slightly slower due to the use of the occupancy API, but that +# will not matter with more complex kernels. + + +# ### Printing + +# When debugging, it's not uncommon to want to print some values. This is achieved with +# `@cuprint`: + +function gpu_add2_print!(y, x) + index = threadIdx().x # this example only requires linear indexing, so just use `x` + stride = blockDim().x + @cuprintln("thread $index, block $stride") + for i = index:stride:length(y) + @inbounds y[i] += x[i] + end + return nothing +end + +@cuda threads=16 gpu_add2_print!(y_d, x_d) +synchronize() + +# Note that the printed output is only generated when synchronizing the entire GPU with +# `synchronize()`. This is similar to `CUDA.@sync`, and is the counterpart of +# `cudaDeviceSynchronize` in CUDA C++. + + +# ### Error-handling + +# The final topic of this intro concerns the handling of errors. Note that the kernels +# above used `@inbounds`, but did not check whether `y` and `x` have the same length. If +# your kernel does not respect these bounds, you will run into nasty errors: + +# ``` +# ERROR: CUDA error: an illegal memory access was encountered (code #700, ERROR_ILLEGAL_ADDRESS) +# Stacktrace: +# [1] ... +# ``` + +# If you remove the `@inbounds` annotation, instead you get +# +# ``` +# ERROR: a exception was thrown during kernel execution. +# Run Julia on debug level 2 for device stack traces. +# ``` + +# As the error message mentions, a higher level of debug information will result in a more +# detailed report. Let's run the same code with with `-g2`: +# +# ``` +# ERROR: a exception was thrown during kernel execution. +# Stacktrace: +# [1] throw_boundserror at abstractarray.jl:484 +# [2] checkbounds at abstractarray.jl:449 +# [3] setindex! at /home/tbesard/Julia/CUDA/src/device/array.jl:79 +# [4] some_kernel at /tmp/tmpIMYANH:6 +# ``` + +# !!! warning +# +# On older GPUs (with a compute capability below `sm_70`) these errors are fatal, +# and effectively kill the CUDA environment. On such GPUs, it's often a good idea to +# perform your "sanity checks" using code that runs on the CPU and only turn over the +# computation to the GPU once you've deemed it to be safe. + + + +# ## Summary + +# Keep in mind that the high-level functionality of CUDA often means that you don't +# need to worry about writing kernels at such a low level. However, there are many cases +# where computations can be optimized using clever low-level manipulations. Hopefully, you +# now feel comfortable taking the plunge. diff --git a/previews/PR2003/tutorials/introduction/index.html b/previews/PR2003/tutorials/introduction/index.html new file mode 100644 index 0000000000..0f02deb724 --- /dev/null +++ b/previews/PR2003/tutorials/introduction/index.html @@ -0,0 +1,184 @@ + +Introduction · CUDA.jl

      Introduction

      A gentle introduction to parallelization and GPU programming in Julia

      Julia has first-class support for GPU programming: you can use high-level abstractions or obtain fine-grained control, all without ever leaving your favorite programming language. The purpose of this tutorial is to help Julia users take their first step into GPU computing. In this tutorial, you'll compare CPU and GPU implementations of a simple calculation, and learn about a few of the factors that influence the performance you obtain.

      This tutorial is inspired partly by a blog post by Mark Harris, An Even Easier Introduction to CUDA, which introduced CUDA using the C++ programming language. You do not need to read that tutorial, as this one starts from the beginning.

      A simple example on the CPU

      We'll consider the following demo, a simple calculation on the CPU.

      N = 2^20
      +x = fill(1.0f0, N)  # a vector filled with 1.0 (Float32)
      +y = fill(2.0f0, N)  # a vector filled with 2.0
      +
      +y .+= x             # increment each element of y with the corresponding element of x
      1048576-element Vector{Float32}:
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + ⋮
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0
      + 3.0

      check that we got the right answer

      using Test
      +@test all(y .== 3.0f0)
      Test Passed

      From the Test Passed line we know everything is in order. We used Float32 numbers in preparation for the switch to GPU computations: GPUs are faster (sometimes, much faster) when working with Float32 than with Float64.

      A distinguishing feature of this calculation is that every element of y is being updated using the same operation. This suggests that we might be able to parallelize this.

      Parallelization on the CPU

      First let's do the parallelization on the CPU. We'll create a "kernel function" (the computational core of the algorithm) in two implementations, first a sequential version:

      function sequential_add!(y, x)
      +    for i in eachindex(y, x)
      +        @inbounds y[i] += x[i]
      +    end
      +    return nothing
      +end
      +
      +fill!(y, 2)
      +sequential_add!(y, x)
      +@test all(y .== 3.0f0)
      Test Passed

      And now a parallel implementation:

      function parallel_add!(y, x)
      +    Threads.@threads for i in eachindex(y, x)
      +        @inbounds y[i] += x[i]
      +    end
      +    return nothing
      +end
      +
      +fill!(y, 2)
      +parallel_add!(y, x)
      +@test all(y .== 3.0f0)
      Test Passed

      Now if I've started Julia with JULIA_NUM_THREADS=4 on a machine with at least 4 cores, I get the following:

      using BenchmarkTools
      +@btime sequential_add!($y, $x)
        487.303 μs (0 allocations: 0 bytes)

      versus

      @btime parallel_add!($y, $x)
        259.587 μs (13 allocations: 1.48 KiB)

      You can see there's a performance benefit to parallelization, though not by a factor of 4 due to the overhead for starting threads. With larger arrays, the overhead would be "diluted" by a larger amount of "real work"; these would demonstrate scaling that is closer to linear in the number of cores. Conversely, with small arrays, the parallel version might be slower than the serial version.

      Your first GPU computation

      Installation

      For most of this tutorial you need to have a computer with a compatible GPU and have installed CUDA. You should also install the following packages using Julia's package manager:

      pkg> add CUDA

      If this is your first time, it's not a bad idea to test whether your GPU is working by testing the CUDA.jl package:

      pkg> add CUDA
      +pkg> test CUDA

      Parallelization on the GPU

      We'll first demonstrate GPU computations at a high level using the CuArray type, without explicitly writing a kernel function:

      using CUDA
      +
      +x_d = CUDA.fill(1.0f0, N)  # a vector stored on the GPU filled with 1.0 (Float32)
      +y_d = CUDA.fill(2.0f0, N)  # a vector stored on the GPU filled with 2.0
      1048576-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + ⋮
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0
      + 2.0

      Here the d means "device," in contrast with "host". Now let's do the increment:

      y_d .+= x_d
      +@test all(Array(y_d) .== 3.0f0)
      Test Passed

      The statement Array(y_d) moves the data in y_d back to the host for testing. If we want to benchmark this, let's put it in a function:

      function add_broadcast!(y, x)
      +    CUDA.@sync y .+= x
      +    return
      +end
      add_broadcast! (generic function with 1 method)
      @btime add_broadcast!($y_d, $x_d)
        67.047 μs (84 allocations: 2.66 KiB)

      The most interesting part of this is the call to CUDA.@sync. The CPU can assign jobs to the GPU and then go do other stuff (such as assigning more jobs to the GPU) while the GPU completes its tasks. Wrapping the execution in a CUDA.@sync block will make the CPU block until the queued GPU tasks are done, similar to how Base.@sync waits for distributed CPU tasks. Without such synchronization, you'd be measuring the time takes to launch the computation, not the time to perform the computation. But most of the time you don't need to synchronize explicitly: many operations, like copying memory from the GPU to the CPU, implicitly synchronize execution.

      For this particular computer and GPU, you can see the GPU computation was significantly faster than the single-threaded CPU computation, and that the use of multiple CPU threads makes the CPU implementation competitive. Depending on your hardware you may get different results.

      Writing your first GPU kernel

      Using the high-level GPU array functionality made it easy to perform this computation on the GPU. However, we didn't learn about what's going on under the hood, and that's the main goal of this tutorial. So let's implement the same functionality with a GPU kernel:

      function gpu_add1!(y, x)
      +    for i = 1:length(y)
      +        @inbounds y[i] += x[i]
      +    end
      +    return nothing
      +end
      +
      +fill!(y_d, 2)
      +@cuda gpu_add1!(y_d, x_d)
      +@test all(Array(y_d) .== 3.0f0)
      Test Passed

      Aside from using the CuArrays x_d and y_d, the only GPU-specific part of this is the kernel launch via @cuda. The first time you issue this @cuda statement, it will compile the kernel (gpu_add1!) for execution on the GPU. Once compiled, future invocations are fast. You can see what @cuda expands to using ?@cuda from the Julia prompt.

      Let's benchmark this:

      function bench_gpu1!(y, x)
      +    CUDA.@sync begin
      +        @cuda gpu_add1!(y, x)
      +    end
      +end
      bench_gpu1! (generic function with 1 method)
      @btime bench_gpu1!($y_d, $x_d)
        119.783 ms (47 allocations: 1.23 KiB)

      That's a lot slower than the version above based on broadcasting. What happened?

      Profiling

      When you don't get the performance you expect, usually your first step should be to profile the code and see where it's spending its time. For that, you'll need to be able to run NVIDIA's nvprof tool. On Unix systems, launch Julia this way:

      $ nvprof --profile-from-start off --openacc-profiling off /path/to/julia

      replacing the /path/to/julia with the path to your Julia binary. Note that we don't immediately start the profiler, but instead call into the CUDA APIs and manually start the profiler with CUDA.@profile (thus excluding the time to compile our kernel):

      bench_gpu1!(y_d, x_d)  # run it once to force compilation
      +CUDA.@profile bench_gpu1!(y_d, x_d)
      CUDA.HostKernel for gpu_add1!(CuDeviceVector{Float32, 1}, CuDeviceVector{Float32, 1})

      When we quit the Julia REPL, the profiler process will print information about the executed kernels and API calls:

      ==2574== Profiling result:
      +            Type  Time(%)      Time     Calls       Avg       Min       Max  Name
      + GPU activities:  100.00%  247.61ms         1  247.61ms  247.61ms  247.61ms  ptxcall_gpu_add1__1
      +      API calls:   99.54%  247.83ms         1  247.83ms  247.83ms  247.83ms  cuEventSynchronize
      +                    0.46%  1.1343ms         1  1.1343ms  1.1343ms  1.1343ms  cuLaunchKernel
      +                    0.00%  4.9490us         1  4.9490us  4.9490us  4.9490us  cuEventRecord
      +                    0.00%  4.4190us         1  4.4190us  4.4190us  4.4190us  cuEventCreate
      +                    0.00%     960ns         2     480ns     358ns     602ns  cuCtxGetCurrent

      You can see that 100% of the time was spent in ptxcall_gpu_add1__1, the name of the kernel that CUDA.jl assigned when compiling gpu_add1! for these inputs. (Had you created arrays of multiple data types, e.g., xu_d = CUDA.fill(0x01, N), you might have also seen ptxcall_gpu_add1__2 and so on. Like the rest of Julia, you can define a single method and it will be specialized at compile time for the particular data types you're using.)

      For further insight, run the profiling with the option --print-gpu-trace. You can also invoke Julia with as argument the path to a file containing all commands you want to run (including a call to CUDA.@profile):

      $ nvprof --profile-from-start off --openacc-profiling off --print-gpu-trace /path/to/julia /path/to/script.jl
      +     Start  Duration   Grid Size   Block Size     Regs*    SSMem*    DSMem*           Device   Context    Stream  Name
      +  13.3134s  245.04ms     (1 1 1)      (1 1 1)        20        0B        0B  GeForce GTX TIT         1         7  ptxcall_gpu_add1__1 [34]

      The key thing to note here is the (1 1 1) in the "Grid Size" and "Block Size" columns. These terms will be explained shortly, but for now, suffice it to say that this is an indication that this computation ran sequentially. Of note, sequential processing with GPUs is much slower than with CPUs; where GPUs shine is with large-scale parallelism.

      Writing a parallel GPU kernel

      To speed up the kernel, we want to parallelize it, which means assigning different tasks to different threads. To facilitate the assignment of work, each CUDA thread gets access to variables that indicate its own unique identity, much as Threads.threadid() does for CPU threads. The CUDA analogs of threadid and nthreads are called threadIdx and blockDim, respectively; one difference is that these return a 3-dimensional structure with fields x, y, and z to simplify cartesian indexing for up to 3-dimensional arrays. Consequently we can assign unique work in the following way:

      function gpu_add2!(y, x)
      +    index = threadIdx().x    # this example only requires linear indexing, so just use `x`
      +    stride = blockDim().x
      +    for i = index:stride:length(y)
      +        @inbounds y[i] += x[i]
      +    end
      +    return nothing
      +end
      +
      +fill!(y_d, 2)
      +@cuda threads=256 gpu_add2!(y_d, x_d)
      +@test all(Array(y_d) .== 3.0f0)
      Test Passed

      Note the threads=256 here, which divides the work among 256 threads numbered in a linear pattern. (For a two-dimensional array, we might have used threads=(16, 16) and then both x and y would be relevant.)

      Now let's try benchmarking it:

      function bench_gpu2!(y, x)
      +    CUDA.@sync begin
      +        @cuda threads=256 gpu_add2!(y, x)
      +    end
      +end
      bench_gpu2! (generic function with 1 method)
      @btime bench_gpu2!($y_d, $x_d)
        1.873 ms (47 allocations: 1.23 KiB)

      Much better!

      But obviously we still have a ways to go to match the initial broadcasting result. To do even better, we need to parallelize more. GPUs have a limited number of threads they can run on a single streaming multiprocessor (SM), but they also have multiple SMs. To take advantage of them all, we need to run a kernel with multiple blocks. We'll divide up the work like this:

      block grid

      This diagram was borrowed from a description of the C/C++ library; in Julia, threads and blocks begin numbering with 1 instead of 0. In this diagram, the 4096 blocks of 256 threads (making 1048576 = 2^20 threads) ensures that each thread increments just a single entry; however, to ensure that arrays of arbitrary size can be handled, let's still use a loop:

      function gpu_add3!(y, x)
      +    index = (blockIdx().x - 1) * blockDim().x + threadIdx().x
      +    stride = gridDim().x * blockDim().x
      +    for i = index:stride:length(y)
      +        @inbounds y[i] += x[i]
      +    end
      +    return
      +end
      +
      +numblocks = ceil(Int, N/256)
      +
      +fill!(y_d, 2)
      +@cuda threads=256 blocks=numblocks gpu_add3!(y_d, x_d)
      +@test all(Array(y_d) .== 3.0f0)
      Test Passed

      The benchmark:

      function bench_gpu3!(y, x)
      +    numblocks = ceil(Int, length(y)/256)
      +    CUDA.@sync begin
      +        @cuda threads=256 blocks=numblocks gpu_add3!(y, x)
      +    end
      +end
      bench_gpu3! (generic function with 1 method)
      @btime bench_gpu3!($y_d, $x_d)
        67.268 μs (52 allocations: 1.31 KiB)

      Finally, we've achieved the similar performance to what we got with the broadcasted version. Let's run nvprof again to confirm this launch configuration:

      ==23972== Profiling result:
      +   Start  Duration            Grid Size      Block Size     Regs*    SSMem*    DSMem*           Device   Context    Stream  Name
      +13.3526s  101.22us           (4096 1 1)       (256 1 1)        32        0B        0B  GeForce GTX TIT         1         7  ptxcall_gpu_add3__1 [34]

      In the previous example, the number of threads was hard-coded to 256. This is not ideal, as using more threads generally improves performance, but the maximum number of allowed threads to launch depends on your GPU as well as on the kernel. To automatically select an appropriate number of threads, it is recommended to use the launch configuration API. This API takes a compiled (but not launched) kernel, returns a tuple with an upper bound on the number of threads, and the minimum number of blocks that are required to fully saturate the GPU:

      kernel = @cuda launch=false gpu_add3!(y_d, x_d)
      +config = launch_configuration(kernel.fun)
      +threads = min(N, config.threads)
      +blocks = cld(N, threads)
      1024

      The compiled kernel is callable, and we can pass the computed launch configuration as keyword arguments:

      fill!(y_d, 2)
      +kernel(y_d, x_d; threads, blocks)
      +@test all(Array(y_d) .== 3.0f0)
      Test Passed

      Now let's benchmark this:

      function bench_gpu4!(y, x)
      +    kernel = @cuda launch=false gpu_add3!(y, x)
      +    config = launch_configuration(kernel.fun)
      +    threads = min(length(y), config.threads)
      +    blocks = cld(length(y), threads)
      +
      +    CUDA.@sync begin
      +        kernel(y, x; threads, blocks)
      +    end
      +end
      bench_gpu4! (generic function with 1 method)
      @btime bench_gpu4!($y_d, $x_d)
        70.826 μs (99 allocations: 3.44 KiB)

      A comparable performance; slightly slower due to the use of the occupancy API, but that will not matter with more complex kernels.

      Printing

      When debugging, it's not uncommon to want to print some values. This is achieved with @cuprint:

      function gpu_add2_print!(y, x)
      +    index = threadIdx().x    # this example only requires linear indexing, so just use `x`
      +    stride = blockDim().x
      +    @cuprintln("thread $index, block $stride")
      +    for i = index:stride:length(y)
      +        @inbounds y[i] += x[i]
      +    end
      +    return nothing
      +end
      +
      +@cuda threads=16 gpu_add2_print!(y_d, x_d)
      +synchronize()
      thread 1, block 16
      +thread 2, block 16
      +thread 3, block 16
      +thread 4, block 16
      +thread 5, block 16
      +thread 6, block 16
      +thread 7, block 16
      +thread 8, block 16
      +thread 9, block 16
      +thread 10, block 16
      +thread 11, block 16
      +thread 12, block 16
      +thread 13, block 16
      +thread 14, block 16
      +thread 15, block 16
      +thread 16, block 16

      Note that the printed output is only generated when synchronizing the entire GPU with synchronize(). This is similar to CUDA.@sync, and is the counterpart of cudaDeviceSynchronize in CUDA C++.

      Error-handling

      The final topic of this intro concerns the handling of errors. Note that the kernels above used @inbounds, but did not check whether y and x have the same length. If your kernel does not respect these bounds, you will run into nasty errors:

      ERROR: CUDA error: an illegal memory access was encountered (code #700, ERROR_ILLEGAL_ADDRESS)
      +Stacktrace:
      + [1] ...

      If you remove the @inbounds annotation, instead you get

      ERROR: a exception was thrown during kernel execution.
      +       Run Julia on debug level 2 for device stack traces.

      As the error message mentions, a higher level of debug information will result in a more detailed report. Let's run the same code with with -g2:

      ERROR: a exception was thrown during kernel execution.
      +Stacktrace:
      + [1] throw_boundserror at abstractarray.jl:484
      + [2] checkbounds at abstractarray.jl:449
      + [3] setindex! at /home/tbesard/Julia/CUDA/src/device/array.jl:79
      + [4] some_kernel at /tmp/tmpIMYANH:6
      Warning

      On older GPUs (with a compute capability below sm_70) these errors are fatal, and effectively kill the CUDA environment. On such GPUs, it's often a good idea to perform your "sanity checks" using code that runs on the CPU and only turn over the computation to the GPU once you've deemed it to be safe.

      Summary

      Keep in mind that the high-level functionality of CUDA often means that you don't need to worry about writing kernels at such a low level. However, there are many cases where computations can be optimized using clever low-level manipulations. Hopefully, you now feel comfortable taking the plunge.


      This page was generated using Literate.jl.

      diff --git a/previews/PR2003/usage/array/index.html b/previews/PR2003/usage/array/index.html new file mode 100644 index 0000000000..ddfb9b2d4a --- /dev/null +++ b/previews/PR2003/usage/array/index.html @@ -0,0 +1,253 @@ + +Array programming · CUDA.jl

      Array programming

      The easiest way to use the GPU's massive parallelism, is by expressing operations in terms of arrays: CUDA.jl provides an array type, CuArray, and many specialized array operations that execute efficiently on the GPU hardware. In this section, we will briefly demonstrate use of the CuArray type. Since we expose CUDA's functionality by implementing existing Julia interfaces on the CuArray type, you should refer to the upstream Julia documentation for more information on these operations.

      If you encounter missing functionality, or are running into operations that trigger so-called "scalar iteration", have a look at the issue tracker and file a new issue if there's none. Do note that you can always access the underlying CUDA APIs by calling into the relevant submodule. For example, if parts of the Random interface isn't properly implemented by CUDA.jl, you can look at the CURAND documentation and possibly call methods from the CURAND submodule directly. These submodules are available after importing the CUDA package.

      Construction and Initialization

      The CuArray type aims to implement the AbstractArray interface, and provide implementations of methods that are commonly used when working with arrays. That means you can construct CuArrays in the same way as regular Array objects:

      julia> CuArray{Int}(undef, 2)
      +2-element CuArray{Int64, 1}:
      + 0
      + 0
      +
      +julia> CuArray{Int}(undef, (1,2))
      +1×2 CuArray{Int64, 2}:
      + 0  0
      +
      +julia> similar(ans)
      +1×2 CuArray{Int64, 2}:
      + 0  0

      Copying memory to or from the GPU can be expressed using constructors as well, or by calling copyto!:

      julia> a = CuArray([1,2])
      +2-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 1
      + 2
      +
      +julia> b = Array(a)
      +2-element Vector{Int64}:
      + 1
      + 2
      +
      +julia> copyto!(b, a)
      +2-element Vector{Int64}:
      + 1
      + 2

      Higher-order abstractions

      The real power of programming GPUs with arrays comes from Julia's higher-order array abstractions: Operations that take user code as an argument, and specialize execution on it. With these functions, you can often avoid having to write custom kernels. For example, to perform simple element-wise operations you can use map or broadcast:

      julia> a = CuArray{Float32}(undef, (1,2));
      +
      +julia> a .= 5
      +1×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 5.0  5.0
      +
      +julia> map(sin, a)
      +1×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + -0.958924  -0.958924

      To reduce the dimensionality of arrays, CUDA.jl implements the various flavours of (map)reduce(dim):

      julia> a = CUDA.ones(2,3)
      +2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 1.0  1.0  1.0
      + 1.0  1.0  1.0
      +
      +julia> reduce(+, a)
      +6.0f0
      +
      +julia> mapreduce(sin, *, a; dims=2)
      +2×1 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.59582335
      + 0.59582335
      +
      +julia> b = CUDA.zeros(1)
      +1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.0
      +
      +julia> Base.mapreducedim!(identity, +, b, a)
      +1×1 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 6.0

      To retain intermediate values, you can use accumulate:

      julia> a = CUDA.ones(2,3)
      +2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 1.0  1.0  1.0
      + 1.0  1.0  1.0
      +
      +julia> accumulate(+, a; dims=2)
      +2×3 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 1.0  2.0  3.0
      + 1.0  2.0  3.0

      Be wary that the operator f of accumulate, accumulate!, scan and scan! must be associative since the operation is performed in parallel. That is f(f(a,b)c) must be equivalent to f(a,f(b,c)). Accumulating with a non-associative operator on a CuArray will not produce the same result as on an Array.

      Logical operations

      CuArrays can also be indexed with arrays of boolean values to select items:

      julia> a = CuArray([1,2,3])
      +3-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 1
      + 2
      + 3
      +
      +julia> a[[false,true,false]]
      +1-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 2

      Built on top of this, are several functions with higher-level semantics:

      julia> a = CuArray([11,12,13])
      +3-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 11
      + 12
      + 13
      +
      +julia> findall(isodd, a)
      +2-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 1
      + 3
      +
      +julia> findfirst(isodd, a)
      +1
      +
      +julia> b = CuArray([11 12 13; 21 22 23])
      +2×3 CuArray{Int64, 2, CUDA.Mem.DeviceBuffer}:
      + 11  12  13
      + 21  22  23
      +
      +julia> findmin(b)
      +(11, CartesianIndex(1, 1))
      +
      +julia> findmax(b; dims=2)
      +([13; 23;;], CartesianIndex{2}[CartesianIndex(1, 3); CartesianIndex(2, 3);;])

      Array wrappers

      To some extent, CUDA.jl also supports well-known array wrappers from the standard library:

      julia> a = CuArray(collect(1:10))
      +10-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      +  1
      +  2
      +  3
      +  4
      +  5
      +  6
      +  7
      +  8
      +  9
      + 10
      +
      +julia> a = CuArray(collect(1:6))
      +6-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 1
      + 2
      + 3
      + 4
      + 5
      + 6
      +
      +julia> b = reshape(a, (2,3))
      +2×3 CuArray{Int64, 2, CUDA.Mem.DeviceBuffer}:
      + 1  3  5
      + 2  4  6
      +
      +julia> c = view(a, 2:5)
      +4-element CuArray{Int64, 1, CUDA.Mem.DeviceBuffer}:
      + 2
      + 3
      + 4
      + 5

      The above contiguous view and reshape have been specialized to return new objects of type CuArray. Other wrappers, such as non-contiguous views or the LinearAlgebra wrappers that will be discussed below, are implemented using their own type (e.g. SubArray or Transpose). This can cause problems, as calling methods with these wrapped objects will not dispatch to specialized CuArray methods anymore. That may result in a call to fallback functionality that performs scalar iteration.

      Certain common operations, like broadcast or matrix multiplication, do know how to deal with array wrappers by using the Adapt.jl package. This is still not a complete solution though, e.g. new array wrappers are not covered, and only one level of wrapping is supported. Sometimes the only solution is to materialize the wrapper to a CuArray again.

      Random numbers

      Base's convenience functions for generating random numbers are available in the CUDA module as well:

      julia> CUDA.rand(2)
      +2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.74021935
      + 0.9209938
      +
      +julia> CUDA.randn(Float64, 2, 1)
      +2×1 CuArray{Float64, 2, CUDA.Mem.DeviceBuffer}:
      + -0.3893830994647195
      +  1.618410515635752

      Behind the scenes, these random numbers come from two different generators: one backed by CURAND, another by kernels defined in CUDA.jl. Operations on these generators are implemented using methods from the Random standard library:

      julia> using Random
      +
      +julia> a = Random.rand(CURAND.default_rng(), Float32, 1)
      +1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.74021935
      +
      +julia> a = Random.rand!(CUDA.default_rng(), a)
      +1-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.46691537

      CURAND also supports generating lognormal and Poisson-distributed numbers:

      julia> CUDA.rand_logn(Float32, 1, 5; mean=2, stddev=20)
      +1×5 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 2567.61  4.256f-6  54.5948  0.00283999  9.81175f22
      +
      +julia> CUDA.rand_poisson(UInt32, 1, 10; lambda=100)
      +1×10 CuArray{UInt32, 2, CUDA.Mem.DeviceBuffer}:
      + 0x00000058  0x00000066  0x00000061  …  0x0000006b  0x0000005f  0x00000069

      Note that these custom operations are only supported on a subset of types.

      Linear algebra

      CUDA's linear algebra functionality from the CUBLAS library is exposed by implementing methods in the LinearAlgebra standard library:

      julia> # enable logging to demonstrate a CUBLAS kernel is used
      +       CUBLAS.cublasLoggerConfigure(1, 0, 1, C_NULL)
      +
      +julia> CUDA.rand(2,2) * CUDA.rand(2,2)
      +I! cuBLAS (v10.2) function cublasStatus_t cublasSgemm_v2(cublasContext*, cublasOperation_t, cublasOperation_t, int, int, int, const float*, const float*, int, const float*, int, const float*, float*, int) called
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.295727  0.479395
      + 0.624576  0.557361

      Certain operations, like the above matrix-matrix multiplication, also have a native fallback written in Julia for the purpose of working with types that are not supported by CUBLAS:

      julia> # enable logging to demonstrate no CUBLAS kernel is used
      +       CUBLAS.cublasLoggerConfigure(1, 0, 1, C_NULL)
      +
      +julia> CUDA.rand(Int128, 2, 2) * CUDA.rand(Int128, 2, 2)
      +2×2 CuArray{Int128, 2, CUDA.Mem.DeviceBuffer}:
      + -147256259324085278916026657445395486093  -62954140705285875940311066889684981211
      + -154405209690443624360811355271386638733  -77891631198498491666867579047988353207

      Operations that exist in CUBLAS, but are not (yet) covered by high-level constructs in the LinearAlgebra standard library, can be accessed directly from the CUBLAS submodule. Note that you do not need to call the C wrappers directly (e.g. cublasDdot), as many operations have more high-level wrappers available as well (e.g. dot):

      julia> x = CUDA.rand(2)
      +2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.74021935
      + 0.9209938
      +
      +julia> y = CUDA.rand(2)
      +2-element CuArray{Float32, 1, CUDA.Mem.DeviceBuffer}:
      + 0.03902049
      + 0.9689629
      +
      +julia> CUBLAS.dot(2, x, y)
      +0.92129254f0
      +
      +julia> using LinearAlgebra
      +
      +julia> dot(Array(x), Array(y))
      +0.92129254f0

      Solver

      LAPACK-like functionality as found in the CUSOLVER library can be accessed through methods in the LinearAlgebra standard library too:

      julia> using LinearAlgebra
      +
      +julia> a = CUDA.rand(2,2)
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.740219  0.0390205
      + 0.920994  0.968963
      +
      +julia> a = a * a'
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.549447  0.719547
      + 0.719547  1.78712
      +
      +julia> cholesky(a)
      +Cholesky{Float32, CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}}
      +U factor:
      +2×2 UpperTriangular{Float32, CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}}:
      + 0.741247  0.970725
      +  ⋅        0.919137

      Other operations are bound to the left-division operator:

      julia> a = CUDA.rand(2,2)
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.740219  0.0390205
      + 0.920994  0.968963
      +
      +julia> b = CUDA.rand(2,2)
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.925141  0.667319
      + 0.44635   0.109931
      +
      +julia> a \ b
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      +  1.29018    0.942772
      + -0.765663  -0.782648
      +
      +julia> Array(a) \ Array(b)
      +2×2 Matrix{Float32}:
      +  1.29018    0.942773
      + -0.765663  -0.782648

      Sparse arrays

      Sparse array functionality from the CUSPARSE library is mainly available through functionality from the SparseArrays package applied to CuSparseArray objects:

      julia> using SparseArrays
      +
      +julia> x = sprand(10,0.2)
      +10-element SparseVector{Float64, Int64} with 5 stored entries:
      +  [2 ]  =  0.538639
      +  [4 ]  =  0.89699
      +  [6 ]  =  0.258478
      +  [7 ]  =  0.338949
      +  [10]  =  0.424742
      +
      +julia> using CUDA.CUSPARSE
      +
      +julia> d_x = CuSparseVector(x)
      +10-element CuSparseVector{Float64, Int32} with 5 stored entries:
      +  [2 ]  =  0.538639
      +  [4 ]  =  0.89699
      +  [6 ]  =  0.258478
      +  [7 ]  =  0.338949
      +  [10]  =  0.424742
      +
      +julia> nonzeros(d_x)
      +5-element CuArray{Float64, 1, CUDA.Mem.DeviceBuffer}:
      + 0.538639413965653
      + 0.8969897902567084
      + 0.25847781536337067
      + 0.3389490517221738
      + 0.4247416640213063
      +
      +julia> nnz(d_x)
      +5

      For 2-D arrays the CuSparseMatrixCSC and CuSparseMatrixCSR can be used.

      Non-integrated functionality can be access directly in the CUSPARSE submodule again.

      FFTs

      Functionality from CUFFT is integrated with the interfaces from the AbstractFFTs.jl package:

      julia> a = CUDA.rand(2,2)
      +2×2 CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}:
      + 0.740219  0.0390205
      + 0.920994  0.968963
      +
      +julia> using CUDA.CUFFT
      +
      +julia> fft(a)
      +2×2 CuArray{ComplexF32, 2, CUDA.Mem.DeviceBuffer}:
      +   2.6692+0.0im   0.65323+0.0im
      + -1.11072+0.0im  0.749168+0.0im
      diff --git a/previews/PR2003/usage/memory/index.html b/previews/PR2003/usage/memory/index.html new file mode 100644 index 0000000000..f597578ef3 --- /dev/null +++ b/previews/PR2003/usage/memory/index.html @@ -0,0 +1,63 @@ + +Memory management · CUDA.jl

      Memory management

      A crucial aspect of working with a GPU is managing the data on it. The CuArray type is the primary interface for doing so: Creating a CuArray will allocate data on the GPU, copying elements to it will upload, and converting back to an Array will download values to the CPU:

      # generate some data on the CPU
      +cpu = rand(Float32, 1024)
      +
      +# allocate on the GPU
      +gpu = CuArray{Float32}(undef, 1024)
      +
      +# copy from the CPU to the GPU
      +copyto!(gpu, cpu)
      +
      +# download and verify
      +@test cpu == Array(gpu)

      A shorter way to accomplish these operations is to call the copy constructor, i.e. CuArray(cpu).

      Type-preserving upload

      In many cases, you might not want to convert your input data to a dense CuArray. For example, with array wrappers you will want to preserve that wrapper type on the GPU and only upload the contained data. The Adapt.jl package does exactly that, and contains a list of rules on how to unpack and reconstruct types like array wrappers so that we can preserve the type when, e.g., uploading data to the GPU:

      julia> cpu = Diagonal([1,2])     # wrapped data on the CPU
      +2×2 Diagonal{Int64,Array{Int64,1}}:
      + 1  ⋅
      + ⋅  2
      +
      +julia> using Adapt
      +
      +julia> gpu = adapt(CuArray, cpu) # upload to the GPU, keeping the wrapper intact
      +2×2 Diagonal{Int64,CuArray{Int64,1,Nothing}}:
      + 1  ⋅
      + ⋅  2

      Since this is a very common operation, the cu function conveniently does this for you:

      julia> cu(cpu)
      +2×2 Diagonal{Float32,CuArray{Float32,1,Nothing}}:
      + 1.0   ⋅
      +  ⋅   2.0
      Warning

      The cu function is opinionated and converts input most floating-point scalars to Float32. This is often a good call, as Float64 and many other scalar types perform badly on the GPU. If this is unwanted, use adapt directly.

      Garbage collection

      Instances of the CuArray type are managed by the Julia garbage collector. This means that they will be collected once they are unreachable, and the memory hold by it will be repurposed or freed. There is no need for manual memory management, just make sure your objects are not reachable (i.e., there are no instances or references).

      Memory pool

      Behind the scenes, a memory pool will hold on to your objects and cache the underlying memory to speed up future allocations. As a result, your GPU might seem to be running out of memory while it isn't. When memory pressure is high, the pool will automatically free cached objects:

      julia> CUDA.memory_status()             # initial state
      +Effective GPU memory usage: 16.12% (2.537 GiB/15.744 GiB)
      +Memory pool usage: 0 bytes (0 bytes reserved)
      +
      +julia> a = CuArray{Int}(undef, 1024);   # allocate 8KB
      +
      +julia> CUDA.memory_status()
      +Effective GPU memory usage: 16.35% (2.575 GiB/15.744 GiB)
      +Memory pool usage: 8.000 KiB (32.000 MiB reserved)
      +
      +julia> a = nothing; GC.gc(true)
      +
      +julia> CUDA.memory_status()             # 8KB is now cached
      +Effective GPU memory usage: 16.34% (2.573 GiB/15.744 GiB)
      +Memory pool usage: 0 bytes (32.000 MiB reserved)
      +

      If for some reason you need all cached memory to be reclaimed, call CUDA.reclaim():

      julia> CUDA.reclaim()
      +
      +julia> CUDA.memory_status()
      +Effective GPU memory usage: 16.17% (2.546 GiB/15.744 GiB)
      +Memory pool usage: 0 bytes (0 bytes reserved)
      Note

      It should never be required to manually reclaim memory before performing any high-level GPU array operation: Functionality that allocates should itself call into the memory pool and free any cached memory if necessary. It is a bug if that operation runs into an out-of-memory situation only if not manually reclaiming memory beforehand.

      Note

      If you need to disable the memory pool, e.g. because of incompatibility with certain CUDA APIs, set the environment variable JULIA_CUDA_MEMORY_POOL to none before importing CUDA.jl.

      Memory limits

      If you're sharing a GPU with other users or applications, you might want to limit how much memory is used. By default, CUDA.jl will configure the memory pool to use all available device memory. You can change this using two environment variables:

      • JULIA_CUDA_SOFT_MEMORY_LIMIT: This is an advisory limit, used to configure the memory pool. If you set this to a nonzero value, the memory pool will attempt to release cached memory until memory use falls below this limit. Note that this only happens at specific synchronization points, so memory use may temporarily exceed this limit. In addition, this limit is incompatible with JULIA_CUDA_MEMORY_POOL=none.
      • JULIA_CUDA_HARD_MEMORY_LIMIT: This is a hard limit, checked before every allocation. This incurs a certain cost, so it is recommended to first try to use the soft limit.

      The value of these variables can be formatted as a numer of bytes, optionally followed by a unit, or as a percentage of the total device memory. Examples: 100M, 50%, 1.5GiB, 10000.

      Avoiding GC pressure

      When your application performs a lot of memory operations, the time spent during GC might increase significantly. This happens more often than it does on the CPU because GPUs tend to have smaller memories and more frequently run out of it. When that happens, CUDA invokes the Julia garbage collector, which then needs to scan objects to see if they can be freed to get back some GPU memory.

      To avoid having to depend on the Julia GC to free up memory, you can directly inform CUDA.jl when an allocation can be freed (or reused) by calling the unsafe_free! method. Once you've done so, you cannot use that array anymore:

      julia> a = CuArray([1])
      +1-element CuArray{Int64,1,Nothing}:
      + 1
      +
      +julia> CUDA.unsafe_free!(a)
      +
      +julia> a
      +1-element CuArray{Int64,1,Nothing}:
      +Error showing value of type CuArray{Int64,1,Nothing}:
      +ERROR: AssertionError: Use of freed memory

      Batching iterator

      If you are dealing with data sets that are too large to fit on the GPU all at once, you can use CuIterator to batch operations:

      julia> batches = [([1], [2]), ([3], [4])]
      +
      +julia> for (batch, (a,b)) in enumerate(CuIterator(batches))
      +         println("Batch $batch: ", a .+ b)
      +       end
      +Batch 1: [3]
      +Batch 2: [7]

      For each batch, every argument (assumed to be an array-like) is uploaded to the GPU using the adapt mechanism from above. Afterwards, the memory is eagerly put back in the CUDA memory pool using unsafe_free! to lower GC pressure.

      diff --git a/previews/PR2003/usage/multigpu/index.html b/previews/PR2003/usage/multigpu/index.html new file mode 100644 index 0000000000..03052428ad --- /dev/null +++ b/previews/PR2003/usage/multigpu/index.html @@ -0,0 +1,66 @@ + +Multiple GPUs · CUDA.jl

      Multiple GPUs

      There are different ways of working with multiple GPUs: using one or more tasks, processes, or systems. Although all of these are compatible with the Julia CUDA toolchain, the support is a work in progress and the usability of some combinations can be significantly improved.

      Scenario 1: One GPU per process

      The easiest solution that maps well onto Julia's existing facilities for distributed programming, is to use one GPU per process

      # spawn one worker per device
      +using Distributed, CUDA
      +addprocs(length(devices()))
      +@everywhere using CUDA
      +
      +# assign devices
      +asyncmap((zip(workers(), devices()))) do (p, d)
      +    remotecall_wait(p) do
      +        @info "Worker $p uses $d"
      +        device!(d)
      +    end
      +end

      Communication between nodes should happen via the CPU (the CUDA IPC APIs are available as CUDA.cuIpcOpenMemHandle and friends, but not available through high-level wrappers).

      Alternatively, one can use MPI.jl together with an CUDA-aware MPI implementation. In that case, CuArray objects can be passed as send and receive buffers to point-to-point and collective operations to avoid going through the CPU.

      Scenario 2: Multiple GPUs per process

      In a similar vein to the multi-process solution, one can work with multiple devices from within a single process by calling CUDA.device! to switch to a specific device. Furthermore, as the active device is a task-local property you can easily work with multiple devices using one task per device. For more details, refer to the section on Tasks and threads.

      Warning

      You currently need to re-set the device at the start of every task, i.e., call device! as one of the first statement in your @async or @spawn block:

      @sync begin
      +    @async begin
      +        device!(0)
      +        # do work on GPU 0 here
      +    end
      +    @async begin
      +        device!(1)
      +        # do work on GPU 1 here
      +    end
      +end

      Without this, the newly-created task would use the same device as the previously-executing task, and not the parent task as could be expected. This is expected to be improved in the future using context variables.

      Memory management

      When working with multiple devices, you need to be careful with allocated memory: Allocations are tied to the device that was active when requesting the memory, and cannot be used with another device. That means you cannot allocate a CuArray, switch devices, and use that object. Similar restrictions apply to library objects, like CUFFT plans.

      To avoid this difficulty, you can use unified memory that is accessible from all devices. These APIs are available through high-level wrappers, but not exposed by the CuArray constructors yet:

      using CUDA
      +
      +gpus = Int(length(devices()))
      +
      +# generate CPU data
      +dims = (3,4,gpus)
      +a = round.(rand(Float32, dims) * 100)
      +b = round.(rand(Float32, dims) * 100)
      +
      +# CuArray doesn't support unified memory yet,
      +# so allocate our own buffers
      +buf_a = Mem.alloc(Mem.Unified, sizeof(a))
      +d_a = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_a), dims)
      +finalizer(d_a) do _
      +    Mem.free(buf_a)
      +end
      +copyto!(d_a, a)
      +
      +buf_b = Mem.alloc(Mem.Unified, sizeof(b))
      +d_b = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_b), dims)
      +finalizer(d_b) do _
      +    Mem.free(buf_b)
      +end
      +copyto!(d_b, b)
      +
      +buf_c = Mem.alloc(Mem.Unified, sizeof(a))
      +d_c = unsafe_wrap(CuArray{Float32,3}, convert(CuPtr{Float32}, buf_c), dims)
      +finalizer(d_c) do _
      +    Mem.free(buf_c)
      +end

      The data allocated here uses the GPU id as a the outermost dimension, which can be used to extract views of contiguous memory that represent the slice to be processed by a single GPU:

      for (gpu, dev) in enumerate(devices())
      +    device!(dev)
      +    @views d_c[:, :, gpu] .= d_a[:, :, gpu] .+ d_b[:, :, gpu]
      +end

      Before downloading the data, make sure to synchronize the devices:

      for dev in devices()
      +    # NOTE: normally you'd use events and wait for them
      +    device!(dev)
      +    synchronize()
      +end
      +
      +using Test
      +c = Array(d_c)
      +@test a+b ≈ c
      diff --git a/previews/PR2003/usage/multitasking/index.html b/previews/PR2003/usage/multitasking/index.html new file mode 100644 index 0000000000..36a79ace5a --- /dev/null +++ b/previews/PR2003/usage/multitasking/index.html @@ -0,0 +1,76 @@ + +Tasks and threads · CUDA.jl

      Tasks and threads

      CUDA.jl can be used with Julia tasks and threads, offering a convenient way to work with multiple devices, or to perform independent computations that may execute concurrently on the GPU.

      Task-based programming

      Each Julia task gets its own local CUDA execution environment, with its own stream, library handles, and active device selection. That makes it easy to use one task per device, or to use tasks for independent operations that can be overlapped. At the same time, it's important to take care when sharing data between tasks.

      For example, let's take some dummy expensive computation and execute it from two tasks:

      # an expensive computation
      +function compute(a, b)
      +    c = a * b             # library call
      +    broadcast!(sin, c, c) # Julia kernel
      +    c
      +end
      +
      +function run(a, b)
      +    results = Vector{Any}(undef, 2)
      +
      +    # computation
      +    @sync begin
      +        @async begin
      +            results[1] = Array(compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +        @async begin
      +            results[2] = Array(compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +    end
      +
      +    # comparison
      +    results[1] == results[2]
      +end

      We use familiar Julia constructs to create two tasks and re-synchronize afterwards (@async and @sync), while the dummy compute function demonstrates both the use of a library (matrix multiplication uses CUBLAS) and a native Julia kernel. The function is passed three GPU arrays filled with random numbers:

      function main(N=1024)
      +    a = CUDA.rand(N,N)
      +    b = CUDA.rand(N,N)
      +
      +    # make sure this data can be used by other tasks!
      +    synchronize()
      +
      +    run(a, b)
      +end

      The main function illustrates how we need to take care when sharing data between tasks: GPU operations typically execute asynchronously, queued on an execution stream, so if we switch tasks and thus switch execution streams we need to synchronize() to ensure the data is actually available.

      Using Nsight Systems, we can visualize the execution of this example:

      "Profiling overlapping execution using multiple tasks

      You can see how the two invocations of compute resulted in overlapping execution. The memory copies, however, were executed in serial. This is expected: Regular CPU arrays cannot be used for asynchronous operations, because their memory is not page-locked. For most applications, this does not matter as the time to compute will typically be much larger than the time to copy memory.

      If your application needs to perform many copies between the CPU and GPU, it might be beneficial to "pin" the CPU memory so that asynchronous memory copies are possible. This operation is expensive though, and should only be used if you can pre-allocate and re-use your CPU buffers. Applied to the previous example:

      function run(a, b)
      +    results = Vector{Any}(undef, 2)
      +
      +    # pre-allocate and pin destination CPU memory
      +    results[1] = Mem.pin(Array{eltype(a)}(undef, size(a)))
      +    results[2] = Mem.pin(Array{eltype(a)}(undef, size(a)))
      +
      +    # computation
      +    @sync begin
      +        @async begin
      +            copyto!(results[1], compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +        @async begin
      +            copyto!(results[2], compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +    end
      +
      +    # comparison
      +    results[1] == results[2]
      +end

      "Profiling overlapping execution using multiple tasks and pinned memory

      The profile reveals that the memory copies themselves could not be overlapped, but the first copy was executed while the GPU was still active with the second round of computations. Furthermore, the copies executed much quicker – if the memory were unpinned, it would first have to be staged to a pinned CPU buffer anyway.

      Multithreading

      Use of tasks can be easily extended to multiple threads with functionality from the Threads standard library:

      function run(a, b)
      +    results = Vector{Any}(undef, 2)
      +
      +    # computation
      +    @sync begin
      +        Threads.@spawn begin
      +            results[1] = Array(compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +        Threads.@spawn begin
      +            results[2] = Array(compute(a,b))
      +            nothing # JuliaLang/julia#40626
      +        end
      +    end
      +
      +    # comparison
      +    results[1] == results[2]
      +end

      By using the Threads.@spawn macro, the tasks will be scheduled to be run on different CPU threads. This can be useful when you are calling a lot of operations that "block" in CUDA, e.g., memory copies to or from unpinned memory. Generally though, operations that synchronize GPU execution (including the call to synchronize itself) are implemented in a way that they yield back to the Julia scheduler, to enable concurrent execution without requiring the use of different CPU threads.

      Warning

      Use of multiple threads with CUDA.jl is a recent addition, and there may still be bugs or performance issues.

      diff --git a/previews/PR2003/usage/multitasking/tasks.png b/previews/PR2003/usage/multitasking/tasks.png new file mode 100644 index 0000000000..500369e182 Binary files /dev/null and b/previews/PR2003/usage/multitasking/tasks.png differ diff --git a/previews/PR2003/usage/multitasking/tasks_pinned.png b/previews/PR2003/usage/multitasking/tasks_pinned.png new file mode 100644 index 0000000000..9b5be7e7ed Binary files /dev/null and b/previews/PR2003/usage/multitasking/tasks_pinned.png differ diff --git a/previews/PR2003/usage/overview/index.html b/previews/PR2003/usage/overview/index.html new file mode 100644 index 0000000000..3f06fbab93 --- /dev/null +++ b/previews/PR2003/usage/overview/index.html @@ -0,0 +1,34 @@ + +Overview · CUDA.jl

      Overview

      The CUDA.jl package provides three distinct, but related, interfaces for CUDA programming:

      • the CuArray type: for programming with arrays;
      • native kernel programming capabilities: for writing CUDA kernels in Julia;
      • CUDA API wrappers: for low-level interactions with the CUDA libraries.

      Much of the Julia CUDA programming stack can be used by just relying on the CuArray type, and using platform-agnostic programming patterns like broadcast and other array abstractions. Only once you hit a performance bottleneck, or some missing functionality, you might need to write a custom kernel or use the underlying CUDA APIs.

      The CuArray type

      The CuArray type is an essential part of the toolchain. Primarily, it is used to manage GPU memory, and copy data from and back to the CPU:

      a = CuArray{Int}(undef, 1024)
      +
      +# essential memory operations, like copying, filling, reshaping, ...
      +b = copy(a)
      +fill!(b, 0)
      +@test b == CUDA.zeros(Int, 1024)
      +
      +# automatic memory management
      +a = nothing

      Beyond memory management, there are a whole range of array operations to process your data. This includes several higher-order operations that take other code as arguments, such as map, reduce or broadcast. With these, it is possible to perform kernel-like operations without actually writing your own GPU kernels:

      a = CUDA.zeros(1024)
      +b = CUDA.ones(1024)
      +a.^2 .+ sin.(b)

      When possible, these operations integrate with existing vendor libraries such as CUBLAS and CURAND. For example, multiplying matrices or generating random numbers will automatically dispatch to these high-quality libraries, if types are supported, and fall back to generic implementations otherwise.

      For more details, refer to the section on Array programming.

      Kernel programming with @cuda

      If an operation cannot be expressed with existing functionality for CuArray, or you need to squeeze every last drop of performance out of your GPU, you can always write a custom kernel. Kernels are functions that are executed in a massively parallel fashion, and are launched by using the @cuda macro:

      a = CUDA.zeros(1024)
      +
      +function kernel(a)
      +    i = threadIdx().x
      +    a[i] += 1
      +    return
      +end
      +
      +@cuda threads=length(a) kernel(a)

      These kernels give you all the flexibility and performance a GPU has to offer, within a familiar language. However, not all of Julia is supported: you (generally) cannot allocate memory, I/O is disallowed, and badly-typed code will not compile. As a general rule of thumb, keep kernels simple, and only incrementally port code while continuously verifying that it still compiles and executes as expected.

      CUDA API wrappers

      For advanced use of the CUDA, you can use the driver API wrappers in CUDA.jl. Common operations include synchronizing the GPU, inspecting its properties, starting the profiler, etc. These operations are low-level, but for your convenience wrapped using high-level constructs. For example:

      CUDA.@profile begin
      +    # code that runs under the profiler
      +end
      +
      +# or
      +
      +for device in CUDA.devices()
      +    @show capability(device)
      +end

      If such high-level wrappers are missing, you can always access the underling C API (functions and structures prefixed with cu) without having to ever exit Julia:

      version = Ref{Cint}()
      +CUDA.cuDriverGetVersion(version)
      +@show version[]
      diff --git a/previews/PR2003/usage/workflow/index.html b/previews/PR2003/usage/workflow/index.html new file mode 100644 index 0000000000..04fc9dc051 --- /dev/null +++ b/previews/PR2003/usage/workflow/index.html @@ -0,0 +1,38 @@ + +Workflow · CUDA.jl

      Workflow

      A typical approach for porting or developing an application for the GPU is as follows:

      1. develop an application using generic array functionality, and test it on the CPU with the Array type
      2. port your application to the GPU by switching to the CuArray type
      3. disallow the CPU fallback ("scalar indexing") to find operations that are not implemented for or incompatible with GPU execution
      4. (optional) use lower-level, CUDA-specific interfaces to implement missing functionality or optimize performance

      Scalar indexing

      Many array operations in Julia are implemented using loops, processing one element at a time. Doing so with GPU arrays is very ineffective, as the loop won't actually execute on the GPU, but transfer one element at a time and process it on the CPU. As this wrecks performance, you will be warned when performing this kind of iteration:

      julia> a = CuArray([1])
      +1-element CuArray{Int64,1,Nothing}:
      + 1
      +
      +julia> a[1] += 1
      +┌ Warning: Performing scalar indexing.
      +│ ...
      +└ @ GPUArrays ~/Julia/pkg/GPUArrays/src/host/indexing.jl:57
      +2

      Scalar indexing is only allowed in an interactive session, e.g. the REPL, because it is convenient when porting CPU code to the GPU. If you want to disallow scalar indexing, e.g. to verify that your application executes correctly on the GPU, call the allowscalar function:

      julia> CUDA.allowscalar(false)
      +
      +julia> a[1] .+ 1
      +ERROR: scalar getindex is disallowed
      +Stacktrace:
      + [1] error(::String) at ./error.jl:33
      + [2] assertscalar(::String) at GPUArrays/src/indexing.jl:14
      + [3] getindex(::CuArray{Int64,1,Nothing}, ::Int64) at GPUArrays/src/indexing.jl:54
      + [4] top-level scope at REPL[5]:1
      +
      +julia> a .+ 1
      +1-element CuArray{Int64,1,Nothing}:
      + 2

      In a non-interactive session, e.g. when running code from a script or application, scalar indexing is disallowed by default. There is no global toggle to allow scalar indexing; if you really need it, you can mark expressions using allowscalar with do-block syntax or @allowscalar macro:

      julia> a = CuArray([1])
      +1-element CuArray{Int64, 1}:
      + 1
      +
      +julia> CUDA.allowscalar(false)
      +
      +julia> CUDA.allowscalar() do
      +         a[1] += 1
      +       end
      +2
      +
      +julia> CUDA.@allowscalar a[1] += 1
      +3