blob: d0d036ae779cef3f1b17c37f6fca788ef221bfd1 [file] [log] [blame]
/* Test F2008 18.5: ISO_Fortran_binding.h functions. */
#include <ISO_Fortran_binding.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
/* Test the example in F2008 C.12.9: Processing assumed-shape arrays in C,
modified to use CFI_address instead of pointer arithmetic. */
int elemental_mult_c(CFI_cdesc_t * a_desc, CFI_cdesc_t * b_desc,
CFI_cdesc_t * c_desc)
{
CFI_index_t idx[2];
int *res_addr;
int err = 1; /* this error code represents all errors */
if (a_desc->rank == 0)
{
err = *(int*)a_desc->base_addr;
*(int*)a_desc->base_addr = 0;
return err;
}
if (a_desc->type != CFI_type_int
|| b_desc->type != CFI_type_int
|| c_desc->type != CFI_type_int)
return err;
/* Only support two dimensions. */
if (a_desc->rank != 2
|| b_desc->rank != 2
|| c_desc->rank != 2)
return err;
if (a_desc->attribute == CFI_attribute_other)
{
assert (a_desc->dim[0].lower_bound == 0);
assert (a_desc->dim[1].lower_bound == 0);
for (idx[0] = 0; idx[0] < a_desc->dim[0].extent; idx[0]++)
for (idx[1] = 0; idx[1] < a_desc->dim[1].extent; idx[1]++)
{
res_addr = CFI_address (a_desc, idx);
*res_addr = *(int*)CFI_address (b_desc, idx)
* *(int*)CFI_address (c_desc, idx);
}
}
else
{
assert (a_desc->attribute == CFI_attribute_allocatable
|| a_desc->attribute == CFI_attribute_pointer);
for (idx[0] = a_desc->dim[0].lower_bound;
idx[0] < a_desc->dim[0].extent + a_desc->dim[0].lower_bound;
idx[0]++)
for (idx[1] = a_desc->dim[1].lower_bound;
idx[1] < a_desc->dim[1].extent + a_desc->dim[1].lower_bound;
idx[1]++)
{
res_addr = CFI_address (a_desc, idx);
*res_addr = *(int*)CFI_address (b_desc, idx)
* *(int*)CFI_address (c_desc, idx);
}
}
return 0;
}
int deallocate_c(CFI_cdesc_t * dd)
{
return CFI_deallocate(dd);
}
int allocate_c(CFI_cdesc_t * da, CFI_index_t lower[], CFI_index_t upper[])
{
int err = 1;
CFI_index_t idx[2];
int *res_addr;
if (da->attribute == CFI_attribute_other) return err;
if (CFI_allocate(da, lower, upper, 0)) return err;
assert (da->dim[0].lower_bound == lower[0]);
assert (da->dim[1].lower_bound == lower[1]);
for (idx[0] = lower[0]; idx[0] < da->dim[0].extent + lower[0]; idx[0]++)
for (idx[1] = lower[1]; idx[1] < da->dim[1].extent + lower[1]; idx[1]++)
{
res_addr = CFI_address (da, idx);
*res_addr = (int)(idx[0] * idx[1]);
}
return 0;
}
int establish_c(CFI_cdesc_t * desc)
{
typedef struct {double x; double _Complex y;} t;
int err;
CFI_index_t idx[1], extent[1];
t *res_addr;
double value = 1.0;
double complex z_value = 0.0 + 2.0 * I;
extent[0] = 10;
err = CFI_establish((CFI_cdesc_t *)desc,
malloc ((size_t)(extent[0] * sizeof(t))),
CFI_attribute_pointer,
CFI_type_struct,
sizeof(t), 1, extent);
assert (desc->dim[0].lower_bound == 0);
for (idx[0] = 0; idx[0] < extent[0]; idx[0]++)
{
res_addr = (t*)CFI_address (desc, idx);
res_addr->x = value++;
res_addr->y = z_value * (idx[0] + 1);
}
return err;
}
int contiguous_c(CFI_cdesc_t * desc)
{
return CFI_is_contiguous(desc);
}
float section_c(int *std_case, CFI_cdesc_t * source, int *low, int *str)
{
CFI_index_t idx[CFI_MAX_RANK], lower[CFI_MAX_RANK],
strides[CFI_MAX_RANK], upper[CFI_MAX_RANK];
CFI_CDESC_T(1) section;
int ind;
float *ret_addr;
float ans = 0.0;
/* Case (i) from F2018:18.5.5.7. */
if (*std_case == 1)
{
lower[0] = (CFI_index_t)low[0];
strides[0] = (CFI_index_t)str[0];
ind = CFI_establish((CFI_cdesc_t *)&section, NULL, CFI_attribute_other,
CFI_type_float, 0, 1, NULL);
if (ind) return -1.0;
ind = CFI_section((CFI_cdesc_t *)&section, source, lower, NULL, strides);
if (ind) return -2.0;
/* Sum over the section */
for (idx[0] = section.dim[0].lower_bound;
idx[0] < section.dim[0].extent + section.dim[0].lower_bound;
idx[0]++)
ans += *(float*)CFI_address ((CFI_cdesc_t*)&section, idx);
return ans;
}
else if (*std_case == 2)
{
int ind;
lower[0] = source->dim[0].lower_bound;
upper[0] = source->dim[0].lower_bound + source->dim[0].extent - 1;
strides[0] = str[0];
lower[1] = upper[1] = source->dim[1].lower_bound + low[1] - 1;
strides[1] = 0;
ind = CFI_establish((CFI_cdesc_t *)&section, NULL, CFI_attribute_other,
CFI_type_float, 0, 1, NULL);
if (ind) return -1.0;
ind = CFI_section((CFI_cdesc_t *)&section, source,
lower, upper, strides);
assert (section.rank == 1);
if (ind) return -2.0;
/* Sum over the section */
for (idx[0] = section.dim[0].lower_bound;
idx[0] < section.dim[0].extent + section.dim[0].lower_bound;
idx[0]++)
ans += *(float*)CFI_address ((CFI_cdesc_t*)&section, idx);
return ans;
}
return 0.0;
}
double select_part_c (CFI_cdesc_t * source)
{
typedef struct {
double x; double _Complex y;
} t;
CFI_CDESC_T(2) component;
CFI_cdesc_t * comp_cdesc = (CFI_cdesc_t *)&component;
CFI_index_t extent[] = {10,10};
CFI_index_t idx[] = {4,0};
double ans = 0.0;
int size;
(void)CFI_establish(comp_cdesc, NULL, CFI_attribute_other,
CFI_type_double_Complex, sizeof(double _Complex),
2, extent);
(void)CFI_select_part(comp_cdesc, source, offsetof(t,y), 0);
assert (comp_cdesc->dim[0].lower_bound == 0);
assert (comp_cdesc->dim[1].lower_bound == 0);
/* Sum over comp_cdesc[4,:] */
size = comp_cdesc->dim[1].extent;
for (idx[1] = 0; idx[1] < size; idx[1]++)
ans += cimag (*(double _Complex*)CFI_address ((CFI_cdesc_t*)comp_cdesc,
idx));
return ans;
}
int setpointer_c(CFI_cdesc_t * ptr, int lbounds[])
{
CFI_index_t lower_bounds[] = {lbounds[0],lbounds[1]};
int ind;
ind = CFI_setpointer(ptr, ptr, lower_bounds);
return ind;
}
int assumed_size_c(CFI_cdesc_t * desc)
{
int res;
res = CFI_is_contiguous(desc);
if (!res)
return 1;
if (desc->rank)
res = 2 * (desc->dim[desc->rank-1].extent
!= (CFI_index_t)(long long)(-1));
else
res = 3;
return res;
}