#include <stdio.h>

static const int N = 32;

#pragma omp declare simd uniform(fact)
double
add1 (double a,
      double b,
      double fact)
{
    return a + b + fact;
}

#pragma omp declare simd uniform(a,b,fact) linear(i:1)
double
add2 (double *a,
      double *b,
      int     i,
      double  fact)
{
    return a[i] + b[i] + fact;
}

#pragma omp declare simd uniform(fact) linear(a,b:1)
double
add3 (double *a,
      double *b,
      double  fact)
{
    return *a + *b + fact;
}

void
work (double *a,
      double *b,
      int     n)
{
    double tmp;

    #pragma omp simd private(tmp)
    for (int i = 0; i < n; i++)
    {
        tmp = add1 (a[i], b[i], 1.0);
        a[i] = add2 (a, b, i, 1.0 + tmp);
        a[i] = add3 (&a[i], &b[i], 1.0);
    }
}

int
main (void)
{
    double a[N], b[N];

    for (int i = 0; i < N; i++)
    {
        a[i] = i;
        b[i] = N - i;
    }

    work (a, b, N);

    for (int i = 0; i < N; i++)
        printf ("%d %f\n", i, a[i]);

    return 0;
}