public class JCufft extends Object
Modifier and Type | Field and Description |
---|---|
static int |
CUFFT_FORWARD
CUFFT transform direction
|
static int |
CUFFT_INVERSE
CUFFT transform direction
|
Modifier and Type | Method and Description |
---|---|
static int |
cufftCreate(cufftHandle cufftHandle) |
static int |
cufftDestroy(cufftHandle plan)
Frees all GPU resources associated with a CUFFT plan and destroys the
internal plan data structure.
|
static int |
cufftEstimate1d(int nx,
int type,
int batch,
long[] workSize) |
static int |
cufftEstimate2d(int nx,
int ny,
int type,
long[] workSize) |
static int |
cufftEstimate3d(int nx,
int ny,
int nz,
int type,
long[] workSize) |
static int |
cufftEstimateMany(int rank,
int[] n,
int[] inembed,
int istride,
int idist,
int[] onembed,
int ostride,
int odist,
int type,
int batch,
long[] workSize) |
static int |
cufftExecC2C(cufftHandle plan,
float[] cIdata,
float[] cOdata,
int direction)
Convenience method for
cufftExecC2C(cufftHandle, Pointer, Pointer, int) . |
static int |
cufftExecC2C(cufftHandle plan,
Pointer cIdata,
Pointer cOdata,
int direction)
Executes a CUFFT complex-to-complex transform plan.
|
static int |
cufftExecC2R(cufftHandle plan,
float[] cIdata,
float[] rOdata)
Convenience method for
cufftExecC2R(cufftHandle, Pointer, Pointer) . |
static int |
cufftExecC2R(cufftHandle plan,
Pointer cIdata,
Pointer rOdata)
Executes a CUFFT complex-to-real (implicitly inverse) transform plan.
|
static int |
cufftExecD2Z(cufftHandle plan,
double[] rIdata,
double[] cOdata)
Convenience method for
cufftExecD2Z(cufftHandle, Pointer, Pointer) . |
static int |
cufftExecD2Z(cufftHandle plan,
Pointer rIdata,
Pointer cOdata)
Executes a CUFFT real-to-complex (implicitly forward) transform plan
for double precision values.
|
static int |
cufftExecR2C(cufftHandle plan,
float[] rIdata,
float[] cOdata)
Convenience method for
cufftExecR2C(cufftHandle, Pointer, Pointer) . |
static int |
cufftExecR2C(cufftHandle plan,
Pointer rIdata,
Pointer cOdata)
Executes a CUFFT real-to-complex (implicitly forward) transform plan.
|
static int |
cufftExecZ2D(cufftHandle plan,
double[] cIdata,
double[] rOdata)
Convenience method for
cufftExecZ2D(cufftHandle, Pointer, Pointer) . |
static int |
cufftExecZ2D(cufftHandle plan,
Pointer cIdata,
Pointer rOdata)
Executes a CUFFT complex-to-real (implicitly inverse) transform plan
for double precision values.
|
static int |
cufftExecZ2Z(cufftHandle plan,
double[] cIdata,
double[] cOdata,
int direction)
Convenience method for
cufftExecZ2Z(cufftHandle, Pointer, Pointer, int) . |
static int |
cufftExecZ2Z(cufftHandle plan,
Pointer cIdata,
Pointer cOdata,
int direction)
Executes a CUFFT complex-to-complex transform plan for double precision
values.
|
static int |
cufftGetProperty(int type,
int[] value)
Obtains the value of the specified property.
|
static int |
cufftGetSize(cufftHandle handle,
long[] workSize) |
static int |
cufftGetSize1d(cufftHandle handle,
int nx,
int type,
int batch,
long[] workSize) |
static int |
cufftGetSize2d(cufftHandle handle,
int nx,
int ny,
int type,
long[] workSize) |
static int |
cufftGetSize3d(cufftHandle handle,
int nx,
int ny,
int nz,
int type,
long[] workSize) |
static int |
cufftGetSizeMany(cufftHandle handle,
int rank,
int[] n,
int[] inembed,
int istride,
int idist,
int[] onembed,
int ostride,
int odist,
int type,
int batch,
long[] workArea) |
static int |
cufftGetSizeMany64(cufftHandle plan,
int rank,
long[] n,
long[] inembed,
long istride,
long idist,
long[] onembed,
long ostride,
long odist,
int type,
long batch,
long[] workSize) |
static int |
cufftGetVersion(int[] version)
Writes the CUFFT version into the given argument.
|
static int |
cufftMakePlan1d(cufftHandle plan,
int nx,
int type,
int batch,
long[] workSize) |
static int |
cufftMakePlan2d(cufftHandle plan,
int nx,
int ny,
int type,
long[] workSize) |
static int |
cufftMakePlan3d(cufftHandle plan,
int nx,
int ny,
int nz,
int type,
long[] workSize) |
static int |
cufftMakePlanMany(cufftHandle plan,
int rank,
int[] n,
int[] inembed,
int istride,
int idist,
int[] onembed,
int ostride,
int odist,
int type,
int batch,
long[] workSize) |
static int |
cufftMakePlanMany64(cufftHandle plan,
int rank,
long[] n,
long[] inembed,
long istride,
long idist,
long[] onembed,
long ostride,
long odist,
int type,
long batch,
long[] workSize) |
static int |
cufftPlan1d(cufftHandle plan,
int nx,
int type,
int batch)
Creates a 1D FFT plan configuration for a specified signal size and data
type.
|
static int |
cufftPlan2d(cufftHandle plan,
int nx,
int ny,
int type)
Creates a 2D FFT plan configuration according to specified signal sizes
and data type.
|
static int |
cufftPlan3d(cufftHandle plan,
int nx,
int ny,
int nz,
int type)
Creates a 3D FFT plan configuration according to specified signal sizes
and data type.
|
static int |
cufftPlanMany(cufftHandle plan,
int rank,
int[] n,
int[] inembed,
int istride,
int idist,
int[] onembed,
int ostride,
int odist,
int type,
int batch)
Creates a FFT plan configuration of dimension rank, with sizes
specified in the array n.
|
static int |
cufftSetAutoAllocation(cufftHandle plan,
int autoAllocate) |
static int |
cufftSetCompatibilityMode(cufftHandle plan,
int mode)
Deprecated.
This function was removed in CUDA 9.1, and will throw
an UnsupportedOperationException
|
static int |
cufftSetStream(cufftHandle plan,
cudaStream_t stream)
Associates a CUDA stream with a CUFFT plan.
|
static int |
cufftSetWorkArea(cufftHandle plan,
Pointer workArea) |
static void |
initialize()
Initializes the native library.
|
static void |
setExceptionsEnabled(boolean enabled)
Enables or disables exceptions.
|
static void |
setLogLevel(LogLevel logLevel)
Set the specified log level for the JCufft library.
|
public static final int CUFFT_FORWARD
public static final int CUFFT_INVERSE
public static void initialize()
public static void setLogLevel(LogLevel logLevel)
logLevel
- The log level to use.public static void setExceptionsEnabled(boolean enabled)
enabled
- Whether exceptions are enabledpublic static int cufftGetVersion(int[] version)
version
- The versionpublic static int cufftGetProperty(int type, int[] value)
type
- The libraryPropertyType
value
- The valuepublic static int cufftPlan1d(cufftHandle plan, int nx, int type, int batch)
Creates a 1D FFT plan configuration for a specified signal size and data type. cufftResult cufftPlan1d( cufftHandle *plan, int nx, cufftType type, int batch ); The batch input parameter tells CUFFT how many 1D transforms to configure. Input ---- plan Pointer to a cufftHandle object nx The transform size (e.g., 256 for a 256-point FFT) type The transform data type (e.g., CUFFT_C2C for complex to complex) batch Number of transforms of size nx Output ---- plan Contains a CUFFT 1D plan handle value Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_SIZE The nx parameter is not a supported size. CUFFT_INVALID_TYPE The type parameter is not supported. CUFFT_ALLOC_FAILED Allocation of GPU resources for the plan failed. CUFFT_SUCCESS CUFFT successfully created the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurredNOTE: Batch sizes other than 1 for cufftPlan1d() have been deprecated as of CUDA 6.0RC. Use cufftPlanMany() for multiple batch execution.
public static int cufftPlan2d(cufftHandle plan, int nx, int ny, int type)
Creates a 2D FFT plan configuration according to specified signal sizes and data type. cufftResult cufftPlan2d( cufftHandle *plan, int nx, int ny, cufftType type ); This function is the same as cufftPlan1d() except that it takes a second size parameter, ny, and does not support batching. Input ---- plan Pointer to a cufftHandle object nx The transform size in the X dimension (number of rows) ny The transform size in the Y dimension (number of columns) type The transform data type (e.g., CUFFT_C2R for complex to real) Output ---- plan Contains a CUFFT 2D plan handle value Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_SIZE The nx or ny parameter is not a supported size. CUFFT_INVALID_TYPE The type parameter is not supported. CUFFT_ALLOC_FAILED Allocation of GPU resources for the plan failed. CUFFT_SUCCESS CUFFT successfully created the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftPlan3d(cufftHandle plan, int nx, int ny, int nz, int type)
Creates a 3D FFT plan configuration according to specified signal sizes and data type. cufftResult cufftPlan3d( cufftHandle *plan, int nx, int ny, int nz, cufftType type ); This function is the same as cufftPlan2d() except that it takes a third size parameter nz. Input ---- plan Pointer to a cufftHandle object nx The transform size in the X dimension ny The transform size in the Y dimension nz The transform size in the Z dimension type The transform data type (e.g., CUFFT_R2C for real to complex) Output ---- plan Contains a CUFFT 3D plan handle value Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_SIZE Parameter nx, ny, or nz is not a supported size. CUFFT_INVALID_TYPE The type parameter is not supported. CUFFT_ALLOC_FAILED Allocation of GPU resources for the plan failed. CUFFT_SUCCESS CUFFT successfully created the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftPlanMany(cufftHandle plan, int rank, int[] n, int[] inembed, int istride, int idist, int[] onembed, int ostride, int odist, int type, int batch)
Creates a FFT plan configuration of dimension rank, with sizes specified in the array n. cufftResult cufftPlanMany(cufftHandle *plan, int rank, int *n, int *inembed, int istride, int idist, int *onembed, int ostride, int odist, cufftType type, int batch ); The batch input parameter tells CUFFT how many transforms to configure in parallel. With this function, batched plans of any dimension may be created. Input parameters inembed, istride, and idist and output parameters onembed, ostride, and odist will allow setup of noncontiguous input data in a future version. Note that for CUFFT 3.0, these parameters are ignored and the layout of batched data must be side-by-side and not interleaved. Input ---- plan Pointer to a cufftHandle object rank Dimensionality of the transform (1, 2, or 3) n An array of size rank, describing the size of each dimension inembed Unused: pass NULL istride Unused: pass 1 idist Unused: pass 0 onembed Unused: pass NULL ostride Unused: pass 1 odist Unused: pass 0 type Transform data type (e.g., CUFFT_C2C, as per other CUFFT calls) batch Batch size for this transform Output ---- plan Contains a CUFFT plan handle Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_SIZE Parameter is not a supported size. CUFFT_INVALID_TYPE The type parameter is not supported
public static int cufftMakePlan1d(cufftHandle plan, int nx, int type, int batch, long[] workSize)
public static int cufftMakePlan2d(cufftHandle plan, int nx, int ny, int type, long[] workSize)
public static int cufftMakePlan3d(cufftHandle plan, int nx, int ny, int nz, int type, long[] workSize)
public static int cufftMakePlanMany(cufftHandle plan, int rank, int[] n, int[] inembed, int istride, int idist, int[] onembed, int ostride, int odist, int type, int batch, long[] workSize)
public static int cufftMakePlanMany64(cufftHandle plan, int rank, long[] n, long[] inembed, long istride, long idist, long[] onembed, long ostride, long odist, int type, long batch, long[] workSize)
public static int cufftGetSizeMany64(cufftHandle plan, int rank, long[] n, long[] inembed, long istride, long idist, long[] onembed, long ostride, long odist, int type, long batch, long[] workSize)
public static int cufftEstimate1d(int nx, int type, int batch, long[] workSize)
public static int cufftEstimate2d(int nx, int ny, int type, long[] workSize)
public static int cufftEstimate3d(int nx, int ny, int nz, int type, long[] workSize)
public static int cufftEstimateMany(int rank, int[] n, int[] inembed, int istride, int idist, int[] onembed, int ostride, int odist, int type, int batch, long[] workSize)
public static int cufftCreate(cufftHandle cufftHandle)
public static int cufftGetSize1d(cufftHandle handle, int nx, int type, int batch, long[] workSize)
public static int cufftGetSize2d(cufftHandle handle, int nx, int ny, int type, long[] workSize)
public static int cufftGetSize3d(cufftHandle handle, int nx, int ny, int nz, int type, long[] workSize)
public static int cufftGetSizeMany(cufftHandle handle, int rank, int[] n, int[] inembed, int istride, int idist, int[] onembed, int ostride, int odist, int type, int batch, long[] workArea)
public static int cufftGetSize(cufftHandle handle, long[] workSize)
public static int cufftSetWorkArea(cufftHandle plan, Pointer workArea)
public static int cufftSetAutoAllocation(cufftHandle plan, int autoAllocate)
public static int cufftDestroy(cufftHandle plan)
Frees all GPU resources associated with a CUFFT plan and destroys the internal plan data structure. cufftResult cufftDestroy( cufftHandle plan ); This function should be called once a plan is no longer needed to avoid wasting GPU memory. Input ---- plan The cufftHandle object of the plan to be destroyed. Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_SHUTDOWN_FAILED CUFFT library failed to shut down. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_SUCCESS CUFFT successfully destroyed the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftSetStream(cufftHandle plan, cudaStream_t stream)
Associates a CUDA stream with a CUFFT plan. cufftResult cufftSetStream( cufftHandle plan, cudaStream_t stream ); All kernel launches made during plan execution are now done through the associated stream, enabling overlap with activity in other streams (for example, data copying). The association remains until the plan is destroyed or the stream is changed with another call to cufftSetStream(). Input plan The cufftHandle object to associate with the stream stream A valid CUDA stream created with cudaStreamCreate() (or 0 for the default stream) Return Values CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_SUCCESS The stream was successfully associated with the plan.
public static int cufftSetCompatibilityMode(cufftHandle plan, int mode)
Configures the layout of CUFFT output in FFTW-compatible modes. When FFTW compatibility is desired, it can be configured for padding only, for asymmetric complex inputs only, or to be fully compatible. Input plan The cufftHandle object to associate with the stream mode The cufftCompatibility option to be used: CUFFT_COMPATIBILITY_NATIVE: Disable any FFTW compatibility mode. CUFFT_COMPATIBILITY_FFTW_PADDING: Support FFTW data padding. (Default) CUFFT_COMPATIBILITY_FFTW_ASYMMETRIC: Waive the C2R symmetry requirement. Should be used with asymmetric input. CUFFT_COMPATIBILITY_FFTW_ALL: Enable full FFTW compatibility. Return Values CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_SUCCESS CUFFT successfully executed the FFT plan.
public static int cufftExecC2C(cufftHandle plan, Pointer cIdata, Pointer cOdata, int direction)
Executes a CUFFT complex-to-complex transform plan. cufftResult cufftExecC2C( cufftHandle plan, cufftComplex *idata, cufftComplex *odata, int direction ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. This function stores the Fourier coefficients in the odata array. If idata and odata are the same, this method does an in-place transform. Input ---- plan The cufftHandle object for the plan to update idata Pointer to the input data (in GPU memory) to transform odata Pointer to the output data (in GPU memory) direction The transform direction: CUFFT_FORWARD or CUFFT_INVERSE Output ---- odata Contains the complex Fourier coefficients Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata, odata, and/or direction parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecC2C(cufftHandle plan, float[] cIdata, float[] cOdata, int direction)
cufftExecC2C(cufftHandle, Pointer, Pointer, int)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.public static int cufftExecR2C(cufftHandle plan, Pointer rIdata, Pointer cOdata)
Executes a CUFFT real-to-complex (implicitly forward) transform plan. cufftResult cufftExecR2C( cufftHandle plan, cufftReal *idata, cufftComplex *odata ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. This function stores the non-redundant Fourier coefficients in the odata array. If idata and odata are the same, this method does an in-place transform (See CUFFT documentation for details on real data FFTs.) Input ---- plan The cufftHandle object for the plan to update idata Pointer to the input data (in GPU memory) to transform odata Pointer to the output data (in GPU memory) direction The transform direction: CUFFT_FORWARD or CUFFT_INVERSE Output ---- odata Contains the complex Fourier coefficients Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata, odata, and/or direction parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecR2C(cufftHandle plan, float[] rIdata, float[] cOdata)
cufftExecR2C(cufftHandle, Pointer, Pointer)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.public static int cufftExecC2R(cufftHandle plan, Pointer cIdata, Pointer rOdata)
Executes a CUFFT complex-to-real (implicitly inverse) transform plan. cufftResult cufftExecC2R( cufftHandle plan, cufftComplex *idata, cufftReal *odata ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. The input array holds only the non-redundant complex Fourier coefficients. This function stores the real output values in the odata array. If idata and odata are the same, this method does an inplace transform. (See CUFFT documentation for details on real data FFTs.) Input ---- plan The cufftHandle object for the plan to update idata Pointer to the complex input data (in GPU memory) to transform odata Pointer to the real output data (in GPU memory) Output ---- odata Contains the real-valued output data Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata and/or odata parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecC2R(cufftHandle plan, float[] cIdata, float[] rOdata)
cufftExecC2R(cufftHandle, Pointer, Pointer)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.public static int cufftExecZ2Z(cufftHandle plan, Pointer cIdata, Pointer cOdata, int direction)
Executes a CUFFT complex-to-complex transform plan for double precision values. cufftResult cufftExecZ2Z( cufftHandle plan, cufftDoubleComplex *idata, cufftDoubleComplex *odata, int direction ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. This function stores the Fourier coefficients in the odata array. If idata and odata are the same, this method does an in-place transform. Input ---- plan The cufftHandle object for the plan to update idata Pointer to the input data (in GPU memory) to transform odata Pointer to the output data (in GPU memory) direction The transform direction: CUFFT_FORWARD or CUFFT_INVERSE Output ---- odata Contains the complex Fourier coefficients Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata, odata, and/or direction parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecZ2Z(cufftHandle plan, double[] cIdata, double[] cOdata, int direction)
cufftExecZ2Z(cufftHandle, Pointer, Pointer, int)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.public static int cufftExecD2Z(cufftHandle plan, Pointer rIdata, Pointer cOdata)
Executes a CUFFT real-to-complex (implicitly forward) transform plan for double precision values. cufftResult cufftExecD2Z( cufftHandle plan, cufftDoubleReal *idata, cufftDoubleComplex *odata ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. This function stores the non-redundant Fourier coefficients in the odata array. If idata and odata are the same, this method does an in-place transform (See CUFFT documentation for details on real data FFTs.) Input ---- plan The cufftHandle object for the plan to update idata Pointer to the input data (in GPU memory) to transform odata Pointer to the output data (in GPU memory) direction The transform direction: CUFFT_FORWARD or CUFFT_INVERSE Output ---- odata Contains the complex Fourier coefficients Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata, odata, and/or direction parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecD2Z(cufftHandle plan, double[] rIdata, double[] cOdata)
cufftExecD2Z(cufftHandle, Pointer, Pointer)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.public static int cufftExecZ2D(cufftHandle plan, Pointer cIdata, Pointer rOdata)
Executes a CUFFT complex-to-real (implicitly inverse) transform plan for double precision values. cufftResult cufftExecZ2D( cufftHandle plan, cufftDoubleComplex *idata, cufftDoubleReal *odata ); CUFFT uses as input data the GPU memory pointed to by the idata parameter. The input array holds only the non-redundant complex Fourier coefficients. This function stores the real output values in the odata array. If idata and odata are the same, this method does an inplace transform. (See CUFFT documentation for details on real data FFTs.) Input ---- plan The cufftHandle object for the plan to update idata Pointer to the complex input data (in GPU memory) to transform odata Pointer to the real output data (in GPU memory) Output ---- odata Contains the real-valued output data Return Values ---- CUFFT_SETUP_FAILED CUFFT library failed to initialize. CUFFT_INVALID_PLAN The plan parameter is not a valid handle. CUFFT_INVALID_VALUE The idata and/or odata parameter is not valid. CUFFT_EXEC_FAILED CUFFT failed to execute the transform on GPU. CUFFT_SUCCESS CUFFT successfully executed the FFT plan. JCUFFT_INTERNAL_ERROR If an internal JCufft error occurred
public static int cufftExecZ2D(cufftHandle plan, double[] cIdata, double[] rOdata)
cufftExecZ2D(cufftHandle, Pointer, Pointer)
.
Accepts arrays for input and output data and automatically performs the host-device
and device-host copies.Copyright © 2020. All rights reserved.