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
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, Clone, 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) } } /// 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)*] }; );