Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5) rust: use AsRef/AsMut in compute interface #1087

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 12 additions & 32 deletions compiler/generator/rust/rust_code_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,6 @@ void RustCodeContainer::produceClass()
tab(n, *fOut);
*fOut << "pub type FaustFloat = " << ifloat() << ";";

tab(n, *fOut);
*fOut << "use std::convert::TryInto;";

// Generate gub containers
generateSubContainers();
Expand Down Expand Up @@ -527,7 +525,6 @@ void RustCodeContainer::produceClass()
generateComputeFrame(n + 1);
} else {
generateCompute(n + 1);
generateComputeInterface(n + 1);
}

tab(n, *fOut);
Expand Down Expand Up @@ -627,18 +624,18 @@ void RustCodeContainer::generateComputeHeader(int n, std::ostream* fOut, int fNu
{
// Compute "compute" declaration
tab(n, *fOut);
*fOut << "pub fn compute_arrays("
<< "&mut self, " << fFullCount << ": usize, inputs: &[&[FaustFloat] ; " << fNumInputs
<< "]"
<< ", outputs: &mut [&mut [FaustFloat] ; " << fNumOutputs << "]) {";
}

void RustCodeContainer::generateComputeInterfaceHeader(int n, std::ostream* fOut, int fNumInputs,
int fNumOutputs)
{
*fOut << "pub fn compute("
<< "&mut self, " << fFullCount << ": usize, inputs: & [& [FaustFloat] ]"
<< ", outputs: & mut[& mut[FaustFloat] ]) {";
tab(n, *fOut);
*fOut << "pub fn compute(";
tab(n + 1, *fOut);
*fOut << "&mut self,";
tab(n + 1, *fOut);
*fOut << "count: usize,";
tab(n + 1, *fOut);
*fOut << "inputs: &[impl AsRef<[FaustFloat]>],";
tab(n + 1, *fOut);
*fOut << "outputs: &mut[impl AsMut<[FaustFloat]>],";
tab(n, *fOut);
*fOut << ") {";
tab(n + 1, *fOut);
}

Expand Down Expand Up @@ -685,23 +682,6 @@ void RustCodeContainer::generateComputeFrame(int n)
tab(n, *fOut);
}

void RustCodeContainer::generateComputeInterface(int n)
{
// Generates declaration
tab(n, *fOut);
generateComputeInterfaceHeader(n, fOut, fNumInputs, fNumOutputs);

*fOut << "let input_array = inputs.split_at(" << fNumInputs
<< ").0.try_into().expect(\"too few input buffers\");";
tab(n + 1, *fOut);
*fOut << "let output_array = outputs.split_at_mut(" << fNumOutputs
<< ").0.try_into().expect(\"too few output buffers\");";
tab(n + 1, *fOut);
*fOut << "self.compute_arrays(count, input_array, output_array);";
tab(n, *fOut);
*fOut << "}" << endl;
}

// Scalar
RustScalarCodeContainer::RustScalarCodeContainer(const string& name, int numInputs, int numOutputs,
std::ostream* out, int sub_container_type)
Expand Down
2 changes: 0 additions & 2 deletions compiler/generator/rust/rust_code_container.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ class RustCodeContainer : public virtual CodeContainer {

virtual void produceClass();
void generateComputeHeader(int n, std::ostream* fOut, int fNumInputs, int fNumOutputs);
void generateComputeInterfaceHeader(int n, std::ostream* fOut, int fNumInputs, int fNumOutputs);
void generateComputeInterface(int tab);
void generateComputeFrame(int tab);
virtual void generateCompute(int tab) = 0;
void produceInternal();
Expand Down
24 changes: 15 additions & 9 deletions compiler/generator/rust/rust_instructions.hh
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ class RustInstVisitor : public TextInstVisitor {
virtual void visit(DeclareBufferIterators* inst)
{
/* Generates an expression like:
let [outputs0, outputs1, ..] = outputs;
let outputs0 = outputs0[..count].iter_mut();
let outputs1 = outputs1[..count].iter_mut();
let [outputs0, outputs1, ..] = outputs.as_mut() else { panic!(\"wrong number of outputs\"); };";
let outputs0 = outputs0.as_mut[..count].iter_mut();
let outputs1 = outputs1.as_mut[..count].iter_mut();
*/

// Don't generate if no channels or onesample mode
Expand All @@ -241,23 +241,29 @@ class RustInstVisitor : public TextInstVisitor {
for (int i = 0; i < inst->fChannels; ++i) {
*fOut << name << i << ", ";
}
*fOut << "] = " << name << ";";
*fOut << ".. ] = " << name;
if (inst->fMutable) {
*fOut << ".as_mut() else { panic!(\"wrong number of outputs\"); };";
} else {
*fOut << ".as_ref() else { panic!(\"wrong number of inputs\"); };";
}

// Build fixed size iterator variables
for (int i = 0; i < inst->fChannels; ++i) {
tab(fTab, *fOut);
*fOut << "let " << name << i << " = " << name << i << "[..count]";
*fOut << "let " << name << i << " = " << name << i;
;
if (inst->fMutable) {
if (inst->fChunk) {
*fOut << ".chunks_mut(vsize as usize);";
*fOut << ".as_mut()[..count].chunks_mut(vsize as usize);";
} else {
*fOut << ".iter_mut();";
*fOut << ".as_mut()[..count].iter_mut();";
}
} else {
if (inst->fChunk) {
*fOut << ".chunks(vsize as usize);";
*fOut << ".as_ref()[..count].chunks(vsize as usize);";
} else {
*fOut << ".iter();";
*fOut << ".as_ref()[..count].iter();";
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions tests/impulse-tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,9 @@ travis:
#########################################################################
# automatic github action test
github_action:
$(MAKE) -f Make.rust outdir=rust/osec CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -os -ec -rnt -a archs/rust/architecture_osecrnt.rs"
Copy link
Member

@sletz sletz Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you remove the tests here ? (I think it makes sense to keep all of them)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rational was to only keep tests that relate to a change in ci. I don't have a strong opinion on this.

$(MAKE) -f Make.rust outdir=rust/os CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -os -rnt -a archs/rust/architecture_osrnt.rs"
$(MAKE) -f Make.rust outdir=rust/no CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -a archs/rust/architecture_trait.rs"
$(MAKE) -f Make.gcc outdir=cpp/double/os lang=cpp arch=impulsearch7ter.cpp FAUSTOPTIONS="-I dsp -double -os"
$(MAKE) -f Make.rust outdir=rust/cm CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -cm -a archs/rust/architecture_cm.rs"
$(MAKE) -f Make.rust outdir=rust/ecrnt CARGOOPTIONS="" FAUSTOPTIONS="-I ../../libraries/ -double -ec -rnt -a archs/rust/architecture_ecrnt.rs"
$(MAKE) -f Make.gcc outdir=cpp/double lang=cpp arch=impulsearch.cpp FAUSTOPTIONS="-I ../../libraries/ -I dsp -double"

#########################################################################
Expand Down
96 changes: 33 additions & 63 deletions tests/impulse-tests/archs/rust/architecture_cm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
************************************************************************
************************************************************************/

// this architecture file uses arrays of arrays to test the interface of the compute functions

#![allow(unused_parens)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
Expand Down Expand Up @@ -185,37 +187,33 @@ impl<T: Float + FromPrimitive> UI<T> for ButtonUI {
// // Generated class:
// <<includeclass>>

const SAMPLE_RATE: i32 = 44100;

type Dsp64 = dyn FaustDsp<T = f64>;

fn print_header(mut dsp: Box<Dsp64>, num_total_samples: usize, output_file: &mut File) {
dsp.init(SAMPLE_RATE);
fn print_header(dsp: &impl FaustDsp<T = FaustFloat>, output_file: &mut File) {
writeln!(output_file, "number_of_inputs : {}", dsp.get_num_inputs()).unwrap();
writeln!(output_file, "number_of_outputs : {}", dsp.get_num_outputs()).unwrap();
writeln!(output_file, "number_of_frames : {}", num_total_samples).unwrap();
writeln!(output_file, "number_of_frames : {}", NUM_TOTAL_SAMPLES).unwrap();
}

fn run_dsp(
mut dsp: Box<Dsp64>,
num_samples: usize,
line_num_offset: usize,
output_file: &mut File,
) {
type T = <Dsp64 as FaustDsp>::T;
const SAMPLE_RATE: i32 = 44100;
const NUM_TOTAL_SAMPLES: usize = 60000;
const BLOCK_SIZE: usize = NUM_TOTAL_SAMPLES / 4;
const BUFFER_SIZE: usize = 64usize;

// Generation constants
let buffer_size = 64usize;
fn main() {
// Open output file
let output_file_name = env::args()
.nth(1)
.expect("ERROR: Output file name expected.");
let mut output_file = File::create(output_file_name).expect("Cannot create output file");

let mut dsp = mydsp::default_boxed();
// Init dsp
dsp.init(SAMPLE_RATE);

let num_inputs = dsp.get_num_inputs() as usize;
let num_outputs = dsp.get_num_outputs() as usize;
print_header(&*dsp, &mut output_file);

// Prepare buffers
let mut in_buffer = vec![vec![0 as T; buffer_size]; num_inputs];
let mut out_buffer = vec![vec![0 as T; buffer_size]; num_outputs];
let mut in_buffer = [[0.0 as FaustFloat; BUFFER_SIZE]; FAUST_INPUTS];
let mut out_buffer = [[0.0 as FaustFloat; BUFFER_SIZE]; FAUST_OUTPUTS];

// Prepare UI
let mut ui = ButtonUI {
Expand All @@ -226,16 +224,16 @@ fn run_dsp(
// Compute
let mut cycle = 0;
let mut num_samples_written = 0;
while num_samples_written < num_samples {
let buffer_size = buffer_size.min(num_samples - num_samples_written);
while num_samples_written < BLOCK_SIZE {
let buffer_size = BUFFER_SIZE.min(BLOCK_SIZE - num_samples_written);

// handle inputs
for c in 0..num_inputs {
for j in 0..buffer_size {
(0..FAUST_INPUTS).for_each(|c| {
(0..buffer_size).for_each(|j| {
let first_frame = num_samples_written == 0 && j == 0;
in_buffer[c][j] = if first_frame { 1.0 } else { 0.0 };
}
}
});
});

// Set button state
if cycle == 0 {
Expand All @@ -245,50 +243,22 @@ fn run_dsp(
}

// right now the cm flag is only tested for the case that is the buffer is zeroed every time
let i = in_buffer
.iter()
.map(|buffer| buffer.as_slice())
.collect::<Vec<&[T]>>();
let mut o = out_buffer
out_buffer
.iter_mut()
.map(|buffer| {
buffer.iter_mut().for_each(|i| *i = 0.0);
buffer.as_mut_slice()
})
.collect::<Vec<&mut [T]>>();
.for_each(|mut buffer| buffer.iter_mut().for_each(|mut sample| *sample = 0.0));

dsp.compute(buffer_size as i32, i.as_slice(), o.as_mut_slice());
dsp.compute(buffer_size, &in_buffer, &mut out_buffer);

// handle outputs
for j in 0..buffer_size {
write!(output_file, "{:6} :", num_samples_written + line_num_offset).unwrap();
for c in 0..num_outputs {
(0..buffer_size).for_each(|j| {
write!(output_file, "{:6} :", num_samples_written).unwrap();
(0..FAUST_OUTPUTS).for_each(|c| {
write!(output_file, " {:8.6}", out_buffer[c][j]).unwrap();
}
});
writeln!(output_file).unwrap();
num_samples_written += 1;
}
});

cycle = cycle + 1;
cycle += 1;
}
}

fn new_dsp() -> Box<Dsp64> {
mydsp::default_boxed()
}

fn main() {
let num_total_samples = 60000;

let block_size = num_total_samples / 4;

// Open output file
let output_file_name = env::args()
.nth(1)
.expect("ERROR: Output file name expected.");
let mut output_file = File::create(output_file_name).expect("Cannot create output file");

print_header(new_dsp(), num_total_samples, &mut output_file);

run_dsp(mydsp::default_boxed(), block_size, 0, &mut output_file);
}
24 changes: 7 additions & 17 deletions tests/impulse-tests/archs/rust/architecture_ecrnt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
************************************************************************
************************************************************************/

// this architecture file use vectors of vectors to test the compute interface

#![allow(unused_parens)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
Expand Down Expand Up @@ -152,11 +154,11 @@ impl<T: Float + FromPrimitive> UI<T> for ButtonUI {
fn declare(&mut self, param: Option<ParamIndex>, key: &str, value: &str) {}
}

// Generated intrinsics:
<<includeIntrinsic>>
// // Generated intrinsics:
// <<includeIntrinsic>>

// Generated class:
<<includeclass>>
// // Generated class:
// <<includeclass>>

const SAMPLE_RATE: i32 = 44100;

Expand Down Expand Up @@ -211,19 +213,7 @@ fn run_dsp(
}

dsp.control();
dsp.compute(
buffer_size,
in_buffer
.iter()
.map(|buffer| buffer.as_slice())
.collect::<Vec<&[FaustFloat]>>()
.as_slice(),
out_buffer
.iter_mut()
.map(|buffer| buffer.as_mut_slice())
.collect::<Vec<&mut [FaustFloat]>>()
.as_mut_slice(),
);
dsp.compute(buffer_size, &in_buffer, &mut out_buffer);

// handle outputs
for j in 0..buffer_size {
Expand Down
5 changes: 1 addition & 4 deletions tests/impulse-tests/archs/rust/architecture_osecrnt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,9 @@ extern crate libm;
extern crate num_traits;
/* extern crate fastfloat; */

use std::env;
use std::fs::File;
use std::io::Write;

use default_boxed::DefaultBoxed;
use num_traits::{cast::FromPrimitive, float::Float};
use std::{convert::TryInto, env, fs::File, io::Write};

type F32 = f32;
type F64 = f64;
Expand Down
5 changes: 1 addition & 4 deletions tests/impulse-tests/archs/rust/architecture_osrnt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,9 @@ extern crate libm;
extern crate num_traits;
/* extern crate fastfloat; */

use std::env;
use std::fs::File;
use std::io::Write;

use default_boxed::DefaultBoxed;
use num_traits::{cast::FromPrimitive, float::Float};
use std::{convert::TryInto, env, fs::File, io::Write};

type F32 = f32;
type F64 = f64;
Expand Down
Loading