SHA3-512 NIST FIPS PUB 202 in rust - rust

I'm attempting to implement SHA3-512 the way it is done by NIST in FIPS PUB 202:
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf.
It works whenever I plug in the test vector's bit values + "01"(look for HERE in code), and for the blank value test case.
Example working test vector:
https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg5.pdf
For some reason, whenever string values such as "abc" are plugged in, the hash function fails to work. Despite the conversion from string to binary string being fine, I believe the issue is with the padding function but I cant see where I messed up.
/* Keccak */
struct Keccak<'a> {
b: usize,
d: usize,
r: usize,
l: usize,
w: usize,
delim: &'a str,
}
impl Keccak<'_> {
pub fn new(digest: usize, bits: usize, delim: &str) -> Keccak {
Keccak {
b: bits,
d: digest,
r: (bits - digest * 2),
w: bits / 25,
l: (((bits / 25) as f32).log2()) as usize,
delim,
}
}
pub fn hash(&mut self, msg: &mut String) {
self.sponge(msg);
}
// SPONGE the provided string of binary m
fn sponge(&mut self, msg: &mut String) {
// Pad the message using pad10*1
// HERE: let mut msg = &mut String::from("01");
let len = msg.len() as isize;
self.pad101(msg, self.r as isize, len);
// Let n be size of P
let n = msg.len() / self.r;
// Create vector s of size b/8, each value is a byte
let mut s: Vec<String> = vec!["0".repeat(8); self.b / 8];
// Xor s and p for every p in P
let c = self.b - self.r;
for i in 0..n {
// let p be the message of len(r) + 0^c of size b
let p = format!("{}{}", &msg[i * self.r..(i + 1) * self.r], "0".repeat(c));
// Xor s and p in byte sized intervals, then do a round of keccakf
s = self.keccackf(
&(0..p.len())
.step_by(8)
.map(|x| {
format!(
"{:08?}",
p[x..x + 8].parse::<u32>().unwrap() ^ s[x / 8].parse::<u32>().unwrap()
)
})
.collect::<Vec<String>>()
.join(""),
);
let mut z = String::new();
while z.len() <= self.d {
let mut str = s.join("");
str.truncate(self.r);
z += &str;
s = self.keccackf(&(s.join("")));
}
z.truncate(self.d);
self.from_bin_string(&z);
}
}
// Convert string m to state array
fn to_state(&self, msg: &str) -> Vec<Vec<Vec<u8>>> {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
let i = self.w * (5 * y + x) + z;
column.push(msg[i..i + 1].parse::<u8>().unwrap());
}
row.push(column)
}
s.push(row);
}
s
}
// Convert state array to vector of string
fn from_state(&self, state: Vec<Vec<Vec<u8>>>) -> Vec<String> {
let mut result: Vec<String> = Vec::new();
let mut temp = String::new();
for i in 0..5 {
for j in 0..5 {
for w in 0..self.w {
temp += &format!("{}", state[j][i][w]);
if (temp.len() == 8) {
result.push(temp.clone());
temp = String::new();
}
}
}
}
result
}
fn theta(&self, state: &mut Vec<Vec<Vec<u8>>>) {
// C NIST
fn c(x: usize, z: usize, state: &Vec<Vec<Vec<u8>>>) -> u8 {
state[x][0][z] ^ state[x][1][z] ^ state[x][2][z] ^ state[x][3][z] ^ state[x][4][z]
}
// D NIST
fn d(x: usize, z: usize, state: &Vec<Vec<Vec<u8>>>, w: isize) -> u8 {
c(((x as isize) - 1).rem_euclid(5) as usize, z, state)
^ c(
(x + 1).rem_euclid(5),
((z as isize) - 1).rem_euclid(w) as usize,
state,
)
}
// Let s be a'
let mut s = vec![vec![vec![0; self.w]; 5]; 5];
// Save xor'd values into a'
for x in 0..5 {
for y in 0..5 {
for z in 0..self.w {
s[x][y][z] = state[x][y][z] ^ d(x, z, &state, self.w as isize);
}
}
}
s.clone_into(state);
}
fn rho(&self, state: &mut Vec<Vec<Vec<u8>>>) {
// Let s be a'
let mut s = vec![vec![vec![0; self.w]; 5]; 5];
// Set all z values of a' = a
state[0][0].clone_into(&mut s[0][0]);
// Let coords represent (x, y)
let mut coords = [1, 0];
for t in 0..24 {
for z in 0..self.w {
s[coords[0]][coords[1]][z] = state[coords[0]][coords[1]]
[((z as isize) - (t + 1) * (t + 2) / 2).rem_euclid(self.w as isize) as usize];
}
coords = [coords[1], (2 * coords[0] + 3 * coords[1]).rem_euclid(5)];
}
s.clone_into(state);
}
fn pi(&self, state: &mut Vec<Vec<Vec<u8>>>) {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
column.push(state[((x as usize) + 3 * y).rem_euclid(5)][x][z]);
}
row.push(column)
}
s.push(row);
}
s.clone_into(state)
}
fn chi(&self, state: &mut Vec<Vec<Vec<u8>>>) {
let mut s: Vec<Vec<Vec<u8>>> = Vec::new();
for x in 0..5 {
let mut row = Vec::new();
for y in 0..5 {
let mut column = Vec::new();
for z in 0..self.w {
column.push(
state[x][y][z]
^ ((state[(x + 1).rem_euclid(5)][y][z] ^ 1)
* state[(x + 2).rem_euclid(5)][y][z]),
);
}
row.push(column)
}
s.push(row);
}
s.clone_into(state)
}
fn rc(&self, t: usize) -> u8 {
if t.rem_euclid(255) == 0 {
return 1;
}
let mut r = std::collections::VecDeque::new();
r.extend(
"10000000"
.chars()
.map(|x| x.to_string().parse::<u8>().unwrap()),
);
for _ in 0..t.rem_euclid(255) {
r.push_front(0);
r[0] ^= r[8];
r[4] ^= r[8];
r[5] ^= r[8];
r[6] ^= r[8];
r.truncate(8);
}
return r[0];
}
fn iota(&self, state: &mut Vec<Vec<Vec<u8>>>, round: usize) {
let mut r: Vec<u8> = vec![0; self.w];
for j in 0..=self.l {
r[((2 as isize).pow(j as u32) - 1) as usize] = self.rc(j + 7 * round);
}
for z in 0..self.w {
state[0][0][z] ^= r[z];
}
}
fn keccackf(&self, msg: &str) -> Vec<String> {
let mut state = self.to_state(msg);
// Go through all the rounds
for r in 0..(12 + 2 * self.l) {
self.theta(&mut state);
self.rho(&mut state);
self.pi(&mut state);
self.chi(&mut state);
self.iota(&mut state, r);
}
let res = self.from_state(state);
res
}
// Pad10*1
fn pad101(&mut self, msg: &mut String, x: isize, m: isize) {
let j = (-m - 2).rem_euclid(x);
msg.push_str("1");
msg.push_str(&"0".repeat(j as usize));
msg.push('1');
}
// For nist test vectors
fn from_bin_string(&self, str: &str) {
let z = (0..str.len())
.step_by(8)
.map(|i| (&str[i..i + 8]).chars().rev().collect::<String>())
.collect::<Vec<String>>();
for i in 0..z.len() {
print!("{:02x}", u32::from_str_radix(&z[i], 2).unwrap());
}
}
}
/* Sha3 */
pub struct SHA3<'a> {
kec: Option<Keccak<'a>>,
}
impl SHA3<'_> {
// Creates new hash variable with default hash function, currently SHA512
pub fn new() -> SHA3<'static> {
SHA3 { kec: None }
}
// Sha512
fn SHA512(&mut self, mut msg: String) {
match self.kec.as_mut() {
// Provided kec hash msg
Some(kec) => kec.hash(&mut msg),
// Otherwise create new kec and call function again
None => {
// Creating new keccack struct, l & w & state are defined in NIST
self.kec = Some(Keccak::new(512, 1600, "0110"));
self.SHA512(msg)
}
}
}
// Return hashed vector
pub fn hash(&mut self, m: &str) {
self.SHA512(self.to_bin_string(m) + "01");
}
// Return hexdigest output
pub fn hexdigest(&self, m: &str) {}
// Convert string slice to binary string
fn to_bin_string(&self, str: &str) -> String {
String::from(str)
.as_bytes()
.into_iter()
.map(|x| format!("{:08b}", x))
.collect::<Vec<String>>()
.join("")
}
}

Related

How to traverse and consume a vector in given order? [duplicate]

For example, I have a Vec<String> and an array storing indexes.
let src = vec!["a".to_string(), "b".to_string(), "c".to_string()];
let idx_arr = [2_usize, 0, 1];
The indexes stored in idx_arr comes from the range 0..src.len(), without repetition or omission.
I want to move the elements in src to another container in the given order, until the vector is completely consumed. For example,
let iter = into_iter_in_order(src, &idx_arr);
for s in iter {
// s: String
}
// or
consume_vec_in_order(src, &idx_arr, |s| {
// s: String
});
If the type of src can be changed to Vec<Option<String>>, things will be much easier, just use src[i].take(). However, it cannot.
Edit:
"Another container" refers to any container, such as a queue or hash set. Reordering in place is not the answer to the problem. It introduces the extra time cost of O(n). The ideal method should be 0-cost.
Not sure if my algorithm satisfies your requirements but here I have an algorithm that can consume the provided vector in-order without initializing a new temporary vector, which is more efficient for a memory.
fn main() {
let src = &mut vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()];
let idx_arr = [2_usize, 3, 1, 0];
consume_vector_in_order(src, idx_arr.to_vec());
println!("{:?}", src); // d , c , a , b
}
// In-place consume vector in order
fn consume_vector_in_order<T>(v: &mut Vec<T>, inds: Vec<usize>) -> &mut Vec<T>
where
T: Default,
{
let mut i: usize = 0;
let mut temp_inds = inds.to_vec();
while i < inds.to_vec().len() {
let s_index = temp_inds[i];
if s_index != i {
let new_index = temp_inds[s_index];
temp_inds.swap(s_index, new_index);
v.swap(s_index, new_index);
} else {
i += 1;
}
}
v
}
You can use the technique found in How to sort a Vec by indices? (using my answer in particular) since that can reorder the data in-place from the indices, and then its just simple iteration:
fn consume_vec_in_order<T>(mut vec: Vec<T>, order: &[usize], mut cb: impl FnMut(T)) {
sort_by_indices(&mut vec, order.to_owned());
for elem in vec {
cb(elem);
}
}
Full example available on the playground.
Edit:
An ideal method, but needs to access unstable features and functions not exposed by the standard library.
use std::alloc::{Allocator, RawVec};
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ptr::{self, NonNull};
#[inline]
unsafe fn into_iter_in_order<'a, T, A: Allocator>(
vec: Vec<T, A>,
order: &'a [usize],
) -> IntoIter<'a, T, A> {
unsafe {
let mut vec = ManuallyDrop::new(vec);
let cap = vec.capacity();
let alloc = ManuallyDrop::new(ptr::read(vec.allocator()));
let ptr = order.as_ptr();
let end = ptr.add(order.len());
IntoIter {
buf: NonNull::new_unchecked(vec.as_mut_ptr()),
_marker_1: PhantomData,
cap,
alloc,
ptr,
end,
_marker_2: PhantomData,
}
}
}
struct IntoIter<'a, T, A: Allocator> {
buf: NonNull<T>,
_marker_1: PhantomData<T>,
cap: usize,
alloc: ManuallyDrop<A>,
ptr: *const usize,
end: *const usize,
_marker_2: PhantomData<&'a usize>,
}
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.ptr == self.end {
None
} else {
let idx = unsafe { *self.ptr };
self.ptr = unsafe { self.ptr.add(1) };
if T::IS_ZST {
Some(unsafe { mem::zeroed() })
} else {
Some(unsafe { ptr::read(self.buf.as_ptr().add(idx)) })
}
}
}
}
impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
fn drop(&mut self) {
struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);
impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
fn drop(&mut self) {
unsafe {
// `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec
let alloc = ManuallyDrop::take(&mut self.0.alloc);
// RawVec handles deallocation
let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
}
}
}
let guard = DropGuard(self);
// destroy the remaining elements
unsafe {
while self.ptr != self.end {
let idx = *self.ptr;
self.ptr = self.ptr.add(1);
let p = if T::IS_ZST {
self.buf.as_ptr().wrapping_byte_add(idx)
} else {
self.buf.as_ptr().add(idx)
};
ptr::drop_in_place(p);
}
}
// now `guard` will be dropped and do the rest
}
}
Example:
let src = vec![
"0".to_string(),
"1".to_string(),
"2".to_string(),
"3".to_string(),
"4".to_string(),
];
let mut dst = vec![];
let iter = unsafe { into_iter_in_order(src, &[2, 1, 3, 0, 4]) };
for s in iter {
dst.push(s);
}
assert_eq!(dst, vec!["2", "1", "3", "0", "4"]);
My previous answer:
use std::mem;
use std::ptr;
pub unsafe fn consume_vec_in_order<T>(vec: Vec<T>, order: &[usize], mut cb: impl FnMut(T)) {
// Check whether `order` contains all numbers in 0..len without repetition
// or omission.
if cfg!(debug_assertions) {
use std::collections::HashSet;
let n = order.len();
if n != vec.len() {
panic!("The length of `order` is not equal to that of `vec`.");
}
let mut set = HashSet::<usize>::new();
for &idx in order {
if idx >= n {
panic!("`{idx}` in the `order` is out of range (0..{n}).");
} else if set.contains(&idx) {
panic!("`order` contains the repeated element `{idx}`");
} else {
set.insert(idx);
}
}
}
unsafe {
for &idx in order {
let s = ptr::read(vec.get_unchecked(idx));
cb(s);
}
vec.set_len(0);
}
}
Example:
let src = vec![
"0".to_string(),
"1".to_string(),
"2".to_string(),
"3".to_string(),
"4".to_string(),
];
let mut dst = vec![];
consume_vec_in_order(
src,
&[2, 1, 3, 0, 4],
|elem| dst.push(elem),
);
assert_eq!(dst, vec!["2", "1", "3", "0", "4"]);

Rust trait object in tuple --- expected trait object, found type

I have been reading chapter 17 in The Rust Programming Language and I have been trying to use trait objects in my code.
Could someone please explain why the function test2 does not compile while the others do?
trait Print {
fn print(&self) -> String;
}
impl Print for i32 {
fn print(&self) -> String {
return format!("{}", &self);
}
}
impl Print for &str {
fn print(&self) -> String {
return format!("'{}'", &self);
}
}
pub fn test1() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx = Box::new(0);
let idx = 1;
v.push((idx, bxx));
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
pub fn test2() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx = Box::new(0);
let idx = 2;
let t = (idx, bxx);
v.push(t);
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
pub fn test3() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
v.push((3, Box::new("a")));
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
fn main() {
test1();
test2();
test3();
}
playground
By default when boxing it is gonna take as a box of the espeficit type you are boxing. In your case would be Box<i32>. If you annotate the type specifically then it works:
pub fn test2() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx: Box<dyn Print> = Box::new(0);
let idx = 2;
let t = (idx, bxx);
v.push(t);
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
Playground

rust piston rectangle function does not work within the loop

I want to draw a lot of cells based on 2d array in rust piston library. I try to edit hello world example and have function like so:
fn render(&mut self, args: &RenderArgs) {
const GREEN: [f32; 4] = [0.0f32, 1.0f32, 0.0f32, 1.0f32];
const RED: [f32; 4] = [1.0f32, 0.0f32, 0.0f32, 1.0f32];
let square = rectangle::square(0.0, 0.0, 10.0);
let field = &mut self.field;
self.gl.draw(args.viewport(), |c, gl| -> () {
clear(GREEN, gl);
for x_y_item in field {
let item = x_y_item.2;
if item == 7 {
let x = x_y_item.0;
let y = x_y_item.1;
rectangle(
RED,
square,
c.transform.trans(x as f64 * 10.0, y as f64 * 10.0),
gl,
);
}
}
rectangle(
RED,
square,
c.transform.trans(0 as f64 * 10.0, 0 as f64 * 10.0),
gl,
);
})
}
sadly it doesn't work within the loop.
as in it works fine if I debug print the variables and hardcode them one by one outside of the loop but inside - it just doesn't draw anything, yet doesn't crash.
Update:
I was asked to provide the code to clarify what field is and so it can be runed, so here it is:
Field:
pub struct Grid {
cursor: i32,
body: Vec<Vec<i32>>,
height: i32,
width: i32,
}
impl Grid {
pub fn new(width: i32, height: i32) -> Self {
let mut body: Vec<Vec<i32>> = Vec::with_capacity(height as usize);
let mut temp: Vec<i32> = Vec::with_capacity(width as usize);
for i in 0..width {
temp.push(0);
}
for i in 0..height {
body.push(temp.clone());
}
println!("W: {}, TW:{}, H:{}, TH: {}",width,body[0].len() ,height, body.len());
return Self {cursor: 1 ,width : width, height : height, body : body};
}
pub fn fill(&mut self, value: i32) {
for y in 0..self.height-1 {
for x in 0..self.width - 1 {
self.body[y as usize][x as usize] = value;
}
}
}
pub fn inject(&mut self, pos: (i32,i32), arg: i32) {
self.body[(pos.1 - 1) as usize][(pos.0 - 1) as usize] = arg;
}
pub fn extract(&mut self, pos: (i32,i32)) -> i32 {
return self.body[(pos.1 - 1) as usize][(pos.0 - 1) as usize];
}
pub fn pinpoint(&mut self, val: i32) -> Vec<[i32;2]> {
let mut ret: Vec<[i32;2]> = Vec::new();
for y in 0..self.height {
for x in 0..self.width {
if self.body[y as usize][x as usize] == val {
ret.push([x as i32 + 1,y as i32 + 1]);
}
}
}
return ret;
}
pub fn d_show(&mut self) {
let mut counter: i32 = 1;
for row in self.body.iter() {
println!("{}. {:?}",counter,*row);
counter += 1;
}
}
}
impl Iterator for Grid {
type Item = (i32,i32,i32);
fn next(&mut self) -> Option<Self::Item> {
if self.cursor == self.width * self.height {
return None;
} else {
let x: i32 = self.cursor - (self.cursor/self.width)*self.width;
let y: i32 = self.cursor/self.width;
let val: i32 = 0;
self.cursor += 1;
return Some((x,y,self.body[y as usize][x as usize]));
}
}
}
Main:
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventSettings, Events};
use piston::input::{RenderArgs, RenderEvent, UpdateArgs, UpdateEvent};
use piston::window::WindowSettings;
use graphics::*;
mod arr2d;
use crate::arr2d::Grid;
pub struct State {
field: arr2d::Grid,
gl: GlGraphics,
}
impl State {
fn render(&mut self, args: &RenderArgs) {
const GREEN: [f32;4] = [0.0f32,1.0f32,0.0f32,1.0f32];
const RED: [f32;4] = [1.0f32,0.0f32,0.0f32,1.0f32];
let square = rectangle::square(0.0,0.0,10.0);
let field = &mut self.field;
self.gl.draw(args.viewport(), |c, gl| -> () {
clear(GREEN,gl);
for x_y_item in field {
let item = x_y_item.2;
if item == 7 {
let x = x_y_item.0;
let y = x_y_item.1;
rectangle(RED, square, c.transform.trans(x as f64 * 10.0, y as f64 * 10.0), gl);
}
}
rectangle(RED, square, c.transform.trans(0 as f64 *10.0,0 as f64 *10.0), gl);
})
}
fn update(&mut self, args: &UpdateArgs) {
}
fn new(gl: OpenGL ,w: i32,h: i32) -> Self {
let mut body = Grid::new(w,h);
body.inject((4,4),7);
body.inject((4,5),7);
body.inject((4,6),7);
return Self{gl: GlGraphics::new(gl), field: body};
}
}
fn main() {
let open_gl = OpenGL::V3_2;
let mut window : Window = WindowSettings::new("Spinning Square",[200,200])
.opengl(open_gl)
.exit_on_esc(true)
.build()
.unwrap();
let mut app = State::new(open_gl,20,20);
let mut events = Events::new(EventSettings::new());
while let Some(e) = events.next(&mut window) {
if let Some(args) = e.render_args() {
app.render(&args);
}
if let Some(args) = e.update_args() {
app.update(&args);
}
}
}
Update #2:
I did more research - and created much simpler version of the code based on other tutorials and examples, but that issue still seem to persist:
extern crate piston;
use piston_window::*;
use std::ffi::OsString;
use std::path::Path;
mod tileSet;
mod arr2d;
fn main() {
let mut window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480]).exit_on_esc(true)
.build()
.unwrap();
let mut tilez: tileSet::Textures = tileSet::Textures::from_directory(OsString::from("C:\\Users\\grass\\Desktop\\codes\\Rust\\ghandalf\\assets"),
window.create_texture_context(),
|x: &Path| -> bool {
return x.to_str().unwrap().ends_with(".png");
}
);
let mut field: arr2d::Grid = arr2d::Grid::new(40,40);
field.fill(0);
let mut image: Image = Image::new();
while let Some(event) = window.next() {
window.draw_2d(&event, |context, graphics, _device| {
clear([1.0; 4], graphics);
for (x,y,item) in &mut field {
let tile: String = match item {
0 => "tile0.png".to_string(),
_ => "tile1.png".to_string()
};
image.draw(tilez.get(tile).unwrap(), &DrawState::default(), context.transform.trans(40.0,40.0), graphics); //empty screen here
}
image.draw(tilez.get(tile).unwrap(), &DrawState::default(), context.transform.trans(40.0,40.0), graphics); //works fine here
});
}
}
I tried using hardcoded variables, debugging whether the loop iterates, check if any variable is out of scope but it doesn't seem to give the answer. I think that it has to do with some open gl concept like clearing the screen per iteration perhaps?
It doesn't help that compiler doesn't throw an error.
Yeah, I'm retarded - I forgot to reset iterator implied for arr2d -_-, so it was drawing but was over within 1 frame.

Can I do this with an iterator?

Hi I wrote a function that maps a vector to the interval [0,1]:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
let mut interval: Vec<f32> = vec![0f32; v.len()];
interval[0] = v[0] / total;
for i in 1..v.len() {
interval[i] = interval[i-1] + v[i] / total;
}
return interval;
}
Is there any way to do the same with iterator? I wrote the following but it's slower and needs a for loop:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
let mut interval: Vec<f32> = v
.iter()
.map(|x| x / total)
.collect::<Vec<f32>>();
for i in 1..v.len() {
interval[i] = interval[i-1] + interval[i];
}
return interval;
}
scan can do all of the job:
fn vec2interval(v: &Vec<f32>) -> Vec<f32> {
let total: f32 = v.iter().sum();
v.iter()
.scan(0.0, |acc, x| {
*acc += x / total;
Some(*acc)
})
.collect()
}
Also, slice (&[u8]) better be used instead of Vec<_> as a parameter.

How to pass multiple args to a rust closure - expected closure that takes 1 argument

I am new to closures and I don't understand why I am getting the following error.
If I don't include the second argument its works:
fn obj_x(x: Vec<f64>) -> f64 {
return 0.0;
};
let f = |x: &Vec<f64>| obj_x(x.to_vec());
Here is my closure:
fn foo() {
let f = |x: &Vec<f64>, N: usize| obj_x(x.to_vec(), N);
}
fn obj_x(x: Vec<f64>, N: usize) -> f64 {
let x = (x[0] + 4.0).powf(2.0);
return x;
}
But unfortunately it fails
error[E0593]: closure is expected to take 1 argument, but it takes 2 arguments
--> src/main.rs:120:44
|
114 | let f = |x: &Vec<f64>, N: usize | obj_x(x.to_vec(),N);
| ------------------------- takes 2 arguments
...
120 | let mut fmin = Funcmin::new(&mut x,&f,&g,"cg");
| ^^ expected closure that takes 1 argument
|
Here is my full code:
fn obj_x(x: Vec<f64>, N: usize) -> f64 {
let x = (x[0] + 4.0).powf(2.0);
return x;
}
fn gradient_x(x: Vec<f64>) -> Vec<f64> {
return vec![2.0 * (x[0] + 4.0)];
}
fn test() {
let f = |x: &Vec<f64>, &N: usize| obj_x(x.to_vec(), N);
let g = |x: &Vec<f64>| gradient_x(x.to_vec());
let mut x = vec![40.0f64];
let mut N = 2220;
{
//you must create a mutable object
let mut fmin = Funcmin::new(&mut x, &f, &g, "cg");
fmin.minimize();
}
println!("{:?}", x);
}
This solution worked for me: declare
fn fold(n: u32, init: u32, op: impl Fn(u32, u32) -> u32) -> u32 {...
and call it as
fold(n, 1, |x: u32, y: u32| -> u32 {x + y })

Resources