Есть ли эквивалент Rust ndarray для арифметики numpy на срезе? - PullRequest
0 голосов
/ 18 мая 2018

Следующий код Python будет многократно добавлять вектор [1, 2, 3, 4] к каждой строке в двумерном массиве a, начиная только с 20-й строки.

import numpy as np

# an array of shape (100, 4)
a = np.zeros((100, 4), dtype=np.float32)

# and this is the operation explained above
a[20:, :] += [1.0, 2.0, 3.0, 0.0]

Существует ли простой эквивалентэто с ndarray?Я уже могу делать то, что мне нужно, с более сложным, грязно выглядящим кодом, но чувствую, что, возможно, есть аккуратный эквивалент ndarray.rs.Я просто не мог откопать ...

Я использую массивы формы f32 (n, 8), представляющие три местоположения вершин, три нормальных компонента и две координаты наложения текстуры.Я объединяю буферы из нескольких 3D-объектов в один для более эффективной визуализации графики.В пределах широкого массива 8 первые три значения должны быть масштабированы, т.е. умножены на &[sx, sy, sz], затем повернуты с использованием стандартной функции rz.dot(&rx.dot(&ry.dot())) и, наконец, добавлено смещение &[dx, dy, dz].Нормалы просто нужно вращать.Моя нынешняя система включает в себя хранение данных в переменных промежуточного массива.

use ndarray as nd;
array_buffer: nd::Array2<f32>, loc: &[f32; 3], scl: &[f32; 3]...
...
// scale then rotate new verts then add displacement
let new_verts = &new_buf.array_buffer.slice(s![.., 0..3]) * &nd::arr1(scl);
let new_verts = rotate_vec(rot, &new_verts) + &nd::arr1(loc);
// then add them to existing verts
let mut verts = nd::stack(nd::Axis(0),
                &[old_buf.array_buffer.slice(s![.., 0..3]),
                  new_verts.view()]).unwrap();
...

Я знаю, что не смогу сократить их до однослойной строки

verts = np.append(old_buf.array_buffer[:,0:3], 
        rotate_vec(rot, (new_buf.array_buffer[:,0:3] * scl) + loc))

, но я подумал, что, возможно,некоторые из вариантов карт или почтовых индексов или макросов могут помочь мне.

1 Ответ

0 голосов

Это можно сделать с теми же двумя шагами, что и в Python: нарезка , затем добавление-присвоение для широковещательного правого массива.

use ndarray::Array2;

let mut a: Array2<f32> = Array2::zeros((100, 4));
{ 
    let mut slice = a.slice_mut(s![20.., ..]);
    slice += &ArrayView::from(&[1.0, 2.0, 3.0, 4.0]);
}

Нарезка выполняется с помощью slice_mut и макроса s! для определения предполагаемого диапазона.Результатом среза является представление изменяемого массива, поэтому доступны большинство операций, видимых в ArrayBase, включая арифметические операции.По правилам широковещания правосторонний массив формы [4] может автоматически транслироваться на одну из форм [100, 4] для оператора +=.


В случае других недоразумений при переходе сndarray ящик Python to Rust, документация содержит руководство для пользователей Python .

...