1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
use std::ops::{Range, RangeFrom, RangeTo, RangeFull}; use super::Ixs; // [a:b:s] syntax for example [:3], [::-1] // [0,:] -- first row of matrix // [:,0] -- first column of matrix #[derive(Copy, PartialEq, Eq, Hash, Debug)] /// A slice, a description of a range of an array axis. /// /// Fields are `begin`, `end` and `stride`, where /// negative `begin` or `end` indexes are counted from the back /// of the axis. /// /// If `end` is `None`, the slice extends to the end of the axis. /// /// See also the [`s![] macro`](macro.s!.html), a convenient way to specify /// an array of `Si`. /// /// ## Examples /// /// `Si(0, None, 1)` is the full range of an axis. /// Python equivalent is `[:]`. Macro equivalent is `s![..]`. /// /// `Si(a, Some(b), 2)` is every second element from `a` until `b`. /// Python equivalent is `[a:b:2]`. Macro equivalent is `s![a..b;2]`. /// /// `Si(a, None, -1)` is every element, from `a` /// until the end, in reverse order. Python equivalent is `[a::-1]`. /// Macro equivalent is `s![a..;-1]`. /// /// The constant [`S`] is a shorthand for the full range of an axis. /// [`S`]: constant.S.html pub struct Si(pub Ixs, pub Option<Ixs>, pub Ixs); impl From<Range<Ixs>> for Si { #[inline] fn from(r: Range<Ixs>) -> Si { Si(r.start, Some(r.end), 1) } } impl From<RangeFrom<Ixs>> for Si { #[inline] fn from(r: RangeFrom<Ixs>) -> Si { Si(r.start, None, 1) } } impl From<RangeTo<Ixs>> for Si { #[inline] fn from(r: RangeTo<Ixs>) -> Si { Si(0, Some(r.end), 1) } } impl From<RangeFull> for Si { #[inline] fn from(_: RangeFull) -> Si { S } } impl Si { #[inline] pub fn step(self, step: Ixs) -> Self { Si(self.0, self.1, self.2 * step) } } impl Clone for Si { #[inline] fn clone(&self) -> Self { *self } } /// Slice value for the full range of an axis. pub const S: Si = Si(0, None, 1); /// Slice argument constructor. /// /// `s![]` takes a list of ranges, separated by comma, with optional strides /// that are separated from the range by a semicolon. /// It is converted into a slice argument with type `&[Si; N]`. /// /// Each range uses signed indices, where a negative value is counted from /// the end of the axis. Strides are also signed and may be negative, but /// must not be zero. /// /// For example, if an array has two axes, the slice argument is passed as /// type `&[Si; 2]`. /// /// For example `s![a..b;c, d..e]` /// is equivalent to `&[Si(a, Some(b), c), Si(d, Some(e), 1)]`. /// /// ``` /// #[macro_use] /// extern crate ndarray; /// /// use ndarray::{ /// ArrayView, /// Ix, /// OwnedArray, /// }; /// /// fn laplacian(v: &ArrayView<f32, (Ix, Ix)>) -> OwnedArray<f32, (Ix, Ix)> { /// -4. * &v.slice(s![1..-1, 1..-1]) /// + v.slice(s![ ..-2, 1..-1]) /// + v.slice(s![1..-1, ..-2]) /// + v.slice(s![1..-1, 2.. ]) /// + v.slice(s![2.. , 1..-1]) /// } /// # fn main() { } /// ``` #[macro_export] macro_rules! s( (@as_expr $e:expr) => ($e); (@parse [$($stack:tt)*] $r:expr;$s:expr) => { s![@as_expr &[$($stack)* s!(@step $r, $s)]] }; (@parse [$($stack:tt)*] $r:expr) => { s![@as_expr &[$($stack)* s!(@step $r, 1)]] }; (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => { s![@parse [$($stack)* s!(@step $r, $s),] $($t)*] }; (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => { s![@parse [$($stack)* s!(@step $r, 1),] $($t)*] }; (@step $r:expr, $s:expr) => { <$crate::Si as ::std::convert::From<_>>::from($r).step($s) }; ($($t:tt)*) => { s![@parse [] $($t)*] }; );