#include <gsl/gsl_test.h>
#include <gsl/gsl_ieee_utils.h>
#include <gsl/gsl_math.h>
#include "gsl_cblas.h"

#include "tests.h"

void
test_her2k (void) {
const double flteps = 1e-4, dbleps = 1e-6;
  {
   int order = 101;
   int uplo = 121;
   int trans = 111;
   int N = 1;
   int K = 2;
   float alpha[2] = {0.0f, 0.1f};
   float beta = 0.1f;
   float A[] = { 0.531f, 0.721f, -0.848f, 0.826f };
   int lda = 2;
   float B[] = { -0.711f, -0.2f, -0.92f, -0.676f };
   int ldb = 2;
   float C[] = { -0.447f, 0.701f };
   int ldc = 1;
   float C_expected[] = { 0.30322f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1654) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1654) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 122;
   int trans = 111;
   int N = 1;
   int K = 2;
   float alpha[2] = {0.0f, 0.1f};
   float beta = 0.1f;
   float A[] = { 0.68f, 0.079f, 0.837f, -0.814f };
   int lda = 2;
   float B[] = { -0.986f, 0.024f, 0.584f, -0.248f };
   int ldb = 2;
   float C[] = { 0.477f, -0.551f };
   int ldc = 1;
   float C_expected[] = { 0.120103f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1655) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1655) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 121;
   int trans = 111;
   int N = 1;
   int K = 2;
   float alpha[2] = {0.0f, 0.1f};
   float beta = 0.1f;
   float A[] = { 0.354f, -0.63f, -0.85f, 0.426f };
   int lda = 1;
   float B[] = { 0.787f, -0.228f, -0.568f, 0.83f };
   int ldb = 1;
   float C[] = { 0.428f, -0.388f };
   int ldc = 1;
   float C_expected[] = { 0.0331132f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1656) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1656) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 122;
   int trans = 111;
   int N = 1;
   int K = 2;
   float alpha[2] = {0.0f, 0.1f};
   float beta = 0.1f;
   float A[] = { -0.49f, 0.224f, -0.606f, 0.46f };
   int lda = 1;
   float B[] = { -0.191f, -0.815f, 0.464f, 0.066f };
   int ldb = 1;
   float C[] = { 0.302f, 0.023f };
   int ldc = 1;
   float C_expected[] = { 0.0679396f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1657) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1657) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 121;
   int trans = 113;
   int N = 1;
   int K = 2;
   float alpha[2] = {-1.0f, 0.0f};
   float beta = 0.0f;
   float A[] = { 0.943f, 0.075f, 0.15f, -0.141f };
   int lda = 1;
   float B[] = { -0.962f, 0.422f, -0.592f, -0.789f };
   int ldb = 1;
   float C[] = { 0.728f, 0.601f };
   int ldc = 1;
   float C_expected[] = { 1.70613f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1658) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1658) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 122;
   int trans = 113;
   int N = 1;
   int K = 2;
   float alpha[2] = {-1.0f, 0.0f};
   float beta = 0.0f;
   float A[] = { -0.93f, -0.386f, 0.565f, 0.141f };
   int lda = 1;
   float B[] = { -0.801f, 0.022f, 0.558f, -0.932f };
   int ldb = 1;
   float C[] = { 0.068f, 0.501f };
   int ldc = 1;
   float C_expected[] = { -1.84059f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1659) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1659) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 121;
   int trans = 113;
   int N = 1;
   int K = 2;
   float alpha[2] = {-1.0f, 0.0f};
   float beta = 0.0f;
   float A[] = { -0.383f, 0.124f, 0.458f, -0.221f };
   int lda = 2;
   float B[] = { -0.107f, 0.199f, 0.18f, 0.122f };
   int ldb = 2;
   float C[] = { 0.896f, -0.874f };
   int ldc = 1;
   float C_expected[] = { -0.24227f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1660) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1660) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 122;
   int trans = 113;
   int N = 1;
   int K = 2;
   float alpha[2] = {-1.0f, 0.0f};
   float beta = 0.0f;
   float A[] = { 0.131f, 0.692f, 0.533f, -0.672f };
   int lda = 2;
   float B[] = { -0.435f, -0.453f, 0.195f, -0.579f };
   int ldb = 2;
   float C[] = { -0.547f, 0.736f };
   int ldc = 1;
   float C_expected[] = { -0.245124f, 0.0f };
   cblas_cher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], flteps, "cher2k(case 1661) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], flteps, "cher2k(case 1661) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 121;
   int trans = 111;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { 0.972, -0.353, 0.712, -0.53 };
   int lda = 2;
   double B[] = { 0.787, -0.379, 0.889, 0.901 };
   int ldb = 2;
   double C[] = { 0.002, 0.266 };
   int ldc = 1;
   double C_expected[] = { -0.4278924, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1662) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1662) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 122;
   int trans = 111;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.36, 0.192, 0.539, 0.198 };
   int lda = 2;
   double B[] = { -0.673, 0.781, 0.792, 0.335 };
   int ldb = 2;
   double C[] = { 0.719, -0.339 };
   int ldc = 1;
   double C_expected[] = { -0.485009, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1663) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1663) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 121;
   int trans = 111;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.143, 0.456, 0.677, -0.522 };
   int lda = 1;
   double B[] = { 0.851, 0.196, 0.586, 0.64 };
   int ldb = 1;
   double C[] = { 0.617, 0.118 };
   int ldc = 1;
   double C_expected[] = { 0.1081226, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1664) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1664) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 122;
   int trans = 111;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { 0.801, 0.91, 0.376, -0.006 };
   int lda = 1;
   double B[] = { -0.613, -0.758, -0.966, 0.194 };
   int ldb = 1;
   double C[] = { -0.723, -0.765 };
   int ldc = 1;
   double C_expected[] = { 0.8583678, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1665) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1665) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 121;
   int trans = 113;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.359, 0.913, 0.738, -0.227 };
   int lda = 1;
   double B[] = { 0.787, 0.745, 0.036, -0.606 };
   int ldb = 1;
   double C[] = { -0.652, -0.281 };
   int ldc = 1;
   double C_expected[] = { -0.1172608, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1666) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1666) imag");
     };
   };
  };

  {
   int order = 101;
   int uplo = 122;
   int trans = 113;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.933, 0.598, 0.952, 0.25 };
   int lda = 1;
   double B[] = { -0.508, -0.461, -0.727, 0.162 };
   int ldb = 1;
   double C[] = { 0.215, 0.943 };
   int ldc = 1;
   double C_expected[] = { 0.0795166, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1667) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1667) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 121;
   int trans = 113;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.735, 0.372, -0.251, -0.168 };
   int lda = 2;
   double B[] = { 0.217, 0.863, -0.179, -0.057 };
   int ldb = 2;
   double C[] = { 0.579, -0.305 };
   int ldc = 1;
   double C_expected[] = { 0.0744312, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1668) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1668) imag");
     };
   };
  };

  {
   int order = 102;
   int uplo = 122;
   int trans = 113;
   int N = 1;
   int K = 2;
   double alpha[2] = {-0.3, 0.1};
   double beta = 0.1;
   double A[] = { -0.587, -0.994, -0.625, 0.681 };
   int lda = 2;
   double B[] = { -0.577, -0.014, -0.434, 0.204 };
   int ldb = 2;
   double C[] = { 0.256, 0.093 };
   int ldc = 1;
   double C_expected[] = { -0.3526202, 0.0 };
   cblas_zher2k(order, uplo, trans, N, K, alpha, A, lda, B, ldb, beta, C, ldc);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(C[2*i], C_expected[2*i], dbleps, "zher2k(case 1669) real");
       gsl_test_rel(C[2*i+1], C_expected[2*i+1], dbleps, "zher2k(case 1669) imag");
     };
   };
  };

}


/**
 *
 * @file qwrapper_ztrtri.c
 *
 *  PLASMA core_blas quark wrapper
 *  PLASMA is a software package provided by Univ. of Tennessee,
 *  Univ. of California Berkeley and Univ. of Colorado Denver
 *
 * @version 2.6.0
 * @author Julien Langou
 * @author Henricus Bouwmeester
 * @author Mathieu Faverge
 * @date 2010-11-15
 * @precisions normal z -> c d s
 *
 **/
#include <lapacke.h>
#include "common.h"

/***************************************************************************//**
 *
 **/
void QUARK_CORE_ztrtri(Quark *quark, Quark_Task_Flags *task_flags,
                       PLASMA_enum uplo, PLASMA_enum diag,
                       int n, int nb,
                       PLASMA_Complex64_t *A, int lda,
                       PLASMA_sequence *sequence, PLASMA_request *request,
                       int iinfo)
{
    QUARK_Insert_Task(
        quark, CORE_ztrtri_quark, task_flags,
        sizeof(PLASMA_enum),                &uplo,      VALUE,
        sizeof(PLASMA_enum),                &diag,      VALUE,
        sizeof(int),                        &n,         VALUE,
        sizeof(PLASMA_Complex64_t)*nb*nb,    A,                 INOUT,
        sizeof(int),                        &lda,       VALUE,
        sizeof(PLASMA_sequence*),           &sequence,  VALUE,
        sizeof(PLASMA_request*),            &request,   VALUE,
        sizeof(int),                        &iinfo,     VALUE,
        0);
}

/***************************************************************************//**
 *
 **/
#if defined(PLASMA_HAVE_WEAK)
#pragma weak CORE_ztrtri_quark = PCORE_ztrtri_quark
#define CORE_ztrtri_quark PCORE_ztrtri_quark
#endif
void CORE_ztrtri_quark(Quark *quark)
{
    PLASMA_enum uplo;
    PLASMA_enum diag;
    int N;
    PLASMA_Complex64_t *A;
    int LDA;
    PLASMA_sequence *sequence;
    PLASMA_request *request;
    int iinfo;

    int info;

    quark_unpack_args_8(quark, uplo, diag, N, A, LDA, sequence, request, iinfo);
    info = LAPACKE_ztrtri_work(
        LAPACK_COL_MAJOR,
        lapack_const(uplo), lapack_const(diag),
        N, A, LDA);
    if ((sequence->status == PLASMA_SUCCESS) && (info > 0))
        plasma_sequence_flush(quark, sequence, request, iinfo + info);
}


/**
 *
 * @file qwrapper_slansy.c
 *
 *  PLASMA core_blas quark wrapper
 *  PLASMA is a software package provided by Univ. of Tennessee,
 *  Univ. of California Berkeley and Univ. of Colorado Denver
 *
 * @version 2.6.0
 * @author Julien Langou
 * @author Henricus Bouwmeester
 * @author Mathieu Faverge
 * @date 2010-11-15
 * @generated s Tue Jan  7 11:44:57 2014
 *
 **/
#include <lapacke.h>
#include "common.h"

/***************************************************************************//**
 *
 **/
void QUARK_CORE_slansy(Quark *quark, Quark_Task_Flags *task_flags,
                       int norm, PLASMA_enum uplo, int N,
                       const float *A, int LDA, int szeA,
                       int szeW, float *result)
{
    szeW = max(1, szeW);
    DAG_CORE_LANSY;
    QUARK_Insert_Task(quark, CORE_slansy_quark, task_flags,
        sizeof(PLASMA_enum),                &norm,  VALUE,
        sizeof(PLASMA_enum),                &uplo,  VALUE,
        sizeof(int),                        &N,     VALUE,
        sizeof(float)*szeA,     A,             INPUT,
        sizeof(int),                        &LDA,   VALUE,
        sizeof(float)*szeW,                 NULL,          SCRATCH,
        sizeof(float),                      result,        OUTPUT,
        0);
}

/***************************************************************************//**
 *
 **/
void QUARK_CORE_slansy_f1(Quark *quark, Quark_Task_Flags *task_flags,
                          PLASMA_enum norm, PLASMA_enum uplo, int N,
                          const float *A, int LDA, int szeA,
                          int szeW, float *result,
                          float *fake, int szeF)
{
    szeW = max(1, szeW);
    DAG_CORE_LANSY;

    if ( result == fake ) {
        QUARK_Insert_Task(quark, CORE_slansy_quark, task_flags,
            sizeof(PLASMA_enum),                &norm,  VALUE,
            sizeof(PLASMA_enum),                &uplo,  VALUE,
            sizeof(int),                        &N,     VALUE,
            sizeof(float)*szeA,     A,             INPUT,
            sizeof(int),                        &LDA,   VALUE,
            sizeof(float)*szeW,                 NULL,          SCRATCH,
            sizeof(float)*szeF,                 result,        OUTPUT | GATHERV,
            0);
    } else {
        QUARK_Insert_Task(quark, CORE_slansy_f1_quark, task_flags,
            sizeof(PLASMA_enum),                &norm,  VALUE,
            sizeof(PLASMA_enum),                &uplo,  VALUE,
            sizeof(int),                        &N,     VALUE,
            sizeof(float)*szeA,     A,             INPUT,
            sizeof(int),                        &LDA,   VALUE,
            sizeof(float)*szeW,                 NULL,          SCRATCH,
            sizeof(float),                      result,        OUTPUT,
            sizeof(float)*szeF,                 fake,          OUTPUT | GATHERV,
            0);
    }
}

/***************************************************************************//**
 *
 **/
#if defined(PLASMA_HAVE_WEAK)
#pragma weak CORE_slansy_quark = PCORE_slansy_quark
#define CORE_slansy_quark PCORE_slansy_quark
#endif
void CORE_slansy_quark(Quark *quark)
{
    float *normA;
    int norm;
    PLASMA_enum uplo;
    int N;
    float *A;
    int LDA;
    float *work;

    quark_unpack_args_7(quark, norm, uplo, N, A, LDA, work, normA);
    *normA = LAPACKE_slansy_work(
        LAPACK_COL_MAJOR,
        lapack_const(norm), lapack_const(uplo),
        N, A, LDA, work);
}

/***************************************************************************//**
 *
 **/
#if defined(PLASMA_HAVE_WEAK)
#pragma weak CORE_slansy_f1_quark = PCORE_slansy_f1_quark
#define CORE_slansy_f1_quark PCORE_slansy_f1_quark
#endif
void CORE_slansy_f1_quark(Quark *quark)
{
    float *normA;
    int norm;
    PLASMA_enum uplo;
    int N;
    float *A;
    int LDA;
    float *work;
    float *fake;

    quark_unpack_args_8(quark, norm, uplo, N, A, LDA, work, normA, fake);
    *normA = LAPACKE_slansy_work(
        LAPACK_COL_MAJOR,
        lapack_const(norm),
        lapack_const(uplo),
        N, A, LDA, work);
}


/*
 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/* This file was automatically generated --- DO NOT EDIT */
/* Generated on Sun Nov  7 20:44:44 EST 1999 */

#include <fftw-int.h>
#include <fftw.h>

/* Generated by: ./genfft -magic-alignment-check -magic-twiddle-load-all -magic-variables 4 -magic-loopi -hc2hc-forward 5 */

/*
 * This function contains 64 FP additions, 40 FP multiplications,
 * (or, 44 additions, 20 multiplications, 20 fused multiply/add),
 * 27 stack variables, and 40 memory accesses
 */
static const fftw_real K250000000 = FFTW_KONST(+0.250000000000000000000000000000000000000000000);
static const fftw_real K559016994 = FFTW_KONST(+0.559016994374947424102293417182819058860154590);
static const fftw_real K587785252 = FFTW_KONST(+0.587785252292473129168705954639072768597652438);
static const fftw_real K951056516 = FFTW_KONST(+0.951056516295153572116439333379382143405698634);

/*
 * Generator Id's :
 * $Id: exprdag.ml,v 1.41 1999/05/26 15:44:14 fftw Exp $
 * $Id: fft.ml,v 1.43 1999/05/17 19:44:18 fftw Exp $
 * $Id: to_c.ml,v 1.25 1999/10/26 21:41:32 stevenj Exp $
 */

void fftw_hc2hc_forward_5(fftw_real *A, const fftw_complex *W, int iostride, int m, int dist)
{
     int i;
     fftw_real *X;
     fftw_real *Y;
     X = A;
     Y = A + (5 * iostride);
     {
	  fftw_real tmp70;
	  fftw_real tmp67;
	  fftw_real tmp68;
	  fftw_real tmp63;
	  fftw_real tmp71;
	  fftw_real tmp66;
	  fftw_real tmp69;
	  fftw_real tmp72;
	  ASSERT_ALIGNED_DOUBLE;
	  tmp70 = X[0];
	  {
	       fftw_real tmp61;
	       fftw_real tmp62;
	       fftw_real tmp64;
	       fftw_real tmp65;
	       ASSERT_ALIGNED_DOUBLE;
	       tmp61 = X[4 * iostride];
	       tmp62 = X[iostride];
	       tmp67 = tmp62 + tmp61;
	       tmp64 = X[2 * iostride];
	       tmp65 = X[3 * iostride];
	       tmp68 = tmp64 + tmp65;
	       tmp63 = tmp61 - tmp62;
	       tmp71 = tmp67 + tmp68;
	       tmp66 = tmp64 - tmp65;
	  }
	  Y[-iostride] = (K951056516 * tmp63) - (K587785252 * tmp66);
	  Y[-2 * iostride] = (K587785252 * tmp63) + (K951056516 * tmp66);
	  X[0] = tmp70 + tmp71;
	  tmp69 = K559016994 * (tmp67 - tmp68);
	  tmp72 = tmp70 - (K250000000 * tmp71);
	  X[iostride] = tmp69 + tmp72;
	  X[2 * iostride] = tmp72 - tmp69;
     }
     X = X + dist;
     Y = Y - dist;
     for (i = 2; i < m; i = i + 2, X = X + dist, Y = Y - dist, W = W + 4) {
	  fftw_real tmp13;
	  fftw_real tmp52;
	  fftw_real tmp42;
	  fftw_real tmp45;
	  fftw_real tmp49;
	  fftw_real tmp50;
	  fftw_real tmp51;
	  fftw_real tmp54;
	  fftw_real tmp53;
	  fftw_real tmp24;
	  fftw_real tmp35;
	  fftw_real tmp36;
	  ASSERT_ALIGNED_DOUBLE;
	  tmp13 = X[0];
	  tmp52 = Y[-4 * iostride];
	  {
	       fftw_real tmp18;
	       fftw_real tmp40;
	       fftw_real tmp34;
	       fftw_real tmp44;
	       fftw_real tmp23;
	       fftw_real tmp41;
	       fftw_real tmp29;
	       fftw_real tmp43;
	       ASSERT_ALIGNED_DOUBLE;
	       {
		    fftw_real tmp15;
		    fftw_real tmp17;
		    fftw_real tmp14;
		    fftw_real tmp16;
		    ASSERT_ALIGNED_DOUBLE;
		    tmp15 = X[iostride];
		    tmp17 = Y[-3 * iostride];
		    tmp14 = c_re(W[0]);
		    tmp16 = c_im(W[0]);
		    tmp18 = (tmp14 * tmp15) - (tmp16 * tmp17);
		    tmp40 = (tmp16 * tmp15) + (tmp14 * tmp17);
	       }
	       {
		    fftw_real tmp31;
		    fftw_real tmp33;
		    fftw_real tmp30;
		    fftw_real tmp32;
		    ASSERT_ALIGNED_DOUBLE;
		    tmp31 = X[3 * iostride];
		    tmp33 = Y[-iostride];
		    tmp30 = c_re(W[2]);
		    tmp32 = c_im(W[2]);
		    tmp34 = (tmp30 * tmp31) - (tmp32 * tmp33);
		    tmp44 = (tmp32 * tmp31) + (tmp30 * tmp33);
	       }
	       {
		    fftw_real tmp20;
		    fftw_real tmp22;
		    fftw_real tmp19;
		    fftw_real tmp21;
		    ASSERT_ALIGNED_DOUBLE;
		    tmp20 = X[4 * iostride];
		    tmp22 = Y[0];
		    tmp19 = c_re(W[3]);
		    tmp21 = c_im(W[3]);
		    tmp23 = (tmp19 * tmp20) - (tmp21 * tmp22);
		    tmp41 = (tmp21 * tmp20) + (tmp19 * tmp22);
	       }
	       {
		    fftw_real tmp26;
		    fftw_real tmp28;
		    fftw_real tmp25;
		    fftw_real tmp27;
		    ASSERT_ALIGNED_DOUBLE;
		    tmp26 = X[2 * iostride];
		    tmp28 = Y[-2 * iostride];
		    tmp25 = c_re(W[1]);
		    tmp27 = c_im(W[1]);
		    tmp29 = (tmp25 * tmp26) - (tmp27 * tmp28);
		    tmp43 = (tmp27 * tmp26) + (tmp25 * tmp28);
	       }
	       tmp42 = tmp40 - tmp41;
	       tmp45 = tmp43 - tmp44;
	       tmp49 = tmp40 + tmp41;
	       tmp50 = tmp43 + tmp44;
	       tmp51 = tmp49 + tmp50;
	       tmp54 = tmp29 - tmp34;
	       tmp53 = tmp18 - tmp23;
	       tmp24 = tmp18 + tmp23;
	       tmp35 = tmp29 + tmp34;
	       tmp36 = tmp24 + tmp35;
	  }
	  X[0] = tmp13 + tmp36;
	  {
	       fftw_real tmp46;
	       fftw_real tmp48;
	       fftw_real tmp39;
	       fftw_real tmp47;
	       fftw_real tmp37;
	       fftw_real tmp38;
	       ASSERT_ALIGNED_DOUBLE;
	       tmp46 = (K951056516 * tmp42) + (K587785252 * tmp45);
	       tmp48 = (K951056516 * tmp45) - (K587785252 * tmp42);
	       tmp37 = K559016994 * (tmp24 - tmp35);
	       tmp38 = tmp13 - (K250000000 * tmp36);
	       tmp39 = tmp37 + tmp38;
	       tmp47 = tmp38 - tmp37;
	       Y[-4 * iostride] = tmp39 - tmp46;
	       X[iostride] = tmp39 + tmp46;
	       X[2 * iostride] = tmp47 - tmp48;
	       Y[-3 * iostride] = tmp47 + tmp48;
	  }
	  Y[0] = tmp51 + tmp52;
	  {
	       fftw_real tmp55;
	       fftw_real tmp60;
	       fftw_real tmp58;
	       fftw_real tmp59;
	       fftw_real tmp56;
	       fftw_real tmp57;
	       ASSERT_ALIGNED_DOUBLE;
	       tmp55 = (K951056516 * tmp53) + (K587785252 * tmp54);
	       tmp60 = (K951056516 * tmp54) - (K587785252 * tmp53);
	       tmp56 = K559016994 * (tmp49 - tmp50);
	       tmp57 = tmp52 - (K250000000 * tmp51);
	       tmp58 = tmp56 + tmp57;
	       tmp59 = tmp57 - tmp56;
	       X[4 * iostride] = -(tmp55 + tmp58);
	       Y[-iostride] = tmp58 - tmp55;
	       X[3 * iostride] = -(tmp59 - tmp60);
	       Y[-2 * iostride] = tmp60 + tmp59;
	  }
     }
     if (i == m) {
	  fftw_real tmp8;
	  fftw_real tmp3;
	  fftw_real tmp6;
	  fftw_real tmp9;
	  fftw_real tmp12;
	  fftw_real tmp11;
	  fftw_real tmp7;
	  fftw_real tmp10;
	  ASSERT_ALIGNED_DOUBLE;
	  tmp8 = X[0];
	  {
	       fftw_real tmp1;
	       fftw_real tmp2;
	       fftw_real tmp4;
	       fftw_real tmp5;
	       ASSERT_ALIGNED_DOUBLE;
	       tmp1 = X[2 * iostride];
	       tmp2 = X[3 * iostride];
	       tmp3 = tmp1 - tmp2;
	       tmp4 = X[4 * iostride];
	       tmp5 = X[iostride];
	       tmp6 = tmp4 - tmp5;
	       tmp9 = tmp3 + tmp6;
	       tmp12 = tmp4 + tmp5;
	       tmp11 = tmp1 + tmp2;
	  }
	  X[2 * iostride] = tmp8 + tmp9;
	  tmp7 = K559016994 * (tmp3 - tmp6);
	  tmp10 = tmp8 - (K250000000 * tmp9);
	  X[0] = tmp7 + tmp10;
	  X[iostride] = tmp10 - tmp7;
	  Y[0] = -((K951056516 * tmp11) + (K587785252 * tmp12));
	  Y[-iostride] = -((K951056516 * tmp12) - (K587785252 * tmp11));
     }
}

static const int twiddle_order[] =
{1, 2, 3, 4};
fftw_codelet_desc fftw_hc2hc_forward_5_desc =
{
     "fftw_hc2hc_forward_5",
     (void (*)()) fftw_hc2hc_forward_5,
     5,
     FFTW_FORWARD,
     FFTW_HC2HC,
     113,
     4,
     twiddle_order,
};


/******************************** Inclusions. ********************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>

/******************************** Definitions. *******************************/
#define MAX(x, y) ((x)>(y) ? (x) : (y))
#define MIN(x, y) ((x)<(y) ? (x) : (y))


//! \file heat_driver.h
//! Driver for Magnolia's heat transfer solver
#ifndef ENRICO_SURROGATE_HEAT_DRIVER_H
#define ENRICO_SURROGATE_HEAT_DRIVER_H

#include "driver.h"

#include "pugixml.hpp"
#include "xtensor/xtensor.hpp"
#include <gsl/gsl>
#include <mpi.h>

#include <cstddef>

namespace enrico {

class SurrogateHeatDriver : public Driver {
public:
  //! Initializes heat-fluids surrogate with the given MPI communicator.
  //!
  //! \param comm  The MPI communicator used to initialze the surrogate
  //! \param node  XML node containing settings for surrogate
  explicit SurrogateHeatDriver(MPI_Comm comm, pugi::xml_node node);

  //! Solves the heat-fluids surrogate solver
  void solve_step() final;

  //! Number of rings in fuel and clad
  //! \return Number of rings
  std::size_t n_rings() { return n_fuel_rings_ + n_clad_rings_; }

  //! Write data to VTK
  void write_step(int timestep, int iteration) final;

  xt::xtensor<double, 1> temperature() const;

  double temperature(int pin, int axial, int ring) const;

  // Data on fuel pins
  xt::xtensor<double, 2> pin_centers_; //!< (x,y) values for center of fuel pins
  xt::xtensor<double, 1> z_;           //!< Bounding z-values for axial segments
  std::size_t n_pins_;                 //!< number of fuel pins
  std::size_t n_axial_;                //!< number of axial segments

  // Dimensions for a single fuel pin axial segment
  double clad_outer_radius_;     //!< clad outer radius in [cm]
  double clad_inner_radius_;     //!< clad inner radius in [cm]
  double pellet_radius_;         //!< fuel pellet radius in [cm]
  std::size_t n_fuel_rings_{20}; //!< number of fuel rings
  std::size_t n_clad_rings_{2};  //!< number of clad rings

  // solver variables and settings
  double tol_;                    //!< tolerance on convergence
  xt::xtensor<double, 3> source_; //!< heat source for each (axial segment, ring)
  xt::xtensor<double, 1> r_grid_clad_; //!< radii of each clad ring in [cm]
  xt::xtensor<double, 1> r_grid_fuel_; //!< radii of each fuel ring in [cm]

  // visualization
  std::string viz_basename_{
    "heat_surrogate"}; //!< base filename for visualization files (default: magnolia)
  std::string viz_iterations_{
    "none"};                    //!< visualization iterations to write (none, all, final)
  std::string viz_data_{"all"}; //!< visualization data to write
  std::string viz_regions_{"all"}; //!< visualization regions to write
  size_t vtk_radial_res_{20};      //!< radial resolution of resulting vtk files

private:
  //! Create internal arrays used for heat equation solver
  void generate_arrays();

  //!< temperature in [K] for each (axial segment, ring)
  xt::xtensor<double, 3> temperature_;

}; // end SurrogateHeatDriver

} // namespace enrico

#endif //ENRICO_SURROGATE_HEAT_DRIVER_H


#include <asm/types.h>
#include <glib.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <float.h>

#include <gsl/gsl_histogram.h>

#include <blktrace_api.h>
#include <blktrace.h>
#include <plugins.h>
#include <utils.h>
#include <list_plugins.h>
#include <reqsize.h>

#define DECL_ASSIGN_I2C(name,data)				\
	struct i2c_data *name = (struct i2c_data *)data

#define OIO_ALLOC	(8)

#define N_BINS		(21)
#define BINS_SEP	(8)

struct oio_data
{
#define READ	0
#define WRITE	1
	gsl_histogram *op[2];
	__u64 time;
};

struct i2c_data
{
	GTree *is;
	FILE *oio_f;

	__u32 outstanding;
	__u32 maxouts;

	/* oio hist */
	struct oio_data *oio;
	__u32 oio_size;
	__u64 oio_prev_time;
	FILE *oio_hist_f;
};

static void write_outs(struct i2c_data *i2c, struct blk_io_trace *t)
{
	if(i2c->oio_f)
		fprintf(i2c->oio_f, "%f %u\n",
				NANO_ULL_TO_DOUBLE(t->time),
				i2c->outstanding);
}

static gsl_histogram *new_hist()
{
	gsl_histogram *h;

	/* allocate bins and set ranges uniformally */
	h = gsl_histogram_alloc(N_BINS);
	gsl_histogram_set_ranges_uniform(h,0,N_BINS*BINS_SEP);

	/* last bin should hold everything greater
	 * than (N_BINS-1)*BINS_SEP */
	h->range[h->n] = DBL_MAX;

	return h;
}

static void init_oio_data(struct oio_data *oio, int n)
{
	int i;

	for (i = 0; i < n; i++) {
		oio[i].time = 0;
		oio[i].op[READ] = new_hist();
		oio[i].op[WRITE] = new_hist();
	}
}

static gboolean add_to_matrix(__u64 *__unused, struct blk_io_trace *t, struct i2c_data *i2c)
{
	gsl_histogram_increment(i2c->oio[i2c->outstanding].op[IS_WRITE(t)], (double)(t->bytes/BLK_SIZE));

	return FALSE;
}

static void oio_change(struct i2c_data *i2c, struct blk_io_trace *t, int inc)
{
	/* allocate oio space if the one I had is over */
	if(i2c->outstanding + 1 >= i2c->oio_size) {
		i2c->oio = realloc(i2c->oio, (i2c->oio_size + OIO_ALLOC)*sizeof(struct oio_data));
		init_oio_data(i2c->oio + i2c->oio_size, OIO_ALLOC);
		i2c->oio_size += OIO_ALLOC;
	}

	/* increase the time */
	if(i2c->oio_prev_time != UINT64_MAX) {
		i2c->oio[i2c->outstanding].time += t->time - i2c->oio_prev_time;
	}
	i2c->oio_prev_time = t->time;

	if(inc) {
		i2c->outstanding++;
	} else {
		i2c->outstanding--;
	}
	i2c->maxouts = MAX(i2c->maxouts, i2c->outstanding);

	g_tree_foreach(i2c->is, (GTraverseFunc)add_to_matrix, i2c);

	write_outs(i2c, t);
}

static void C(struct blk_io_trace *t, void *data)
{
	DECL_ASSIGN_I2C(i2c,data);

	if(g_tree_lookup(i2c->is, &t->sector)!=NULL) {
		g_tree_remove(i2c->is, &t->sector);

		oio_change(i2c, t, FALSE);
	}
}

static void I(struct blk_io_trace *t, void *data)
{
	DECL_ASSIGN_I2C(i2c,data);

	if(g_tree_lookup(i2c->is, &t->sector)==NULL) {
		DECL_DUP(struct blk_io_trace,new_t,t);
		g_tree_insert(i2c->is,&new_t->sector,new_t);

		oio_change(i2c, t, TRUE);
	}
}

static void add_histogram(gsl_histogram *h1, gsl_histogram *h2)
{
	unsigned int i;

	for (i = 0; i < h1->n && i < h2->n; i++) {
		h1->bin[i] += h2->bin[i];
	}
}

void i2c_add(void *data1, const void *data2)
{
	DECL_ASSIGN_I2C(i2c1,data1);
	DECL_ASSIGN_I2C(i2c2,data2);
	__u32 i;

	i2c1->maxouts = MAX(i2c1->maxouts, i2c2->maxouts);
	i2c1->oio_prev_time = MAX(i2c1->oio_prev_time, i2c2->oio_prev_time);

	if(i2c1->oio_size < i2c2->oio_size) {
		__u32 diff = i2c2->oio_size - i2c1->oio_size;
		i2c1->oio = realloc(i2c1->oio, i2c2->oio_size*sizeof(struct oio_data));
		init_oio_data(i2c1->oio + diff, diff);
		i2c1->oio_size = i2c2->oio_size;
	}

	for (i = 0; i <= i2c2->maxouts; i++) {
		i2c1->oio[i].time += i2c2->oio[i].time;
		add_histogram(i2c1->oio[i].op[READ],i2c2->oio[i].op[READ]);
		add_histogram(i2c1->oio[i].op[WRITE],i2c2->oio[i].op[WRITE]);
	}
}

void i2c_print_results(const void *data)
{
	DECL_ASSIGN_I2C(i2c,data);
	double p;
	double avg = 0;
	__u32 i;
	__u64 tot_time = 0;

	for (i = 0; i <= i2c->maxouts; i++) {
		tot_time += i2c->oio[i].time;
	}

	for (i = 0; i <= i2c->maxouts; i++) {
		p = ((double)i2c->oio[i].time)/((double)tot_time);

		if(i2c->oio_hist_f)
			fprintf(i2c->oio_hist_f, "%u\t%.2lf\n",i,100*p);

		avg += p*i;
	}

	/* print all histograms */
	if(i2c->oio_hist_f) {
		for (i = 1; i <= i2c->maxouts; i++) {
			fprintf(i2c->oio_hist_f, "\nread: %d\n",i);
			gsl_histogram_fprintf(i2c->oio_hist_f,
					i2c->oio[i].op[READ], "%g", "%g");
			fprintf(i2c->oio_hist_f, "\nwrite: %d\n",i);
			gsl_histogram_fprintf(i2c->oio_hist_f,
					i2c->oio[i].op[WRITE], "%g", "%g");
		}
	}

	printf("I2C Max. OIO: %u, Avg: %.2lf\n",i2c->maxouts,avg);
}

void i2c_init(struct plugin *p, struct plugin_set *__un1, struct plug_args *pa)
{
	char filename[FILENAME_MAX];
	struct i2c_data *i2c = p->data = g_new(struct i2c_data,1);

	i2c->is = g_tree_new(comp_int64);
	i2c->outstanding = 0;
	i2c->maxouts = 0;

	i2c->oio_f = NULL;
	if(pa->i2c_oio_f) {
		get_filename(filename, "i2c_oio", pa->i2c_oio_f, pa->end_range);
		i2c->oio_f = fopen(filename,"w");
		if(!i2c->oio_f) perror_exit("Opening I2C detail file");
	}

	i2c->oio_hist_f = NULL;
	if(pa->i2c_oio_hist_f) {
		get_filename(filename, "i2c_oio_hist", pa->i2c_oio_hist_f, pa->end_range);
		i2c->oio_hist_f = fopen(filename,"w");
		if(!i2c->oio_hist_f) perror_exit("Opening I2C detail file");
	}

	i2c->oio = NULL;
	i2c->oio_size = 0;
	i2c->oio_prev_time = UINT64_MAX;
}

void i2c_ops_init(struct plugin_ops *po)
{
	po->add = i2c_add;
	po->print_results = i2c_print_results;

	/* association of event int and function */
	g_tree_insert(po->event_tree,(gpointer)__BLK_TA_COMPLETE,C);
	g_tree_insert(po->event_tree,(gpointer)__BLK_TA_INSERT,I);
}

void i2c_destroy(struct plugin *p)
{
	unsigned int i;

	DECL_ASSIGN_I2C(i2c,p->data);

	if(i2c->oio_f)
		fclose(i2c->oio_f);

	if(i2c->oio_hist_f)
		fclose(i2c->oio_hist_f);

	for (i = 0; i <= i2c->maxouts; i++) {
		gsl_histogram_free(i2c->oio[i].op[READ]);
		gsl_histogram_free(i2c->oio[i].op[WRITE]);
	}
	free(i2c->oio);

	g_free(p->data);
}