...
 
Commits (2)
......@@ -281,7 +281,7 @@ struct aml_layout_ops {
* @return NULL on failure with aml_errno set to the error reason.
**/
void *(*deref)(const struct aml_layout_data *data,
const size_t *coords);
const ssize_t *coords);
/**
* Function for derefencing elements of a layout inside the library.
......@@ -296,8 +296,23 @@ struct aml_layout_ops {
* @return NULL on failure with aml_errno set to the error reason.
**/
void *(*deref_native)(const struct aml_layout_data *data,
const size_t *coords);
const ssize_t *coords);
/**
* Function for dereferencing elements of a layout inside the library.
* Layout assumes data is always stored in AML_LAYOUT_ORDER_FORTRAN
* order. Coordinates provided by the library will match the same
* order, i.e last dimension first. Coordinates are interpreted as for a
* zero-based layout.
* @param data[in]: The non-NULL handle to layout internal data.
* @param coords[in]: The non-NULL coordinates on which to access data.
* The first coordinate should be the last dimensions and so on to the
* last, coordinate, last dimension. All coordinates should be positive.
* @return A pointer to the dereferenced element on success.
* @return NULL on failure with aml_errno set to the error reason.
**/
void *(*deref_nobase_native)(const struct aml_layout_data *data,
const ssize_t *coords);
/**
* Get the order in which dimensions of the layout are
* supposed to be accessed by the user.
......@@ -309,6 +324,27 @@ struct aml_layout_ops {
**/
int (*order)(const struct aml_layout_data *data);
/**
* Get the starting index for each dimension of the layout, in the user
* order.
* @param[in] data: layout-internal data
* @param[out] bases: the non-NULL array of starting indices to fill. Must be
* large enough to contain ndims() elements.
* @return AML_SUCCESS on success, else an AML error code.
*/
int (*bases)(const struct aml_layout_data *data, ssize_t *bases);
/**
* Get the starting index for each dimension of the layout, in the order
* it is stored inside the library.
* @param[in] data: layout-internal data
* @param[out] bases: the non-NULL array of starting indices to fill. Must be
* large enough to contain ndims() elements.
* @return AML_SUCCESS on success, else an AML error code.
*/
int (*bases_native)(const struct aml_layout_data *data,
ssize_t *bases);
/**
* Return the layout dimensions in the user order.
* @param data[in]: The non-NULL handle to layout internal data.
......@@ -343,6 +379,31 @@ struct aml_layout_ops {
**/
size_t (*element_size)(const struct aml_layout_data *data);
/**
* Shift the starting index of each dimension of the layout.
* @param[in] data the non-NULL handle to layout internal data.
* @param[out] output a non-NULL pointer to a new layout with shifted
* starting indices.
* @param[in] shift an array of shift to apply to the starting index of
* each dimension. shift(-starts()) should result in a zero-starting
* layout.
* @return AML_SUCCESS on success, else an AML error code (<0).
**/
int (*shift)(const struct aml_layout_data *data, const ssize_t *shift);
/**
* Shift the starting index of each dimension of the layout, using the
* dimension order internal to the library (AML_LAYOUT_ORDER_FORTRAN).
* @param[in] data the non-NULL handle to layout internal data.
* @param[in] shift an array of shift to apply to the starting index of
* each dimension. shift(-starts()) should result in a zero-starting
* layout.
* @return AML_SUCCESS on success, else an AML error code (<0).
**/
int (*shift_native)(const struct aml_layout_data *data,
const ssize_t *shift);
/**
* Reshape the layout with different dimensions.
* Layout dimensions are checked in aml_layout_reshape() to store
......@@ -379,8 +440,8 @@ struct aml_layout_ops {
**/
int (*slice)(const struct aml_layout_data *data,
struct aml_layout **output,
const ssize_t *offsets,
const size_t *dims,
const size_t *offsets,
const size_t *strides);
/**
......@@ -403,8 +464,8 @@ struct aml_layout_ops {
**/
int (*slice_native)(const struct aml_layout_data *data,
struct aml_layout **output,
const ssize_t *offsets,
const size_t *dims,
const size_t *offsets,
const size_t *strides);
};
......@@ -461,7 +522,7 @@ struct aml_layout_ops {
* on possible error codes.
**/
void *aml_layout_deref(const struct aml_layout *layout,
const size_t *coords);
const ssize_t *coords);
/**
* Equivalent to aml_layout_deref() but with bound checking
......@@ -469,7 +530,7 @@ void *aml_layout_deref(const struct aml_layout *layout,
* @see aml_layout_deref()
**/
void *aml_layout_deref_safe(const struct aml_layout *layout,
const size_t *coords);
const ssize_t *coords);
/**
* Get the order in which dimensions of the layout are supposed to be
......@@ -483,6 +544,15 @@ void *aml_layout_deref_safe(const struct aml_layout *layout,
**/
int aml_layout_order(const struct aml_layout *layout);
/**
* Return the layout starting indices in the user order.
* @param[in] layout: An initialized layout.
* @param[out] bases: A non-NULL array of indices to fill. It is
* supposed to be large enough to contain aml_layout_ndims() elements.
* @return AML_SUCCESS on success, else an AML error code.
**/
int aml_layout_bases(const struct aml_layout *layout, ssize_t *bases);
/**
* Return the layout dimensions in the user order.
* @param[in] layout: An initialized layout.
......@@ -506,6 +576,16 @@ size_t aml_layout_ndims(const struct aml_layout *layout);
**/
size_t aml_layout_element_size(const struct aml_layout *layout);
/**
* Shift the starting indices of each dimension.
* @param[in] layout the layout to shift
* @param[in] shifts an array of size ndims() indicating the shift to perform on
* each dimension. shift(-starts()) should result in a zero-starting layout.
* @return AML_SUCCESS on success.
* @return AML_EINVAL if any of the pointers are NULL.
**/
int aml_layout_shift(const struct aml_layout *layout, const ssize_t *shifts);
/**
* @brief Reshape the layout with different dimensions.
* This function checks that the number of elements of
......@@ -551,8 +631,8 @@ int aml_layout_reshape(const struct aml_layout *layout,
**/
int aml_layout_slice(const struct aml_layout *layout,
struct aml_layout **reshaped_layout,
const ssize_t *offsets,
const size_t *dims,
const size_t *offsets,
const size_t *strides);
////////////////////////////////////////////////////////////////////////////////
......
......@@ -36,6 +36,10 @@ struct aml_layout_dense {
void *ptr;
/** number of dimensions **/
size_t ndims;
/**
* starting index for each dimension, can be negative.
**/
ssize_t *bases;
/**
* dimensions, in element size, of the data structure,
* by order of appearance in memory.
......@@ -67,6 +71,7 @@ struct aml_layout_dense {
* dimension.
* @param[in] pitch: The space between consecutive elements of the same
* dimension. If NULL, pitch is set to the number of elements in each dimension.
* @param[in] bases: the starting index of each dimension. If NULL, set to 0.
* @return -AML_ENOMEM if layout allocation failed.
* @return -AML_EINVAL if layout is NULL.
* @return AML_SUCCESS if creation succeeded.
......@@ -79,7 +84,8 @@ int aml_layout_dense_create(struct aml_layout **layout,
const size_t ndims,
const size_t *dims,
const size_t *stride,
const size_t *pitch);
const size_t *pitch,
const ssize_t *bases);
/**
* Function to free a dense layout.
......@@ -96,7 +102,19 @@ void aml_layout_dense_destroy(struct aml_layout **layout);
* @see aml_layout_deref_native()
**/
void *aml_layout_column_deref(const struct aml_layout_data *data,
const size_t *coords);
const ssize_t *coords);
/**
* Deref operator for dense layout in AML_ORDER_COLUMN_MAJOR.
* Also used as the deref operator for this type of layout.
* Does not check its argument. If data is NULL, or coords are out
* of bounds, the behaviour of aml_layout_column_deref() is undefined.
* Coords are assumed to be for an access on a zero-based layout.
* @see aml_layout_deref()
* @see aml_layout_deref_native()
**/
void *aml_layout_column_deref_nobase(const struct aml_layout_data *data,
const ssize_t *coords);
/**
* Layout operator for retrieving order of dimension storage.
......@@ -120,12 +138,31 @@ size_t aml_layout_dense_ndims(const struct aml_layout_data *data);
**/
size_t aml_layout_dense_element_size(const struct aml_layout_data *data);
/**
* Operator for retrieving the starting indexes of each dimension of the layout,
* in column major order.
* Does not check data is not NULL. If data is NULL or not the good
* pointer type, the behaviour is undefined.
* Arguments are supposed to be checked in aml_layout_bases().
* @see aml_layout_bases()
**/
int aml_layout_column_bases(const struct aml_layout_data *data, ssize_t *bases);
/**
* Operator for retrieving dimensions size of a layout with column major order.
* Does not check data is not NULL. If data is NULL or not the good
* pointer type, the behaviour is undefined.
* Arguments are supposed to be checked in aml_layout_dims().
* @see aml_layout_dims()
**/
int aml_layout_column_dims(const struct aml_layout_data *data, size_t *dims);
/**
* Operator for reshaping dense layouts with column major order.
* Does not check if the number of elements match.
* This should be done in aml_layout_reshape().
* @return -AML_EINVAL if merge then split of dimensions
* cannot be done appropriatly.
* cannot be done appropriately.
* @return -AML_ENOMEM if the resulting layout cannot be allocated.
* @return AML_SUCCESS on successful reshape.
* @see aml_layout_reshape()
......@@ -145,7 +182,7 @@ int aml_layout_column_reshape(const struct aml_layout_data *data,
**/
int aml_layout_column_slice(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides);
......@@ -158,7 +195,7 @@ int aml_layout_column_slice(const struct aml_layout_data *data,
* @see aml_layout_deref()
**/
void *aml_layout_row_deref(const struct aml_layout_data *data,
const size_t *coords);
const ssize_t *coords);
/**
* Operator for retrieving layout order of a row major layout.
......@@ -167,6 +204,16 @@ void *aml_layout_row_deref(const struct aml_layout_data *data,
**/
int aml_layout_row_order(const struct aml_layout_data *data);
/**
* Operator for retrieving the starting indexes of each dimension of the layout,
* in row major order.
* Does not check data is not NULL. If data is NULL or not the good
* pointer type, the behaviour is undefined.
* Arguments are supposed to be checked in aml_layout_bases().
* @see aml_layout_bases()
**/
int aml_layout_row_bases(const struct aml_layout_data *data, ssize_t *bases);
/**
* Operator for retrieving dimensions size of a layout with row major order.
* Does not check data is not NULL. If data is NULL or not the good
......@@ -201,7 +248,7 @@ int aml_layout_row_reshape(const struct aml_layout_data *data,
**/
int aml_layout_row_slice(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides);
......@@ -217,7 +264,7 @@ int aml_layout_row_slice(const struct aml_layout_data *data,
**/
int aml_layout_row_slice_native(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides);
......
......@@ -34,7 +34,30 @@
* @return NULL on failure with aml_errno set to the error reason.
**/
void *aml_layout_deref_native(const struct aml_layout *layout,
const size_t *coords);
const ssize_t *coords);
/**
* Function for dereferencing elements of a layout inside the library.
* Layout assumes data is always stored in AML_LAYOUT_ORDER_FORTRAN order.
* Coordinates provided by the library will match the same order, i.e
* last dimension first. Coordinates are assumed to be for a zero-based layout.
* @param[in] layout: An initialized layout.
* @param[in] coords: The coordinates on which to access data.
* The first coordinate should be the last dimensions and so on to the last,
* coordinate, last dimension. Coordinates must be positive.
* @return A pointer to the dereferenced element on success.
* @return NULL on failure with aml_errno set to the error reason.
**/
void *aml_layout_deref_nobase_native(const struct aml_layout *layout,
const ssize_t *coords);
/**
* Return the layout starting indices in the user order.
* @param[in] layout: An initialized layout.
* @param[out] bases: A non-NULL array of indices to fill. It must be large
* enough to contain aml_layout_ndims() elements.
* @return AML_SUCCESS on success, else an AML error code.
**/
int aml_layout_bases_native(const struct aml_layout *layout, ssize_t *bases);
/**
* Return the layout dimensions in the order they are actually stored
......@@ -69,7 +92,7 @@ int aml_layout_dims_native(const struct aml_layout *layout,
**/
int aml_layout_slice_native(const struct aml_layout *layout,
struct aml_layout **reshaped_layout,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides);
......
......@@ -24,6 +24,7 @@
* This code is all macros to handle the type specific logic we need.
**/
/** Returns the allocation size required to handle two objects side-by-side.
*
* Use an anonymous struct to ask the compiler what size an allocation should be
......
......@@ -24,13 +24,13 @@ static inline void aml_copy_layout_generic_helper(size_t d,
const struct aml_layout *src,
const size_t *elem_number,
size_t elem_size,
size_t *coords)
ssize_t *coords)
{
if (d == 1) {
for (size_t i = 0; i < elem_number[0]; i += 1) {
coords[0] = i;
memcpy(aml_layout_deref_native(dst, coords),
aml_layout_deref_native(src, coords),
memcpy(aml_layout_deref_nobase_native(dst, coords),
aml_layout_deref_nobase_native(src, coords),
elem_size);
}
} else {
......@@ -55,7 +55,7 @@ int aml_copy_layout_generic(struct aml_layout *dst,
assert(aml_layout_element_size(dst) == aml_layout_element_size(src));
elem_size = aml_layout_element_size(dst);
size_t coords[d];
ssize_t coords[d];
size_t elem_number[d];
size_t elem_number2[d];
......
......@@ -18,9 +18,10 @@ static int aml_layout_dense_alloc(struct aml_layout **ret,
struct aml_layout *layout;
struct aml_layout_dense *data;
assert(sizeof(size_t) == sizeof(ssize_t));
layout = AML_INNER_MALLOC_EXTRA(struct aml_layout,
struct aml_layout_dense,
size_t, 3*ndims);
size_t, 4*ndims);
if (layout == NULL) {
*ret = NULL;
return -AML_ENOMEM;
......@@ -33,22 +34,27 @@ static int aml_layout_dense_alloc(struct aml_layout **ret,
data->ptr = NULL;
data->ndims = ndims;
data->bases = AML_INNER_MALLOC_EXTRA_NEXTPTR(layout,
struct aml_layout,
struct aml_layout_dense,
size_t, 0);
data->dims = AML_INNER_MALLOC_EXTRA_NEXTPTR(layout,
struct aml_layout,
struct aml_layout_dense,
size_t, 0);
size_t, ndims);
data->stride = AML_INNER_MALLOC_EXTRA_NEXTPTR(layout,
struct aml_layout,
struct aml_layout_dense,
size_t, ndims);
size_t, ndims*2);
for (size_t i = 0; i < ndims; i++)
data->stride[i] = 1;
data->cpitch = AML_INNER_MALLOC_EXTRA_NEXTPTR(layout,
struct aml_layout,
struct aml_layout_dense,
size_t, ndims*2);
size_t, ndims*3);
*ret = layout;
return AML_SUCCESS;
}
......@@ -64,6 +70,7 @@ void aml_layout_dense_init_cpitch(struct aml_layout *layout,
struct aml_layout_dense *data =
(struct aml_layout_dense *)layout->data;
data->ptr = ptr;
memset(data->bases, 0, ndims * sizeof(ssize_t));
memcpy(data->dims, dims, ndims * sizeof(size_t));
memcpy(data->stride, stride, ndims * sizeof(size_t));
memcpy(data->cpitch, cpitch, ndims * sizeof(size_t));
......@@ -76,7 +83,8 @@ int aml_layout_dense_create(struct aml_layout **layout,
const size_t ndims,
const size_t *dims,
const size_t *stride,
const size_t *pitch)
const size_t *pitch,
const ssize_t *bases)
{
struct aml_layout *l;
......@@ -108,6 +116,10 @@ int aml_layout_dense_create(struct aml_layout **layout,
_pitch[i] = pitch[ndims-i-1];
else
_pitch[i] = dims[ndims-i-1];
if (bases)
data->bases[i] = bases[i];
else
data->bases[i] = 0;
}
break;
......@@ -120,6 +132,10 @@ int aml_layout_dense_create(struct aml_layout **layout,
memcpy(_pitch, pitch, ndims * sizeof(size_t));
else
memcpy(_pitch, dims, ndims * sizeof(size_t));
if (bases)
memcpy(data->bases, bases, ndims * sizeof(ssize_t));
else
memset(data->bases, 0, ndims * sizeof(ssize_t));
break;
default:
free(l);
......@@ -146,7 +162,20 @@ void aml_layout_dense_destroy(struct aml_layout **l)
******************************************************************************/
void *aml_layout_column_deref(const struct aml_layout_data *data,
const size_t *coords)
const ssize_t *coords)
{
char *ptr;
const struct aml_layout_dense *d;
d = (const struct aml_layout_dense *) data;
ptr = (char *) d->ptr;
for (size_t i = 0; i < d->ndims; i++)
ptr += (coords[i]-d->bases[i])*d->cpitch[i]*d->stride[i];
return (void *)ptr;
}
void *aml_layout_column_deref_nobase(const struct aml_layout_data *data,
const ssize_t *coords)
{
char *ptr;
const struct aml_layout_dense *d;
......@@ -164,6 +193,18 @@ int aml_layout_column_order(const struct aml_layout_data *data)
return AML_LAYOUT_ORDER_COLUMN_MAJOR;
}
int aml_layout_column_bases(const struct aml_layout_data *data,
ssize_t *bases)
{
const struct aml_layout_dense *d;
d = (const struct aml_layout_dense *) data;
assert(d != NULL);
assert(bases != NULL);
memcpy((void *)bases, (void *)d->bases, sizeof(ssize_t)*d->ndims);
return 0;
}
int aml_layout_column_dims(const struct aml_layout_data *data, size_t *dims)
{
const struct aml_layout_dense *d;
......@@ -192,6 +233,16 @@ size_t aml_layout_dense_element_size(const struct aml_layout_data *data)
return d->cpitch[0];
}
int aml_layout_column_shift(const struct aml_layout_data *data,
const ssize_t *shifts)
{
const struct aml_layout_dense *d;
d = (const struct aml_layout_dense *)data;
for(size_t i = 0; i < d->ndims; i++)
d->bases[i] += shifts[i];
return AML_SUCCESS;
}
/* Given a layout parameters (ndim, dims, stride, and cpitch), returns
* the representation of this layout that uses the least dimensions.
......@@ -333,7 +384,7 @@ int aml_layout_column_reshape(const struct aml_layout_data *data,
int aml_layout_column_slice(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides)
{
......@@ -372,11 +423,16 @@ int aml_layout_column_slice(const struct aml_layout_data *data,
struct aml_layout_ops aml_layout_column_ops = {
aml_layout_column_deref,
aml_layout_column_deref,
aml_layout_column_deref_nobase,
aml_layout_column_order,
aml_layout_column_bases,
aml_layout_column_bases,
aml_layout_column_dims,
aml_layout_column_dims,
aml_layout_dense_ndims,
aml_layout_dense_element_size,
aml_layout_column_shift,
aml_layout_column_shift,
aml_layout_column_reshape,
aml_layout_column_slice,
aml_layout_column_slice,
......@@ -387,7 +443,7 @@ struct aml_layout_ops aml_layout_column_ops = {
******************************************************************************/
void *aml_layout_row_deref(const struct aml_layout_data *data,
const size_t *coords)
const ssize_t *coords)
{
const struct aml_layout_dense *d;
char *ptr;
......@@ -396,8 +452,7 @@ void *aml_layout_row_deref(const struct aml_layout_data *data,
ptr = (char *) d->ptr;
for (size_t i = 0; i < d->ndims; i++) {
ptr +=
coords[i] *
ptr += (coords[i]-d->bases[d->ndims - i - 1]) *
d->cpitch[d->ndims - i - 1] *
d->stride[d->ndims - i - 1];
}
......@@ -410,6 +465,17 @@ int aml_layout_row_order(const struct aml_layout_data *data)
return AML_LAYOUT_ORDER_ROW_MAJOR;
}
int aml_layout_row_bases(const struct aml_layout_data *data,
ssize_t *bases)
{
const struct aml_layout_dense *d;
d = (const struct aml_layout_dense *) data;
for (size_t i = 0; i < d->ndims; i++)
bases[i] = d->bases[d->ndims - i - 1];
return 0;
}
int aml_layout_row_dims(const struct aml_layout_data *data, size_t *dims)
{
const struct aml_layout_dense *d;
......@@ -420,6 +486,16 @@ int aml_layout_row_dims(const struct aml_layout_data *data, size_t *dims)
return 0;
}
int aml_layout_row_shift(const struct aml_layout_data *data,
const ssize_t *shifts)
{
const struct aml_layout_dense *d;
d = (const struct aml_layout_dense *)data;
for(size_t i = 0; i < d->ndims; i++)
d->bases[i] = d->bases[i] + shifts[d->ndims - i - 1];
return AML_SUCCESS;
}
int aml_layout_row_reshape(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t ndims,
......@@ -461,7 +537,7 @@ int aml_layout_row_reshape(const struct aml_layout_data *data,
int aml_layout_row_slice(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides)
{
......@@ -472,8 +548,8 @@ int aml_layout_row_slice(const struct aml_layout_data *data,
d = (const struct aml_layout_dense *)data;
size_t cpitch[d->ndims];
size_t n_offsets[d->ndims];
size_t cpitch[d->ndims + 1];
ssize_t n_offsets[d->ndims];
size_t n_dims[d->ndims];
size_t n_strides[d->ndims];
......@@ -507,7 +583,7 @@ int aml_layout_row_slice(const struct aml_layout_data *data,
int aml_layout_row_slice_native(const struct aml_layout_data *data,
struct aml_layout **output,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides)
{
......@@ -546,11 +622,16 @@ int aml_layout_row_slice_native(const struct aml_layout_data *data,
struct aml_layout_ops aml_layout_row_ops = {
aml_layout_row_deref,
aml_layout_column_deref,
aml_layout_column_deref_nobase,
aml_layout_row_order,
aml_layout_row_bases,
aml_layout_column_bases,
aml_layout_row_dims,
aml_layout_column_dims,
aml_layout_dense_ndims,
aml_layout_dense_element_size,
aml_layout_row_shift,
aml_layout_column_shift,
aml_layout_row_reshape,
aml_layout_row_slice,
aml_layout_row_slice_native
......
......@@ -11,26 +11,30 @@
#include "aml.h"
static int
aml_check_layout_coords(const struct aml_layout *layout,
int (*get_dims)(const struct aml_layout_data *,
size_t *), const size_t *coords)
aml_check_layout_coords(const struct aml_layout *layout, const ssize_t *coords)
{
size_t ndims = layout->ops->ndims(layout->data);
size_t dims[ndims];
ssize_t bases[ndims];
int err = AML_SUCCESS;
err = get_dims(layout->data, dims);
err = layout->ops->dims(layout->data, dims);
if (err != AML_SUCCESS)
return err;
err = layout->ops->bases(layout->data, bases);
if (err != AML_SUCCESS)
return err;
while (ndims--)
if (coords[ndims] >= dims[ndims])
for(size_t i = 0; i < ndims; i++) {
ssize_t max = bases[i] + dims[i];
if (coords[i] < bases[i] || coords[i] >= max)
return -AML_EINVAL;
}
return AML_SUCCESS;
}
void *aml_layout_deref(const struct aml_layout *layout, const size_t *coords)
void *aml_layout_deref(const struct aml_layout *layout, const ssize_t *coords)
{
assert(layout != NULL &&
layout->ops != NULL &&
......@@ -40,23 +44,22 @@ void *aml_layout_deref(const struct aml_layout *layout, const size_t *coords)
}
void *aml_layout_deref_safe(const struct aml_layout *layout,
const size_t *coords)
const ssize_t *coords)
{
assert(layout != NULL &&
layout->ops != NULL &&
layout->ops->deref != NULL &&
layout->ops->ndims != NULL &&
layout->ops->bases != NULL &&
layout->ops->dims != NULL);
assert(aml_check_layout_coords(layout,
layout->ops->dims,
coords) == AML_SUCCESS);
assert(aml_check_layout_coords(layout, coords) == AML_SUCCESS);
return layout->ops->deref(layout->data, coords);
}
void *aml_layout_deref_native(const struct aml_layout *layout,
const size_t *coords)
const ssize_t *coords)
{
assert(layout != NULL &&
layout->ops != NULL &&
......@@ -67,6 +70,18 @@ void *aml_layout_deref_native(const struct aml_layout *layout,
return layout->ops->deref_native(layout->data, coords);
}
void *aml_layout_deref_nobase_native(const struct aml_layout *layout,
const ssize_t *coords)
{
assert(layout != NULL &&
layout->ops != NULL &&
layout->ops->deref_native != NULL &&
layout->ops->ndims != NULL &&
layout->ops->dims_native != NULL);
return layout->ops->deref_nobase_native(layout->data, coords);
}
int aml_layout_order(const struct aml_layout *layout)
{
assert(layout != NULL &&
......@@ -76,6 +91,24 @@ int aml_layout_order(const struct aml_layout *layout)
return layout->ops->order(layout->data);
}
int aml_layout_bases(const struct aml_layout *layout, ssize_t *bases)
{
assert(layout != NULL &&
layout->ops != NULL &&
layout->ops->bases != NULL);
return layout->ops->bases(layout->data, bases);
}
int aml_layout_bases_native(const struct aml_layout *layout, ssize_t *bases)
{
assert(layout != NULL &&
layout->ops != NULL &&
layout->ops->bases_native != NULL);
return layout->ops->bases_native(layout->data, bases);
}
int aml_layout_dims(const struct aml_layout *layout, size_t *dims)
{
assert(layout != NULL &&
......@@ -165,63 +198,57 @@ int aml_layout_reshape(const struct aml_layout *layout,
return err;
}
/**
* This function will collect the layout dimensions and check that
* the slice queried will fit into the layout.
**/
/* Checks that the offsets don't make the slice overflow out of the layout */
static int
aml_check_layout_slice(const struct aml_layout *layout,
int (*get_dims)(const struct aml_layout_data *,
size_t *),
const size_t *offsets,
const size_t *dims,
const size_t *strides)
aml_check_layout_slice(const size_t ndims, const size_t *src_dims,
const ssize_t *offsets, const size_t *dims,
const size_t *strides, const ssize_t *bases)
{
assert(layout->ops->ndims != NULL &&
layout->ops->dims != NULL);
int err = AML_SUCCESS;
size_t ndims = layout->ops->ndims(layout->data);
size_t n_elements;
size_t layout_dims[ndims];
err = get_dims(layout->data, layout_dims);
if (err != AML_SUCCESS)
return err;
for (size_t i = 0; i < ndims; i++) {
n_elements = offsets[i] + (dims[i]-1) * strides[i];
if (offsets[i] < bases[i])
return -AML_EINVAL;
ssize_t max = bases[i] + src_dims[i];
ssize_t last_in_slice = offsets[i] + (dims[i]-1) * strides[i];
if (n_elements > layout_dims[i])
if (last_in_slice >= max)
return -AML_EINVAL;
}
return AML_SUCCESS;
}
int aml_layout_slice(const struct aml_layout *layout,
struct aml_layout **reshaped_layout,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides)
{
assert(layout != NULL &&
layout->ops != NULL);
assert(layout != NULL && layout->ops != NULL);
if (layout->ops->slice == NULL)
return -AML_ENOTSUP;
if (reshaped_layout == NULL)
return -AML_EINVAL;
size_t ndims = aml_layout_ndims(layout);
struct aml_layout *result;
int err;
size_t _offsets[ndims];
ssize_t _offsets[ndims];
size_t _dims[ndims];
size_t _strides[ndims];
ssize_t bases[ndims];
assert(layout->ops->bases(layout->data, bases) == AML_SUCCESS);
assert(layout->ops->dims(layout->data, _dims) == AML_SUCCESS);
if (offsets)
memcpy(_offsets, offsets, ndims * sizeof(*offsets));
else
for (size_t i = 0; i < ndims; i++)
_offsets[i] = 0;
_offsets[i] = bases[i];
if (strides)
memcpy(_strides, strides, ndims * sizeof(*strides));
......@@ -229,11 +256,10 @@ int aml_layout_slice(const struct aml_layout *layout,
for (size_t i = 0; i < ndims; i++)
_strides[i] = 1;
assert(aml_check_layout_slice(layout,
layout->ops->dims,
_offsets,
dims,
_strides) == AML_SUCCESS);
err = aml_check_layout_slice(ndims, _dims, _offsets, dims, _strides,
bases);
if (err != AML_SUCCESS)
return err;
err = layout->ops->slice(layout->data,
&result,
......@@ -248,27 +274,45 @@ int aml_layout_slice(const struct aml_layout *layout,
int aml_layout_slice_native(const struct aml_layout *layout,
struct aml_layout **reshaped_layout,
const size_t *offsets,
const ssize_t *offsets,
const size_t *dims,
const size_t *strides)
{
assert(layout != NULL &&
layout->ops != NULL);
assert(layout != NULL && layout->ops != NULL);
if (layout->ops->slice_native == NULL)
return -AML_ENOTSUP;
assert(layout->ops->ndims != NULL &&
layout->ops->dims_native != NULL);
assert(layout->ops->ndims != NULL && layout->ops->dims_native != NULL);
size_t ndims = aml_layout_ndims(layout);
struct aml_layout *result;
int err;
ssize_t _offsets[ndims];
size_t _dims[ndims];
size_t _strides[ndims];
ssize_t bases[ndims];
assert(layout->ops->bases_native(layout->data, bases) == AML_SUCCESS);
assert(layout->ops->dims_native(layout->data, _dims) == AML_SUCCESS);
if (offsets)
memcpy(_offsets, offsets, ndims * sizeof(*offsets));
else
for (size_t i = 0; i < ndims; i++)
_offsets[i] = bases[i];
if (strides)
memcpy(_strides, strides, ndims * sizeof(*strides));
else
for (size_t i = 0; i < ndims; i++)
_strides[i] = 1;
assert(aml_check_layout_slice(layout,
layout->ops->dims_native,
dims,
offsets,
strides) == AML_SUCCESS);
err = aml_check_layout_slice(ndims, _dims, _offsets, _dims, _strides,
bases);
if (err != AML_SUCCESS)
return err;
err = layout->ops->slice_native(layout->data,
&result, offsets, dims, strides);
......
......@@ -119,7 +119,7 @@ void aml_layout_pad_destroy(struct aml_layout **l)
******************************************************************************/
void *aml_layout_pad_column_deref(const struct aml_layout_data *data,
const size_t *coords)
const ssize_t *coords)
{
assert(data != NULL);
const struct aml_layout_pad *d = (const struct aml_layout_pad *)data;
......@@ -167,6 +167,8 @@ struct aml_layout_ops aml_layout_pad_column_ops = {
aml_layout_pad_column_deref,
aml_layout_pad_column_deref,
aml_layout_pad_column_order,
NULL,
NULL,
aml_layout_pad_column_dims,
aml_layout_pad_column_dims,
aml_layout_pad_ndims,
......@@ -174,6 +176,8 @@ struct aml_layout_ops aml_layout_pad_column_ops = {
NULL,
NULL,
NULL,
NULL,
NULL,
};
/*******************************************************************************
......@@ -181,7 +185,7 @@ struct aml_layout_ops aml_layout_pad_column_ops = {
******************************************************************************/
void *aml_layout_pad_row_deref(const struct aml_layout_data *data,
const size_t *coords)
const ssize_t *coords)
{
assert(data != NULL);
const struct aml_layout_pad *d = (const struct aml_layout_pad *)data;
......@@ -189,14 +193,14 @@ void *aml_layout_pad_row_deref(const struct aml_layout_data *data,
int type;
for (size_t i = 0; i < ndims; i++) {
if (coords[ndims - i - 1] >= d->target_dims[i])
if (coords[ndims - i - 1] >= d->target_dims[i])
return d->neutral;
}
type = aml_layout_order(d->target);
if (AML_LAYOUT_ORDER(type) == AML_LAYOUT_ORDER_ROW_MAJOR) {
return aml_layout_deref(d->target, coords);
} else if (AML_LAYOUT_ORDER(type) == AML_LAYOUT_ORDER_COLUMN_MAJOR) {
size_t target_coords[ndims];
ssize_t target_coords[ndims];
for (size_t i = 0; i < ndims; i++)
target_coords[i] = coords[ndims - i - 1];
......@@ -225,6 +229,8 @@ struct aml_layout_ops aml_layout_pad_row_ops = {
aml_layout_pad_row_deref,
aml_layout_pad_column_deref,
aml_layout_pad_row_order,
NULL,
NULL,
aml_layout_pad_row_dims,
aml_layout_pad_column_dims,
aml_layout_pad_ndims,
......@@ -232,5 +238,7 @@ struct aml_layout_ops aml_layout_pad_row_ops = {
NULL,
NULL,
NULL,
NULL,
NULL,
};
......@@ -142,7 +142,7 @@ aml_tiling_pad_column_index(const struct aml_tiling_data *t,
assert(d != NULL);
size_t ndims = d->ndims;
size_t offsets[ndims];
ssize_t offsets[ndims];
size_t dims[ndims];
size_t strides[ndims];
......@@ -275,7 +275,7 @@ aml_tiling_pad_row_index(const struct aml_tiling_data *t, const size_t *coords)
assert(d != NULL);
size_t ndims = d->ndims;
size_t offsets[ndims];
ssize_t offsets[ndims];
size_t dims[ndims];
size_t strides[ndims];
......
......@@ -125,7 +125,7 @@ aml_tiling_resize_column_index(const struct aml_tiling_data *t,
assert(d != NULL);
size_t ndims = d->ndims;
size_t offsets[ndims];
ssize_t offsets[ndims];
size_t dims[ndims];
size_t strides[ndims];
......@@ -238,7 +238,7 @@ aml_tiling_resize_row_index(const struct aml_tiling_data *t,
assert(d != NULL);
size_t ndims = d->ndims;
size_t offsets[ndims];
ssize_t offsets[ndims];
size_t dims[ndims];
size_t strides[ndims];
......