#include "config.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "libgfortran.h"
extern void unpack1 (gfc_array_char *, const gfc_array_char *,
const gfc_array_l4 *, const gfc_array_char *);
iexport_proto(unpack1);
void
unpack1 (gfc_array_char *ret, const gfc_array_char *vector,
const gfc_array_l4 *mask, const gfc_array_char *field)
{
index_type rstride[GFC_MAX_DIMENSIONS];
index_type rstride0;
index_type rs;
char *rptr;
index_type vstride0;
char *vptr;
index_type fstride[GFC_MAX_DIMENSIONS];
index_type fstride0;
const char *fptr;
index_type mstride[GFC_MAX_DIMENSIONS];
index_type mstride0;
const GFC_LOGICAL_4 *mptr;
index_type count[GFC_MAX_DIMENSIONS];
index_type extent[GFC_MAX_DIMENSIONS];
index_type n;
index_type dim;
index_type size;
index_type fsize;
size = GFC_DESCRIPTOR_SIZE (ret);
fsize = GFC_DESCRIPTOR_SIZE (field);
if (ret->data == NULL)
{
dim = GFC_DESCRIPTOR_RANK (mask);
rs = 1;
for (n = 0; n < dim; n++)
{
count[n] = 0;
ret->dim[n].stride = rs;
ret->dim[n].lbound = 0;
ret->dim[n].ubound = mask->dim[n].ubound - mask->dim[n].lbound;
extent[n] = ret->dim[n].ubound + 1;
rstride[n] = ret->dim[n].stride * size;
fstride[n] = field->dim[n].stride * fsize;
mstride[n] = mask->dim[n].stride;
rs *= extent[n];
}
ret->base = 0;
ret->data = internal_malloc_size (rs * size);
}
else
{
dim = GFC_DESCRIPTOR_RANK (ret);
for (n = 0; n < dim; n++)
{
count[n] = 0;
extent[n] = ret->dim[n].ubound + 1 - ret->dim[n].lbound;
rstride[n] = ret->dim[n].stride * size;
fstride[n] = field->dim[n].stride * fsize;
mstride[n] = mask->dim[n].stride;
}
if (rstride[0] == 0)
rstride[0] = size;
}
if (fstride[0] == 0)
fstride[0] = fsize;
if (mstride[0] == 0)
mstride[0] = 1;
vstride0 = vector->dim[0].stride * size;
if (vstride0 == 0)
vstride0 = size;
rstride0 = rstride[0];
fstride0 = fstride[0];
mstride0 = mstride[0];
rptr = ret->data;
fptr = field->data;
mptr = mask->data;
vptr = vector->data;
if (GFC_DESCRIPTOR_SIZE (mask) != 4)
{
if (GFC_DESCRIPTOR_SIZE (mask) != 8)
runtime_error ("Funny sized logical array");
for (n = 0; n < dim; n++)
mstride[n] <<= 1;
mstride0 <<= 1;
mptr = GFOR_POINTER_L8_TO_L4 (mptr);
}
while (rptr)
{
if (*mptr)
{
memcpy (rptr, vptr, size);
vptr += vstride0;
}
else
{
memcpy (rptr, fptr, size);
}
rptr += rstride0;
fptr += fstride0;
mptr += mstride0;
count[0]++;
n = 0;
while (count[n] == extent[n])
{
count[n] = 0;
rptr -= rstride[n] * extent[n];
fptr -= fstride[n] * extent[n];
mptr -= mstride[n] * extent[n];
n++;
if (n >= dim)
{
rptr = NULL;
break;
}
else
{
count[n]++;
rptr += rstride[n];
fptr += fstride[n];
mptr += mstride[n];
}
}
}
}
iexport(unpack1);
extern void unpack0 (const gfc_array_char *, const gfc_array_char *,
const gfc_array_l4 *, char *);
export_proto(unpack0);
void
unpack0 (const gfc_array_char *ret, const gfc_array_char *vector,
const gfc_array_l4 *mask, char *field)
{
gfc_array_char tmp;
tmp.dtype = 0;
tmp.data = field;
unpack1 (ret, vector, mask, &tmp);
}