Как стать автором
Обновить

Комментарии 14

Почему Вы не использовали SIMD?

для этого придется писать на си.

Итераторы в расте и так по возможности векторизуются, вроде как)

Есть всего две причины:

  1. Мои навыки программирования на Rust и в целом не находятся на высоком уровне - я не знаю как применить SIMD.

  2. Не хочется уводить пример реализации Стрибог в направлении безудержной оптимизации. Моей целью было максимально доступно и просто пояснить шаги алгоритма. Оптимизировать я хотел только те моменты, где я явно делаю странные вещи, например, копирую кучу данных, хотя цели можно добиться передавая ссылку.

Извините за оффтоп (кто о чём, а визуал о картинке). Как вы сделали эффект CRT (кинескопа) на КДПВ? Полупрозрачный слой с диагональными полосками из прямоугольников поверх фона?

В графическом редакторе Gimp есть фильтр "Искажения/Ухудшение видео". У него есть параметр "Узор", который можно выставить в положение "Large 3x3".

Благодарю.

В L вы копируете данные несколько раз, при этом сам алгоритм не подразумевает копий вообще. Вместо перекладывания данных вам нужно применять индексацию с шагом чтобы убрать копии.

Я понимаю, что данные копировать нужды нет, однако я не нашел способа как можно переводить u8 в u64 иным образом. Буду благодарен, если приведете пример.

Вам нужно применять индексацию с шагом чтобы убрать копии.

Немного не понял что вы имели в виду.

В крейте bytemuck есть функция cast_mut. Если без крейта хотите, то через касты указателей в unsafe-е.

Есть что-то вроде u64::from_be_bytes и from_le_bytes, и обратно. Там проблема только с размером, для оптимизации нужно assert расставлять. Ссылка не нужна, компилятор сам оптимизирует чтение и запись, заодно решая проблему выравнивания, вылезающую в случае unsafe.

Не настоящий растовик, то вон немного накидал кода:

use std::ops::{Add, BitXor};

struct U512([u8; 64]);

impl U512 {
    const PI: [u8; 256] = [...];

    // todo std::mem::MaybeUninit
    fn new() -> Self {
        Self {
            0: [0; 64]
        }
    }
    
    fn transform_s(&mut self) {
        for i in 0..64 {
            self.0[i] = Self::PI[usize::from(self.0[i])];
        }
    }
}

impl Add for U512 {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::new();
        let mut temp: u16 = 0;
        for i in (0..64).rev() {
            temp >>= 8;
            temp += u16::from(self.0[i]) + u16::from(other.0[i]);
            result.0[i] = u8::try_from(temp & 0xff).unwrap();
        }
        result
    }
}

impl BitXor for U512 {
    type Output = Self;

    fn bitxor(self, rhs: Self) -> Self::Output {
        let mut result = Self::new();
        for i in 0..64 {
             result.0[i] = self.0[i] ^ rhs.0[i];
        }
        result
    }
}

Точно! Совсем не подумал, что в Rust можно перегрузить операторы да еще и просто псевдоним сделать для типа [u8; 64]! В следующий раз постараюсь об этом не забывать. Спасибо!

Я бы ещё обратил ваше внимание на отсутствие оператора as в моём коде.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории