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 139 140 141 142 143 144 145 146 147 148 149 150 151 152
// Copyright 2014-2016 bluss and ndarray developers. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. 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 `s![0..4;2, 1..5]` is a slice of rows 0..4 with step size 2, /// and columns 1..5 with default step size 1. The slice would have /// shape `[2, 4]`. /// /// If an array has two axes, the slice argument is passed as /// type `&[Si; 2]`. The macro expansion of `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, /// Array, /// }; /// /// fn laplacian(v: &ArrayView<f32, (Ix, Ix)>) -> Array<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); // convert a..b;c into @step(a..b, c), final item (@parse [$($stack:tt)*] $r:expr;$s:expr) => { s![@as_expr &[$($stack)* s!(@step $r, $s)]] }; // convert a..b into @step(a..b, 1), final item (@parse [$($stack:tt)*] $r:expr) => { s![@as_expr &[$($stack)* s!(@step $r, 1)]] }; // convert a..b;c into @step(a..b, c) (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => { s![@parse [$($stack)* s!(@step $r, $s),] $($t)*] }; // convert a..b into @step(a..b, 1) (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => { s![@parse [$($stack)* s!(@step $r, 1),] $($t)*] }; // convert range, step into Si (@step $r:expr, $s:expr) => { <$crate::Si as ::std::convert::From<_>>::from($r).step($s) }; ($($t:tt)*) => { s![@parse [] $($t)*] }; );