Thanks for your response, John. It is unfortunate that the C-API doesn't
support negative step sizes. I am currently limited to C++11 features by
the client, but it is good to know that the C++ standard is looking to add
something for multi-dimensional support of some sort in the future. My main
data structure is boost's multi_array, which I managed to find some very
convoluted documentation on how to "flip" a dimension around:
https://www.boost.org/doc/libs/1_62_0/libs/multi_array/doc/user.html#sec_storage
which ended up being far too awkward to use with how my code was set up.
Anyway, I ended up figuring out a different location in my code to address
my data flipping needs with minimal performance penalties compared to the
rest of the code. Thank you for your help!
Ben Root
On Sun, May 17, 2020 at 3:01 AM John Buonagurio <jbuonagurio@xxxxxxxxxxxx>
wrote:
> Hi Ben,
>
> On Fri, 15 May 2020 at 18:07 Benjamin Root <ben.v.root@xxxxxxxxx> wrote:
>
> > The documentation for the strided access to variables specify a pointer
> to
> > ptrdiff_t types, which I infer means that I could specify a negative
> value
> > to read/write in a dimension in reverse. However, when I gave this a
> shot,
> > specifying a -1 for the latitude dimension of one of my datasets, the C
> > api came back and said I had an illegal stride.
> >
> > Is there any way to read/write dimensions in reverse order, much like
> > python's [::-1] with the C-API, or am I going to have to flip the data
> > around myself (I'd like to avoid the copy, as well as all of the fun
> code
> > to do so for an arbitrary dimension). At the very least, are there
> helper
> > functions for this?
>
> That's not supported by the C API:
>
>
> https://github.com/Unidata/netcdf-c/blob/64d821b/libdispatch/dvarget.c#L245-L248
>
> https://github.com/Unidata/netcdf-c/blob/b0e0d81/libhdf5/hdf5var.c#L1845-L1847
>
> Flipping the data around doesn't necessarily require a copy; it can be
> done in-place with a complexity of N/2 swaps (`std::reverse` in C++). But
> yes doing it for an arbitrary dimension rather than the full array will
> require some index calculations. I think something like this might do the
> job, albeit not the most efficient approach (untested):
>
> 1. Get the variable values along that dimension, and reverse.
>
> 2. Flatten the N-D indexes into 1-D indexes by calculating an inner
> product with the strides. In NumPy this is `ravel_multi_index`; in C++
> I use `std::inner_product` in <numeric>.
>
> 3. Copy the reversed elements back into the original array using the 1-D
> indexes.
>
> I have some code here in a simple `get_var1` iterator which does the
> reverse operation, unraveling a 1-D index into an N-D index given the
> shape (`unravel_index` in NumPy).
>
>
> https://github.com/jbuonagurio/ncpp/blob/717bb1e/include/ncpp/variable.hpp#L421-L495
>
> I'm sure there are more clever ways. I would use a multidimensional
> 'array view' library if you can and your data are stored contiguously.
> I mostly work in C++ so not sure about other options, but I know that
> xtensor and the reference implementation of the `std::mdspan` proposal
> support arbitrary strides.
>
> - John Buonagurio
>
>