{"id":24647004,"url":"https://github.com/typember/ndarray-conv","last_synced_at":"2025-05-12T23:10:26.249Z","repository":{"id":64727074,"uuid":"577583981","full_name":"TYPEmber/ndarray-conv","owner":"TYPEmber","description":"N-Dimension convolution (with FFT acceleration) library in pure Rust.","archived":false,"fork":false,"pushed_at":"2025-05-03T05:07:37.000Z","size":228,"stargazers_count":11,"open_issues_count":1,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-03T05:16:30.711Z","etag":null,"topics":["convolution","fft","rust"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/ndarray-conv","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TYPEmber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-12-13T03:56:51.000Z","updated_at":"2025-05-03T05:07:40.000Z","dependencies_parsed_at":"2024-05-05T17:35:42.304Z","dependency_job_id":"09315e36-2f01-4fb4-9d45-54e645c8fbad","html_url":"https://github.com/TYPEmber/ndarray-conv","commit_stats":{"total_commits":55,"total_committers":4,"mean_commits":13.75,"dds":0.5636363636363637,"last_synced_commit":"583b670f03711e1156edc656ebbf3a92c7f286ec"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TYPEmber%2Fndarray-conv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TYPEmber%2Fndarray-conv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TYPEmber%2Fndarray-conv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TYPEmber%2Fndarray-conv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TYPEmber","download_url":"https://codeload.github.com/TYPEmber/ndarray-conv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253837452,"owners_count":21971984,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["convolution","fft","rust"],"created_at":"2025-01-25T15:13:48.779Z","updated_at":"2025-05-12T23:10:26.238Z","avatar_url":"https://github.com/TYPEmber.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ndarray-conv\n\nndarray-conv is a crate that provides a N-Dimension convolutions (with FFT acceleration) library in pure Rust.\n\nInspired by\n\nndarray-vision (https://github.com/rust-cv/ndarray-vision)\n\nconvolutions-rs (https://github.com/Conzel/convolutions-rs#readme)\n\npocketfft (https://github.com/mreineck/pocketfft)\n\n## Roadmap\n\n- [x] basic conv for N dimension `Array`/`ArrayView`\n- [x] conv with FFT acceleration for N dimension `Array`/`ArrayView`\n- [x] impl `ConvMode` and `PaddingMode`\n  - [x] `ConvMode`: Full Same Valid Custom Explicit\n  - [x] `PaddingMode`: Zeros Const Reflect Replicate Circular Custom Explicit\n- [x] conv with strides\n- [x] kernel with dilation\n- [x] handle input size error\n- [ ] explict error type\n- [ ] bench with similar libs\n\n## Examples\n\n```rust\nuse ndarray_conv::*;\n\nx_nd.conv(\n    \u0026k_n,\n    ConvMode::Full,\n    PaddingMode::Circular,\n);\n\nx_1d.view().conv_fft(\n    \u0026k_1d,\n    ConvMode::Same,\n    PaddingMode::Explicit([[BorderType::Replicate, BorderType::Reflect]]),\n);\n\nx_2d.conv_fft(\n    k_2d.with_dilation(2),\n    ConvMode::Same,\n    PaddingMode::Custom([BorderType::Reflect, BorderType::Circular]),\n);\n\n// avoid loss of accuracy for fft ver\n// convert Integer to Float before caculate.\nx_3d.map(|\u0026x| x as f32)\n    .conv_fft(\n        \u0026kernel.map(|\u0026x| x as f32),\n        ConvMode::Same,\n        PaddingMode::Zeros,\n    )\n    .unwrap()\n    .map(|x| x.round() as i32);\n```\n\n```rust\n// Example for thin wrapper\nuse ndarray::{\n    array, Array, ArrayView, Dim, IntoDimension, Ix, RemoveAxis, SliceArg, SliceInfo, SliceInfoElem,\n};\nuse ndarray_conv::*;\n\npub fn fftconvolve\u003c'a, T, const N: usize\u003e(\n    in1: impl Into\u003cArrayView\u003c'a, T, Dim\u003c[Ix; N]\u003e\u003e\u003e,\n    in2: impl Into\u003cArrayView\u003c'a, T, Dim\u003c[Ix; N]\u003e\u003e\u003e,\n) -\u003e Array\u003cT, Dim\u003c[Ix; N]\u003e\u003e\nwhere\n    T: num::traits::NumAssign + rustfft::FftNum,\n    Dim\u003c[Ix; N]\u003e: RemoveAxis,\n    [Ix; N]: IntoDimension\u003cDim = Dim\u003c[Ix; N]\u003e\u003e,\n    SliceInfo\u003c[SliceInfoElem; N], Dim\u003c[Ix; N]\u003e, Dim\u003c[Ix; N]\u003e\u003e:\n        SliceArg\u003cDim\u003c[Ix; N]\u003e, OutDim = Dim\u003c[Ix; N]\u003e\u003e,\n{\n    in1.into()\n        .conv_fft(\u0026in2.into(), ConvMode::Full, PaddingMode::Zeros)\n        .unwrap()\n}\n\nfn test() {\n    let o0 = fftconvolve(\u0026[1., 2.], \u0026array![1., 3., 7.]);\n    let o1 = fftconvolve(\u0026vec![1., 2.], \u0026[1., 3., 7.]);\n}\n```\n\n## Benchmark\n\n```rust\nlet x = Array::random(5000, Uniform::new(0f32, 1.));\nlet k = Array::random(31, Uniform::new(0f32, 1.));\n\nfft_1d                  time:   [76.621 µs 76.649 µs 76.681 µs]\nfft_with_processor_1d   time:   [34.563 µs 34.790 µs 35.125 µs]\ntorch_1d                time:   [45.542 µs 45.658 µs 45.775 µs]\nfftconvolve_1d          time:   [161.52 µs 162.28 µs 163.05 µs]\n\n---------------------------------------------------------------\n\nlet x = Array::random((200, 5000), Uniform::new(0f32, 1.));\nlet k = Array::random((11, 31), Uniform::new(0f32, 1.));\n\nfft_2d                  time:   [16.022 ms 16.046 ms 16.071 ms]\nfft_with_processor_2d   time:   [15.949 ms 15.977 ms 16.010 ms]\ntorch_2d                time:   [109.76 ms 111.62 ms 113.79 ms]\nndarray_vision_2d       time:   [429.47 ms 429.64 ms 429.82 ms]\nfftconvolve_2d          time:   [56.273 ms 56.342 ms 56.420 ms]\n\n---------------------------------------------------------------\n\nlet x = Array::random((10, 100, 200), Uniform::new(0f32, 1.));\nlet k = Array::random((5, 11, 31), Uniform::new(0f32, 1.));\n\nfft_3d                  time:   [5.3049 ms 5.3498 ms 5.3957 ms]\nfft_with_processor_3d   time:   [5.2981 ms 5.3345 ms 5.3696 ms]\ntorch_3d                time:   [147.20 ms 151.97 ms 158.54 ms]\nfftconvolve_3d          time:   [11.991 ms 12.009 ms 12.031 ms]\n```\n\n## Versions\n- 0.4.2 - Remove `Debug` trait on `T`.\n- 0.4.1 - Doc update.\n- 0.4.0 - Dependency update: update ndarray from 0.15 to 0.16.\n- 0.3.4 - Bug fix: fix unsafe type cast in circular padding.\n- 0.3.3 - Bug fix: correct conv_fft's output shape.\n- 0.3.2 - Improve performance, by modifying `good_fft_size` and `transpose`.\n- 0.3.1 - Impl basic error type. Fix some bugs.\n- 0.3.0 - update to N-Dimension convolution.\n- 0.2.0 - finished `conv_2d` \u0026 `conv_2d_fft`.\n\n## Frequently Asked Questions (FAQ)\n\nThis FAQ addresses common questions about the `ndarray-conv` crate, a Rust library for N-dimensional convolutions using the `ndarray` ecosystem.\n\n### 1. What is `ndarray-conv`?\n\n`ndarray-conv` is a Rust crate that provides N-dimensional convolution operations for the `ndarray` crate. It offers both standard and FFT-accelerated convolutions, giving you efficient tools for image processing, signal processing, and other applications that rely on convolutions.\n\n### 2. What are the main features of `ndarray-conv`?\n\n*   **N-Dimensional Convolutions:** Supports convolutions on arrays with any number of dimensions.\n*   **Standard and FFT-Accelerated:** Offers both `conv` (standard) and `conv_fft` (FFT-based) methods.\n*   **Flexible Convolution Modes:** `ConvMode` (Full, Same, Valid, Custom, Explicit) to control output size.\n*   **Various Padding Modes:** `PaddingMode` (Zeros, Const, Reflect, Replicate, Circular, Custom, Explicit) to handle boundary conditions.\n*   **Strides and Dilation:** Supports strided convolutions and dilated kernels using the `with_dilation()` method.\n*   **Performance Optimization:** Uses FFTs for larger kernels and optimized low-level operations for efficiency. The `conv_fft_with_processor` allows to reuse an `FftProcessor` for improved performance on repeated calls.\n*   **Integration with `ndarray`:** Seamlessly works with `ndarray` `Array` and `ArrayView` types.\n\n### 3. When should I use `conv_fft` vs. `conv`?\n\n*   **`conv_fft` (FFT-accelerated):** Generally faster for larger kernels (e.g., larger than 11x11) because the computational complexity of FFTs grows more slowly than direct convolution as the kernel size increases.\n*   **`conv` (Standard):** Might be faster for very small kernels (e.g., 3x3, 5x5) due to the overhead associated with FFT calculations.\n\nIt's a good idea to benchmark both methods with your specific kernel sizes and data dimensions to determine the best choice.\n\n### 4. How do I choose the right `ConvMode`?\n\n*   **`Full`:** The output contains all positions where the kernel and input overlap at least partially. This results in the largest output size.\n*   **`Same`:** The output has the same size as the input. This is achieved by padding the input appropriately.\n*   **`Valid`:** The output contains only positions where the kernel and input fully overlap. This results in the smallest output size.\n*   **`Custom`:** You specify the padding for all the dimensions and strides.\n*   **`Explicit`:** You specify the explicit padding for each side of each dimension, and the strides.\n\nThe best choice depends on the desired output size and how you want to handle boundary conditions.\n\n### 5. How do I handle border effects with `PaddingMode`?\n\n`PaddingMode` determines how the input is padded before the convolution.\n\n*   **`Zeros`:** Pads with zeros.\n*   **`Const(value)`:** Pads with a constant value.\n*   **`Reflect`:** Reflects the input at the borders.\n*   **`Replicate`:** Replicates the edge values.\n*   **`Circular`:** Treats the input as a circular buffer, wrapping around at the borders.\n*   **`Custom`:** You provide an array of `BorderType` enums, one for each dimension, to specify different padding behavior for each dimension.\n*   **`Explicit`:** You provide an array with arrays of `BorderType` enums, one for each side of each dimension, to specify different padding behavior for each dimension.\n\nChoose the `PaddingMode` that best suits your application's requirements for handling edges.\n\n### 6. What is dilation, and how do I use it?\n\nDilation expands the *receptive field* of a kernel without increasing the number of its parameters. It does this by inserting spaces (usually zeros) between the original kernel elements. A dilation factor of `d` means that `d-1` zeros are inserted between each kernel element.\n\n*   Use the `with_dilation()` method on an `ndarray` `Array` or `ArrayView` representing your kernel to create a dilated kernel.\n*   Pass the dilated kernel to the `conv` or `conv_fft` methods.\n\n**Example:**\n\n```rust\nlet kernel = ndarray::array![[1, 2, 3], [4, 5, 6]];\nlet dilated_kernel = kernel.with_dilation(2); // Dilate by a factor of 2 in both dimensions\n// dilated_kernel will effectively be: [[1, 0, 2, 0, 3], [4, 0, 5, 0, 6]]\n```\n\n**Why Use Dilation?**\n\n*   **Increased Receptive Field:** Captures information from a wider area of the input without increasing the parameter count.\n*   **Computational Efficiency:** More efficient than using very large standard kernels to achieve the same receptive field.\n*   **Multi-Scale Feature Extraction:** Enables extracting features at different scales by using varying dilation rates.\n\n**Applications:**\n\n*   Semantic segmentation\n*   Object detection\n*   Image generation\n*   Audio processing\n*   Time-series analysis\n\n### 7. How can I improve the performance of repeated convolutions?\n\n*   **Use `conv_fft_with_processor`:** If you're performing multiple FFT-based convolutions, create an `FftProcessor` and reuse it with the `conv_fft_with_processor` method. This avoids recomputing FFT plans and reallocating scratch buffers.\n*   **Convert to `f32` or `f64`:** For FFT convolutions, ensure your input and kernel data are `f32` (for `Rfft32`) or `f64` (for `Rfft64`). This avoids unnecessary type conversions.\n\n### 8. How do I install `ndarray-conv`?\n\nAdd the following to your `Cargo.toml` file:\n\n```toml\nndarray-conv = \"0.3.3\"  # Use the latest version\n```\n\n### 9. Are there any limitations to be aware of?\n\n*   **FFT Overhead:** For very small kernels, FFT-based convolutions might be slower than standard convolutions due to the overhead of FFT calculations.\n*   **Memory Usage:** FFT operations might require additional memory for intermediate buffers.\n*   **`conv_fft` requires floating point:** The input and kernel must be floating point types (`f32` or `f64`) for FFT-based convolutions.\n\n### 10. How do I convert integer arrays to floating-point for use with `conv_fft`?\n\nUse the `.map(|\u0026x| x as f32)` or `.map(|\u0026x| x as f64)` methods to convert an integer `ndarray` to `f32` or `f64`, respectively.\n\n**Example:**\n\n```rust\nlet int_array = ndarray::Array::from_shape_vec((2, 3), vec![1, 2, 3, 4, 5, 6]).unwrap();\nlet float_array = int_array.map(|\u0026x| x as f32);\n```\n\n### 11. Where can I find examples and documentation?\n\n*   **README:** The project's README file on GitHub contains basic examples and usage instructions.\n*   **Rust Docs:** Once published to crates.io, you can find detailed API documentation on docs.rs.\n*   **Test Cases:** The `tests` modules within the source code provide further examples of how to use the library.\n\n### 12. How does `ndarray-conv` compare to other convolution libraries?\n\nThe `ndarray-conv` project includes benchmarks comparing its performance to libraries like `tch` (LibTorch/PyTorch), `ndarray-vision`, and `fftconvolve`. `ndarray-conv` is generally competitive and often outperforms these other libraries, especially when using `conv_fft_with_processor` for repeated convolutions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypember%2Fndarray-conv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypember%2Fndarray-conv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypember%2Fndarray-conv/lists"}