1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#![warn(missing_docs)]
//! CUDA/OpenCL code generator for finite-field arithmetic over prime fields and elliptic curve
//! arithmetic constructed with Rust.
//!
//! There is also support for Fast Fourier Transform and Multiexponentiation.
//!
//! This crate usually creates GPU kernels at compile-time. CUDA generates a [fatbin], which OpenCL only generates the source code, which is then compiled at run-time.
//!
//! In order to make things easier to use, there are helper functions available. You would put some code into `build.rs`, that generates the kernels, and some code into your library which then consumes those generated kernels. The kernels will be directly embedded into your program/library. If something goes wrong, you will get an error at compile-time.
//!
//! In this example we will make use of the FFT functionality. Add to your `build.rs`:
//!
//! ```no_run
//! use blstrs::Scalar;
//! use ec_gpu_gen::SourceBuilder;
//!
//! let source_builder = SourceBuilder::new().add_fft::<Scalar>();
//! ec_gpu_gen::generate(&source_builder);
//! ```
//!
//! The `ec_gpu_gen::generate()` takes care of the actual code generation/compilation. It will automatically create a CUDA and/or OpenCL kernel. It will define two environment variables, which are meant for internal use. `_EC_GPU_CUDA_KERNEL_FATBIN` that points to the compiled CUDA kernel, and `_EC_GPU_OPENCL_KERNEL_SOURCE` that points to the generated OpenCL source.
//!
//! Those variables are then picked up by the `ec_gpu_gen::program!()` macro, which generates a program, for a given GPU device. Using FFT within your library would then look like this:
//!
//! ```no_compile
//! use blstrs::Scalar;
//! use ec_gpu_gen::{
//!     rust_gpu_tools::Device,
//! };
//!
//! let devices = Device::all();
//! let programs = devices
//!     .iter()
//!     .map(|device| ec_gpu_gen::program!(device))
//!     .collect::<Result<_, _>>()
//!     .expect("Cannot create programs!");
//!
//! let mut kern = FftKernel::<Scalar>::create(programs).expect("Cannot initialize kernel!");
//! kern.radix_fft_many(&mut [&mut coeffs], &[omega], &[log_d]).expect("GPU FFT failed!");
//! ```
//!
//! Feature flags
//! -------------
//!
//! CUDA and OpenCL are supprted, each be enabled with the `cuda` and `opencl` [feature flags].
//!
//! [fatbin]: https://en.wikipedia.org/wiki/Fat_binary#Heterogeneous_computing
//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
mod error;
#[cfg(any(feature = "cuda", feature = "opencl"))]
mod program;
mod source;

/// Fast Fourier Transform on the GPU.
#[cfg(any(feature = "cuda", feature = "opencl"))]
pub mod fft;
/// Fast Fourier Transform on the CPU.
pub mod fft_cpu;
/// Multiexponentiation on the GPU.
#[cfg(any(feature = "cuda", feature = "opencl"))]
pub mod multiexp;
/// Multiexponentiation on the CPU.
pub mod multiexp_cpu;
/// Helpers for multithreaded code.
pub mod threadpool;

/// Re-export rust-gpu-tools as things like [`rust_gpu_tools::Device`] might be needed.
#[cfg(any(feature = "cuda", feature = "opencl"))]
pub use rust_gpu_tools;

pub use error::{EcError, EcResult};
pub use source::{generate, SourceBuilder};