From 1d35153993b23ffeb89fd8113242d583f803b573 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Sat, 19 Nov 2022 22:02:14 +0100 Subject: [PATCH 01/15] wrote the 1d convolutions algorithm in rust --- .../1d/code/rust/1d_convolution.rs | 102 ++++++++++++++++++ contents/convolutions/1d/code/rust/Cargo.toml | 12 +++ 2 files changed, 114 insertions(+) create mode 100644 contents/convolutions/1d/code/rust/1d_convolution.rs create mode 100644 contents/convolutions/1d/code/rust/Cargo.toml diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs new file mode 100644 index 000000000..d645e139d --- /dev/null +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -0,0 +1,102 @@ +use std::fs::File; +use std::io::Write; +use std::cmp::max; + +fn main() { + let x = normalize(create_sawtooth(200)); + let y = normalize(create_sawtooth(200)); + + let len_x = x.len(); + let len_y = y.len(); + + let full_linear_output = convolve_linear(&x, &y, len_x + len_y - 1); + let simple_linear_output = convolve_linear(&x, &y, len_x); + let cyclic_output = convolve_cyclic(&x, &y); + + // Save the convolutions to plot them. + // The way I do it is a little weird but it is to store the data the same way as the other programs + let mut full_file = File::create("full_linear.dat").unwrap(); + for i in full_linear_output { + write!(full_file, "{}\n", i).unwrap(); + } + full_file.sync_all().unwrap(); + + let mut simple_file = File::create("simple_linear.dat").unwrap(); + for i in simple_linear_output { + write!(simple_file, "{}\n", i).unwrap(); + } + simple_file.sync_all().unwrap(); + + let mut cyclic_file = File::create("cyclic.dat").unwrap(); + for i in cyclic_output { + write!(cyclic_file, "{}\n", i).unwrap(); + } + cyclic_file.sync_all().unwrap(); +} + +// Generates a sawtooth function with a given length. +fn create_sawtooth(length: usize) -> Vec { + let mut array: Vec = Vec::with_capacity(length); + for i in 0..length { + array.push((i+1) as f64 / 200.); + } + array +} + +// Normalizes the given array. +fn normalize(array: Vec) -> Vec { + let norm = norm(&array); + let mut output: Vec = Vec::with_capacity(array.len()); + + for i in 0..array.len() { + output.push(array[i] / norm); + } + + output +} + +// Calculates the norm of an array. +fn norm(array: &Vec) -> f64 { + let mut sum = 0.; + for i in array.iter() { + sum += i*i; + } + sum.sqrt() +} + + +// Modulus function that handles negative values correctly. +// Assumes that y >= 0. +fn modulus(x: isize, y: isize) -> isize {((x%y) + y) % y} + +fn convolve_linear(signal: &Vec, filter: &Vec, output_size: usize) -> Vec { + let mut output = Vec::with_capacity(output_size); + + for i in 0..(output_size as isize) { + let mut sum: f64 = 0.; + for j in max(0, i as isize - filter.len() as isize)..=i as isize { + if j < signal.len() as isize && (i - j) < filter.len() as isize { + sum += signal[j as usize] * filter[(i-j) as usize] + } + } + output.push(sum); + } + + output +} + +fn convolve_cyclic(signal: &Vec, filter: &Vec) -> Vec { + let output_size = max(signal.len(), filter.len()) as isize; + + let mut output: Vec = Vec::with_capacity(output_size as usize); + for i in 0..output_size { + let mut sum: f64 = 0.; + for j in 0..output_size { + if modulus(i - j, output_size) < filter.len() as isize { + sum += signal[modulus(j - 1, output_size) as usize] * filter[modulus(i - j, output_size) as usize]; + } + } + output.push(sum); + } + output +} diff --git a/contents/convolutions/1d/code/rust/Cargo.toml b/contents/convolutions/1d/code/rust/Cargo.toml new file mode 100644 index 000000000..80352724f --- /dev/null +++ b/contents/convolutions/1d/code/rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[[bin]] +path = "./1d_convolution.rs" +name = "main" From fb21997d222f0f8bc2f29252a30a3265457b4b70 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Sat, 19 Nov 2022 22:13:01 +0100 Subject: [PATCH 02/15] modified 1d convolutions page to use the rust code --- contents/convolutions/1d/1d.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contents/convolutions/1d/1d.md b/contents/convolutions/1d/1d.md index ecf56a1df..2da836650 100644 --- a/contents/convolutions/1d/1d.md +++ b/contents/convolutions/1d/1d.md @@ -58,6 +58,8 @@ With this in mind, we can almost directly transcribe the discrete equation into [import:63-84, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:20-31, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:72-86, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} The easiest way to reason about this code is to read it as you might read a textbook. @@ -193,6 +195,8 @@ Here it is again for clarity: [import:63-84, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:20-31, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:72-86, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} Here, the main difference between the bounded and unbounded versions is that the output array size is smaller in the bounded case. @@ -205,6 +209,8 @@ For an unbounded convolution, the function would be called with a the output arr [import:96-97, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:41-42, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:12-12, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} On the other hand, the bounded call would set the output array size to simply be the length of the signal @@ -216,6 +222,8 @@ On the other hand, the bounded call would set the output array size to simply be [import:98-99, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:44-45, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:13-13, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} Finally, as we mentioned before, it is possible to center bounded convolutions by changing the location where we calculate the each point along the filter. @@ -228,6 +236,8 @@ This can be done by modifying the following line: [import:71-71, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:25-25, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:77-77, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} Here, `j` counts from `i-length(filter)` to `i`. @@ -264,6 +274,8 @@ In code, this typically amounts to using some form of modulus operation, as show [import:38-61, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import:5-17, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import:88-102, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} This is essentially the same as before, except for the modulus operations, which allow us to work on a periodic domain. @@ -283,6 +295,8 @@ For the code associated with this chapter, we have used the convolution to gener [import, lang:"csharp"](code/csharp/1DConvolution.cs) {% sample lang="py" %} [import, lang:"python"](code/python/1d_convolution.py) +{% sample lang="rs" %} +[import, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} At a test case, we have chosen to use two sawtooth functions, which should produce the following images: From e8573e2daf096aecdeba179ce19556420b8d1a13 Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:16:11 +0100 Subject: [PATCH 03/15] replace for-loop with iterator Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index d645e139d..471dd1fcf 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -57,10 +57,7 @@ fn normalize(array: Vec) -> Vec { // Calculates the norm of an array. fn norm(array: &Vec) -> f64 { - let mut sum = 0.; - for i in array.iter() { - sum += i*i; - } + let sum = array.iter().map(|i| i * i).sum::() sum.sqrt() } From 067c92921ec9c0dde8430dd67a8e1910d529e7bb Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:16:30 +0100 Subject: [PATCH 04/15] replaced reference to vec with a slice Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 471dd1fcf..02881e864 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -56,7 +56,7 @@ fn normalize(array: Vec) -> Vec { } // Calculates the norm of an array. -fn norm(array: &Vec) -> f64 { +fn norm(array: &[f64]) -> f64 { let sum = array.iter().map(|i| i * i).sum::() sum.sqrt() } From fc70dc0a62cae2cf764988f82bfec2cd19ca242a Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:17:12 +0100 Subject: [PATCH 05/15] replace write! with writeln! Not sure why I didn't do it in the first place. Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 02881e864..31e8303a9 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -17,7 +17,7 @@ fn main() { // The way I do it is a little weird but it is to store the data the same way as the other programs let mut full_file = File::create("full_linear.dat").unwrap(); for i in full_linear_output { - write!(full_file, "{}\n", i).unwrap(); + writeln!(full_file, "{}", i).unwrap(); } full_file.sync_all().unwrap(); From 9316119bf22ad59cff43579380a9c38600389fce Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:17:23 +0100 Subject: [PATCH 06/15] replace write! with writeln! Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 31e8303a9..647fef6ab 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -23,7 +23,7 @@ fn main() { let mut simple_file = File::create("simple_linear.dat").unwrap(); for i in simple_linear_output { - write!(simple_file, "{}\n", i).unwrap(); + writeln!(simple_file, "{}", i).unwrap(); } simple_file.sync_all().unwrap(); From 9054525058d2ab4e9d4aadda27791a7ea5380ed2 Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:17:40 +0100 Subject: [PATCH 07/15] replace write! with writeln! Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 647fef6ab..9df8ccd03 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -29,7 +29,7 @@ fn main() { let mut cyclic_file = File::create("cyclic.dat").unwrap(); for i in cyclic_output { - write!(cyclic_file, "{}\n", i).unwrap(); + writeln!(cyclic_file, "{}", i).unwrap(); } cyclic_file.sync_all().unwrap(); } From 7fb386fa1b29aa41a16cc0704452b6c54589c563 Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:18:09 +0100 Subject: [PATCH 08/15] use iterator instead of indexing Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 9df8ccd03..850644231 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -48,8 +48,8 @@ fn normalize(array: Vec) -> Vec { let norm = norm(&array); let mut output: Vec = Vec::with_capacity(array.len()); - for i in 0..array.len() { - output.push(array[i] / norm); + for value in array { + output.push(value / norm); } output From 6c52d0a12a70f1c291625f6ccb699b00f3f3ce46 Mon Sep 17 00:00:00 2001 From: eengamer2007 <61841788+eengamer2007@users.noreply.github.com> Date: Mon, 21 Nov 2022 19:18:50 +0100 Subject: [PATCH 09/15] add forgotten ; Co-authored-by: Sammy Plat --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 850644231..3bcd9e86e 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -73,7 +73,7 @@ fn convolve_linear(signal: &Vec, filter: &Vec, output_size: usize) -> let mut sum: f64 = 0.; for j in max(0, i as isize - filter.len() as isize)..=i as isize { if j < signal.len() as isize && (i - j) < filter.len() as isize { - sum += signal[j as usize] * filter[(i-j) as usize] + sum += signal[j as usize] * filter[(i-j) as usize]; } } output.push(sum); From 9151463a9d2dac02c474d593d2eeb7d3225bd9c9 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Mon, 21 Nov 2022 21:00:27 +0100 Subject: [PATCH 10/15] add missing ; --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 3bcd9e86e..9ed9649c7 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -57,7 +57,7 @@ fn normalize(array: Vec) -> Vec { // Calculates the norm of an array. fn norm(array: &[f64]) -> f64 { - let sum = array.iter().map(|i| i * i).sum::() + let sum = array.iter().map(|i| i * i).sum::(); sum.sqrt() } From ad0bd320b6ff261753bb1180d6b8c16fd2d09782 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Mon, 21 Nov 2022 21:01:32 +0100 Subject: [PATCH 11/15] remove a magic number --- contents/convolutions/1d/code/rust/1d_convolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 9ed9649c7..44964648c 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -38,7 +38,7 @@ fn main() { fn create_sawtooth(length: usize) -> Vec { let mut array: Vec = Vec::with_capacity(length); for i in 0..length { - array.push((i+1) as f64 / 200.); + array.push((i+1) as f64 / length as f64); // divide by length for normalization } array } From d1c591fb9d4f5d6520c5cab0f4a7e097ca67387e Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Tue, 22 Nov 2022 20:24:16 +0100 Subject: [PATCH 12/15] add name to contributors list --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 8bf39132c..b9bb8a477 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -64,3 +64,4 @@ This file lists everyone, who contributed to this repo and wanted to show up her - K. Shudipto Amin - Peanutbutter_Warrior - Thijs Raymakers +- eengamer2007 From fb90b49c1b7c85933a1e06b606b078fabe8b4388 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Thu, 22 Dec 2022 15:29:15 +0100 Subject: [PATCH 13/15] reduce amount of type casts by turning modulus from Fn(isize, isize) -> isize to Fn(isize, usize) -> usize --- contents/convolutions/1d/code/rust/1d_convolution.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 44964648c..9760bbfa9 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -64,14 +64,14 @@ fn norm(array: &[f64]) -> f64 { // Modulus function that handles negative values correctly. // Assumes that y >= 0. -fn modulus(x: isize, y: isize) -> isize {((x%y) + y) % y} +fn modulus(x: isize, y: usize) -> usize {((x%y as isize) as usize + y) % y} fn convolve_linear(signal: &Vec, filter: &Vec, output_size: usize) -> Vec { let mut output = Vec::with_capacity(output_size); for i in 0..(output_size as isize) { let mut sum: f64 = 0.; - for j in max(0, i as isize - filter.len() as isize)..=i as isize { + for j in max(0, i - filter.len() as isize)..=i { if j < signal.len() as isize && (i - j) < filter.len() as isize { sum += signal[j as usize] * filter[(i-j) as usize]; } @@ -83,14 +83,14 @@ fn convolve_linear(signal: &Vec, filter: &Vec, output_size: usize) -> } fn convolve_cyclic(signal: &Vec, filter: &Vec) -> Vec { - let output_size = max(signal.len(), filter.len()) as isize; + let output_size = max(signal.len(), filter.len()); - let mut output: Vec = Vec::with_capacity(output_size as usize); + let mut output: Vec = Vec::with_capacity(output_size); for i in 0..output_size { let mut sum: f64 = 0.; for j in 0..output_size { - if modulus(i - j, output_size) < filter.len() as isize { - sum += signal[modulus(j - 1, output_size) as usize] * filter[modulus(i - j, output_size) as usize]; + if modulus((i - j) as isize, output_size) < filter.len() { + sum += signal[modulus((j - 1) as isize, output_size)] * filter[modulus((i - j) as isize, output_size)]; } } output.push(sum); From 1e761b3923e8b034b65d2349adf34a0023714744 Mon Sep 17 00:00:00 2001 From: eengamer2007 Date: Thu, 22 Dec 2022 15:32:10 +0100 Subject: [PATCH 14/15] inline arguments at the writeln because clippy says so --- contents/convolutions/1d/code/rust/1d_convolution.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contents/convolutions/1d/code/rust/1d_convolution.rs b/contents/convolutions/1d/code/rust/1d_convolution.rs index 9760bbfa9..8472b3033 100644 --- a/contents/convolutions/1d/code/rust/1d_convolution.rs +++ b/contents/convolutions/1d/code/rust/1d_convolution.rs @@ -17,19 +17,19 @@ fn main() { // The way I do it is a little weird but it is to store the data the same way as the other programs let mut full_file = File::create("full_linear.dat").unwrap(); for i in full_linear_output { - writeln!(full_file, "{}", i).unwrap(); + writeln!(full_file, "{i}").unwrap(); } full_file.sync_all().unwrap(); let mut simple_file = File::create("simple_linear.dat").unwrap(); for i in simple_linear_output { - writeln!(simple_file, "{}", i).unwrap(); + writeln!(simple_file, "{i}").unwrap(); } simple_file.sync_all().unwrap(); let mut cyclic_file = File::create("cyclic.dat").unwrap(); for i in cyclic_output { - writeln!(cyclic_file, "{}", i).unwrap(); + writeln!(cyclic_file, "{i}").unwrap(); } cyclic_file.sync_all().unwrap(); } From eb76ce54e9e9f4ab4eafd41fa3786792336fc25d Mon Sep 17 00:00:00 2001 From: eengamer Date: Mon, 6 Feb 2023 12:37:29 +0100 Subject: [PATCH 15/15] fix line numbers --- contents/convolutions/1d/1d.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contents/convolutions/1d/1d.md b/contents/convolutions/1d/1d.md index 2da836650..5ee20750f 100644 --- a/contents/convolutions/1d/1d.md +++ b/contents/convolutions/1d/1d.md @@ -59,7 +59,7 @@ With this in mind, we can almost directly transcribe the discrete equation into {% sample lang="py" %} [import:20-31, lang:"python"](code/python/1d_convolution.py) {% sample lang="rs" %} -[import:72-86, lang:"rust"](code/rust/1d_convolution.rs) +[import:69-83, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} The easiest way to reason about this code is to read it as you might read a textbook. @@ -196,7 +196,7 @@ Here it is again for clarity: {% sample lang="py" %} [import:20-31, lang:"python"](code/python/1d_convolution.py) {% sample lang="rs" %} -[import:72-86, lang:"rust"](code/rust/1d_convolution.rs) +[import:69-83, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} Here, the main difference between the bounded and unbounded versions is that the output array size is smaller in the bounded case. @@ -237,7 +237,7 @@ This can be done by modifying the following line: {% sample lang="py" %} [import:25-25, lang:"python"](code/python/1d_convolution.py) {% sample lang="rs" %} -[import:77-77, lang:"rust"](code/rust/1d_convolution.rs) +[import:74-74, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} Here, `j` counts from `i-length(filter)` to `i`. @@ -275,7 +275,7 @@ In code, this typically amounts to using some form of modulus operation, as show {% sample lang="py" %} [import:5-17, lang:"python"](code/python/1d_convolution.py) {% sample lang="rs" %} -[import:88-102, lang:"rust"](code/rust/1d_convolution.rs) +[import:85-99, lang:"rust"](code/rust/1d_convolution.rs) {% endmethod %} This is essentially the same as before, except for the modulus operations, which allow us to work on a periodic domain.