#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_trmv (void) {
const double flteps = 1e-4, dbleps = 1e-6;
  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.136206f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 814)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.138f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 815)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.136206f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 816)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.138f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 817)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.136206f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 818)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.138f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 819)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.136206f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 820)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.987f };
   float X[] = { -0.138f };
   int incX = -1;
   float x_expected[] = { -0.138f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 821)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { -0.152327f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 822)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { 0.463f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 823)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { -0.152327f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 824)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { 0.463f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 825)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { -0.152327f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 826)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { 0.463f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 827)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { -0.152327f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 828)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.329f };
   float X[] = { 0.463f };
   int incX = -1;
   float x_expected[] = { 0.463f };
   cblas_strmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], flteps, "strmv(case 829)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { 0.385671 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 830)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { -0.899 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 831)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { 0.385671 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 832)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { -0.899 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 833)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { 0.385671 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 834)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { -0.899 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 835)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { 0.385671 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 836)");
     }
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.429 };
   double X[] = { -0.899 };
   int incX = -1;
   double x_expected[] = { -0.899 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 837)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.161664 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 838)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.192 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 839)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.161664 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 840)");
     }
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.192 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 841)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.161664 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 842)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.192 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 843)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.161664 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 844)");
     }
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.842 };
   double X[] = { 0.192 };
   int incX = -1;
   double x_expected[] = { 0.192 };
   cblas_dtrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[i], x_expected[i], dbleps, "dtrmv(case 845)");
     }
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { -0.038016f, -0.133218f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 846) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 846) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { 0.542f, 0.461f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 847) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 847) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { -0.038016f, -0.133218f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 848) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 848) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { 0.542f, 0.461f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 849) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 849) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { -0.038016f, -0.133218f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 850) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 850) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { 0.542f, 0.461f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 851) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 851) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { -0.038016f, -0.133218f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 852) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 852) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { -0.162f, -0.108f };
   float X[] = { 0.542f, 0.461f };
   int incX = -1;
   float x_expected[] = { 0.542f, 0.461f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 853) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 853) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.418216f, 0.061332f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 854) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 854) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.302f, 0.434f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 855) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 855) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.418216f, 0.061332f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 856) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 856) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.302f, 0.434f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 857) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 857) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.418216f, 0.061332f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 858) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 858) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.302f, 0.434f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 859) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 859) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.418216f, 0.061332f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 860) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 860) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.547f, 0.583f };
   float X[] = { -0.302f, 0.434f };
   int incX = -1;
   float x_expected[] = { -0.302f, 0.434f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 861) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 861) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.178848f, 0.044136f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 862) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 862) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.564f, -0.297f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 863) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 863) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.178848f, 0.044136f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 864) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 864) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.564f, -0.297f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 865) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 865) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.178848f, 0.044136f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 866) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 866) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.564f, -0.297f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 867) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 867) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.178848f, 0.044136f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 868) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 868) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   float A[] = { 0.216f, 0.192f };
   float X[] = { -0.564f, -0.297f };
   int incX = -1;
   float x_expected[] = { -0.564f, -0.297f };
   cblas_ctrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], flteps, "ctrmv(case 869) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], flteps, "ctrmv(case 869) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { 0.125587, 0.638297 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 870) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 870) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { -0.101, 0.889 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 871) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 871) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { 0.125587, 0.638297 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 872) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 872) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { -0.101, 0.889 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 873) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 873) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { 0.125587, 0.638297 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 874) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 874) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { -0.101, 0.889 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 875) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 875) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { 0.125587, 0.638297 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 876) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 876) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 111;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { 0.693, -0.22 };
   double X[] = { -0.101, 0.889 };
   int incX = -1;
   double x_expected[] = { -0.101, 0.889 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 877) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 877) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.172171, -0.093192 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 878) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 878) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.048, 0.293 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 879) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 879) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.172171, -0.093192 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 880) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 880) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.048, 0.293 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 881) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 881) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.172171, -0.093192 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 882) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 882) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.048, 0.293 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 883) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 883) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.172171, -0.093192 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 884) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 884) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 112;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.216, -0.623 };
   double X[] = { 0.048, 0.293 };
   int incX = -1;
   double x_expected[] = { 0.048, 0.293 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 885) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 885) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.009338, -0.705318 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 886) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 886) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.708, 0.298 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 887) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 887) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.009338, -0.705318 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 888) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 888) imag");
     };
   };
  };

  {
   int order = 101;
   int trans = 113;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.708, 0.298 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 889) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 889) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 121;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.009338, -0.705318 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 890) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 890) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 121;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.708, 0.298 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 891) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 891) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 122;
   int diag = 131;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.009338, -0.705318 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 892) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 892) imag");
     };
   };
  };

  {
   int order = 102;
   int trans = 113;
   int uplo = 122;
   int diag = 132;
   int N = 1;
   int lda = 1;
   double A[] = { -0.345, -0.851 };
   double X[] = { -0.708, 0.298 };
   int incX = -1;
   double x_expected[] = { -0.708, 0.298 };
   cblas_ztrmv(order, uplo, trans, diag, N, A, lda, X, incX);
   {
     int i;
     for (i = 0; i < 1; i++) {
       gsl_test_rel(X[2*i], x_expected[2*i], dbleps, "ztrmv(case 893) real");
       gsl_test_rel(X[2*i+1], x_expected[2*i+1], dbleps, "ztrmv(case 893) imag");
     };
   };
  };

}


#pragma once
/****************************************************************************
 *
 *  nc.h
 *      ($\nativecoin-cpp\src)
 *
 *  by icedac
 *
 ***/
#ifndef ___NATIVECOIN__NATIVECOIN__NC_H_
#define ___NATIVECOIN__NATIVECOIN__NC_H_

#include <string>
#include <vector>
#include <unordered_map>
#include <set>
#include <iostream>
#include <sstream>

#define GSL_THROW_ON_CONTRACT_VIOLATION
#include <gsl/gsl>

#include <utility>
#include <stdio.h>
#include <tuple>
#include <iomanip>

#include "platform.h"

namespace nc {
    typedef unsigned char byte;
    typedef std::int32_t int32;
    typedef std::int64_t int64;
    typedef std::uint32_t uint32;
    typedef std::uint64_t uint64;
    using string = std::string;
    template < typename T >
    using vector = std::vector<T>;
    template < typename T >
    using set = std::set<T>;
    using stringstream = std::stringstream;
    using ostringstream = std::ostringstream;

    template < typename K, typename T >
    using unordered_map = std::unordered_map< K, T>;

    typedef uint32 difficulty_t;
    typedef uint64 nonce_t;
    typedef uint64 timestamp_t;
    typedef uint32 blockindex_t;
}

namespace nc {

    class coin {
    public:
        static const auto SATOSHI_PER_COIN = 1000000;
        explicit inline coin() noexcept : satoshi(0) {}
        explicit inline coin(int32 amount) noexcept : satoshi(amount*SATOSHI_PER_COIN) {}

        inline coin(const coin& c) = default;
        inline coin& operator = (const coin& rhs) = default;
        inline coin(coin&& c) = default;
        inline coin& operator = (coin&& rhs) = default;

        inline operator int32() const {
            return get();
        }

        inline coin& operator += (const coin& rhs) {
            satoshi += rhs.get_as_satoshi();
            return *this;
        }

        inline coin& operator -= (const coin& rhs) {
            satoshi -= rhs.get_as_satoshi();
            return *this;
        }

        inline coin operator + (const coin& rhs) {
            return coin::from_satoshi(this->get_as_satoshi() + rhs.get_as_satoshi());
        }
        inline coin operator - (const coin& rhs) {
            return coin::from_satoshi(this->get_as_satoshi() - rhs.get_as_satoshi());
        }

        inline bool operator == (const coin& rhs) const {
            return this->satoshi == rhs.satoshi;
        }
        inline bool operator != (const coin& rhs) const {
            return !(*this == rhs);
        }

        inline int32 get() const {
            return (int32)(satoshi / SATOSHI_PER_COIN);
        }

        inline int64 get_as_satoshi() const { return satoshi; }

        inline int64 get_satoshi() const {
            return satoshi % SATOSHI_PER_COIN;
        }

        inline string as_string() const {

            int64 satoshi = get_satoshi();

            ostringstream ss;
            ss << get() << ".";
            if (satoshi)
                ss << std::setfill('0') << std::setw(6) << satoshi;
            else
                ss << "00";

            return ss.str();
        }

        static inline coin from_satoshi(int64 satoshi) {
            coin c{ 0 };
            c.satoshi = satoshi;
            return c;
        }

    private:
        int64		satoshi;
    };
}

#endif// ___NATIVECOIN__NATIVECOIN__NC_H_


#ifndef QDM_IJK_H
#define QDM_IJK_H 1

#include <stddef.h>

#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <hdf5.h>

typedef struct {
  size_t size1;
  size_t size2;
  size_t size3;

  double *data;
  bool owner;
} qdm_ijk;

typedef struct {
  qdm_ijk ijk;
} qdm_ijk_view;

qdm_ijk *
qdm_ijk_alloc(
    size_t size1,
    size_t size2,
    size_t size3
);

qdm_ijk *
qdm_ijk_calloc(
    size_t size1,
    size_t size2,
    size_t size3
);

void
qdm_ijk_free(qdm_ijk *t);

qdm_ijk_view
qdm_ijk_view_array(
    double *base,
    size_t size1,
    size_t size2,
    size_t size3
);

gsl_vector_view
qdm_ijk_get_k(
    qdm_ijk *t,
    size_t i,
    size_t j
);

gsl_matrix_view
qdm_ijk_get_ij(
    qdm_ijk *t,
    size_t k
);

double
qdm_ijk_get(
    qdm_ijk *t,
    size_t i,
    size_t j,
    size_t k
);

gsl_matrix *
qdm_ijk_cov(
    qdm_ijk *t
);

int
qdm_ijk_write(
    hid_t id,
    const char *name,
    const qdm_ijk *t
);

int
qdm_ijk_read(
    hid_t id,
    const char *name,
    qdm_ijk **t
);

#endif /* QDM_IJK_H */


/**
 *
 * @file
 *
 *  PLASMA is a software package provided by:
 *  University of Tennessee, US,
 *  University of Manchester, UK.
 *
 **/
#ifndef ICL_CORE_LAPACK_H
#define ICL_CORE_LAPACK_H

#ifdef PLASMA_WITH_MKL
    #include <mkl_cblas.h>
    #include <mkl_lapacke.h>

    // MKL LAPACKE doesn't provide LAPACK_GLOBAL macro, so define it here.
    // MKL provides all 3 name manglings (foo, foo_, FOO); pick foo_.
    #ifndef LAPACK_GLOBAL
    #define LAPACK_GLOBAL(lcname,UCNAME)  lcname##_
    #endif
#else
    #include <cblas.h>
    #include <lapacke.h>

    // Intel mkl_cblas.h does: typedef enum {...} CBLAS_ORDER;
    // Netlib    cblas.h does: enum CBLAS_ORDER {...};
    // OpenBLAS  cblas.h does: typedef enum CBLAS_ORDER {...} CBLAS_ORDER;
    // We use (CBLAS_ORDER), so add these typedefs for Netlib.
    #ifndef OPENBLAS_VERSION
    typedef enum CBLAS_ORDER CBLAS_ORDER;
    typedef enum CBLAS_TRANSPOSE CBLAS_TRANSPOSE;
    typedef enum CBLAS_UPLO CBLAS_UPLO;
    typedef enum CBLAS_DIAG CBLAS_DIAG;
    typedef enum CBLAS_SIDE CBLAS_SIDE;
    #endif
#endif

#include "core_lapack_s.h"
#include "core_lapack_d.h"
#include "core_lapack_c.h"
#include "core_lapack_z.h"

#endif // ICL_CORE_LAPACK_H


/*
* -----------------------------------------------------------------
*  Binary Search Tree Library --- bst_lib.c
*  Version: 1.6180
*  Date: Mar 12, 2010
* -----------------------------------------------------------------
*  Programmer: Americo Barbosa da Cunha Junior
*              americo.cunhajr@gmail.com
* -----------------------------------------------------------------
*  Copyright (c) 2010 by Americo Barbosa da Cunha Junior
*
*  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 3 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.
*
*  A copy of the GNU General Public License is available in
*  LICENSE.txt or http://www.gnu.org/licenses/.
* -----------------------------------------------------------------
*  This is the implementation file of a library
*  to work with binary search trees.
* -----------------------------------------------------------------
*/

#include <stdlib.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_errno.h>

#include "../include/bst_lib.h"

/*
*------------------------------------------------------------
*   bst_leaf_alloc
*
*   This function allocates a struct leaf.
*
*   Input:
*   void
*
*   Output:
*   leaf - pointer to a struct leaf
*
*   last update: May 10, 2009
*------------------------------------------------------------
*/

bst_leaf *bst_leaf_alloc()
{
    bst_leaf *leaf = NULL;

    /* memory allocation for bst_leaf */
    leaf = (bst_leaf *) malloc(sizeof(bst_leaf));
    if ( leaf == NULL )
        return NULL;

    /* setting bst_leaf elements equal to NULL */
    leaf->phi  = NULL;
    leaf->Rphi = NULL;
    leaf->A    = NULL;
    leaf->L    = NULL;

    return leaf;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_node_alloc
*
*   This function allocates a struct node.
*
*   Input:
*   void
*
*   Output:
*   node - pointer to a struct node
*
*   last update: May 10, 2009
*------------------------------------------------------------
*/

bst_node* bst_node_alloc()
{
    bst_node *node = NULL;

    /* memory allocation for bst_node */
    node = (bst_node *) malloc(sizeof(bst_node));
    if ( node == NULL )
        return NULL;

    /* setting bst_node elements equal to NULL */
    node->v      = NULL;
    node->r_node = NULL;
    node->l_node = NULL;
    node->r_leaf = NULL;
    node->l_leaf = NULL;

    return node;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_leaf_free
*
*   This function frees the memory used by a struct leaf.
*
*   Input:
*   leaf - pointer to a struct leaf
*
*   Output:
*   void
*
*   last update: May 9, 2009
*------------------------------------------------------------
*/

void bst_leaf_free(void **leaf_bl)
{
    bst_leaf *leaf = NULL;

    /* checking if leaf_bl is NULL */
    if ( *leaf_bl == NULL )
        return;

    leaf = (bst_leaf *) (*leaf_bl);

    /* releasing bst_leaf elements */
    if( leaf->phi != NULL )
    {
        gsl_vector_free(leaf->phi);
        leaf->phi = NULL;
    }

    if( leaf->Rphi != NULL )
    {
        gsl_vector_free(leaf->Rphi);
        leaf->Rphi = NULL;
    }

    if( leaf->A != NULL )
    {
        gsl_matrix_free(leaf->A);
        leaf->A = NULL;
    }

    if( leaf->L != NULL )
    {
        gsl_matrix_free(leaf->L);
        leaf->L = NULL;
    }

    /* releasing allocated memory by bst_leaf */
    free(*leaf_bl);
    *leaf_bl = NULL;

    return;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_node_free
*
*   This function frees the memory used by a struct node.
*
*   Input:
*   node - pointer to a struct node
*
*   Output:
*   void
*
*   last update: Feb 19, 2010
*------------------------------------------------------------
*/

void bst_node_free(void **node_bl)
{
    bst_node *node = NULL;

    /* checking if node_bl is NULL */
    if ( *node_bl == NULL )
        return;

    node = (bst_node *) (*node_bl);

    /* releasing allocated memory by bst_node elements */
    if( node->l_leaf != NULL )
    {
        bst_leaf_free((void **)&(node->l_leaf));
        node->l_leaf = NULL;
    }

    if( node->r_leaf != NULL )
    {
        bst_leaf_free((void **)&(node->r_leaf));
        node->r_leaf = NULL;
    }

    if( node->l_node != NULL )
    {
        bst_node_free((void **)&(node->l_node));
        node->l_node = NULL;
    }

    if( node->r_node != NULL )
    {
        bst_node_free((void **)&(node->r_node));
        node->r_node = NULL;
    }

    if( node->v != NULL )
    {
        gsl_vector_free(node->v);
        node->v = NULL;
    }

    /* releasing allocated memory by bst_node */
    free(*node_bl);
    *node_bl = NULL;

    return;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_leaf_set
*
*   This function sets the bst_leaf elements equal to
*   the input elements and returns GSL_SUCCESS if
*   there is no problem during its execution.
*
*   Input:
*   phi  - composition
*   Rphi - reaction mapping
*   A    - mapping gradient matrix
*   L    - ellipsoid Cholesky matrix
*
*   Output:
*   leaf - pointer to a struct leaf
*   success or error
*
*   last update: Feb 22, 2009
*------------------------------------------------------------
*/

int bst_leaf_set(gsl_vector *phi,gsl_vector *Rphi,
                    gsl_matrix *A,gsl_matrix *L,bst_leaf *leaf)
{
    /* checking if leaf is NULL */
    if ( leaf == NULL )
        return GSL_EFAILED;

    /* setting phi equal to the input vector phi */
    if ( leaf->phi == NULL )
        leaf->phi = gsl_vector_calloc(phi->size);

    gsl_vector_memcpy(leaf->phi,phi);

    /* setting Rphi equal to the input vector Rphi */
    if ( leaf->Rphi == NULL )
        leaf->Rphi = gsl_vector_calloc(Rphi->size);

    gsl_vector_memcpy(leaf->Rphi,Rphi);

    /* setting A equal to the input matrix A */
    if ( leaf->A == NULL )
        leaf->A = gsl_matrix_calloc(A->size1,A->size2);

    gsl_matrix_memcpy(leaf->A,A);

    /* setting L equal to the input matrix L */
    if ( leaf->L == NULL )
        leaf->L = gsl_matrix_calloc(L->size1,L->size2);

    gsl_matrix_memcpy(leaf->L,L);

    return GSL_SUCCESS;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_cutplane
*
*   This function compute the vector ( v = phi_r - phi_l )
*   and the scalar ( a = (|phi_r|^2-|phi_l|^2)/2 )
*   which define a cutting plane used to search any
*   information in the binary search tree.
*
*   Input:
*   phi_l - left  composition
*   phi_r - right compositon
*
*   Output:
*   v    - cutting plane normal vector
*   a    - cutting plane scalar
*
*   last update: Feb 27, 2009
*------------------------------------------------------------
*/

double bst_cutplane(gsl_vector *phi_l,gsl_vector *phi_r,gsl_vector *v)
{
    double a1, a2;

    /* v := phi_r */
    gsl_vector_memcpy(v,phi_r);

    /* v := phi_r - phi_l */
    gsl_vector_sub(v,phi_l);

    /* a1 := |phi_r|^2 */
    gsl_blas_ddot(phi_r,phi_r,&a1);

    /* a2 := |phi_l|^2 */
    gsl_blas_ddot(phi_l,phi_l,&a2);

    return 0.5*(a1-a2);
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_node_set
*
*   This function set the bst_node elements equal to
*   the input elements and define the vector and
*   scalar to do the search for a information.
*
*   Input:
*   l_leaf - left  leaf
*   r_leaf - right leaf
*
*   Output:
*   node - pointer to a struct node
*   success or error
*
*   last update: Feb 27, 2009
*------------------------------------------------------------
*/

int bst_node_set(bst_leaf *l_leaf,bst_leaf *r_leaf,bst_node *node)
{
    /* checking if node is NULL */
    if ( node == NULL )
        return GSL_EFAILED;

    /* memory allocation for v */
    if ( node->v == NULL )
    	node->v = gsl_vector_calloc(r_leaf->phi->size);

    /* setting v and a */
    node->a = bst_cutplane(l_leaf->phi,r_leaf->phi,node->v);

    /* setting leaf elements equal to the input leaves */
    node->l_leaf = l_leaf;
    node->r_leaf = r_leaf;

    /* setting node elements equal to NULL */
    node->l_node = NULL;
    node->r_node = NULL;

    return GSL_SUCCESS;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_node_add
*
*   This function adds a new node to a given side
*   of a old node and returns GSL_SUCCESS if
*   there is no problem during its execution.
*
*   Input:
*   side     - new node side
*   old_node - pointer to the old node
*   new_node - pointer to the new node
*
*   Output:
*   success or error
*
*   last update: Feb 22, 2009
*------------------------------------------------------------
*/

int bst_node_add(int side,bst_node *old_node,bst_node *new_node)
{
    if( side == RIGHT )
    {
        if( old_node->r_node != NULL )
            return GSL_EFAILED;
        else
        {
            /* adding a new right node */
            old_node->r_node = new_node;
            old_node->r_leaf = NULL;

            return GSL_SUCCESS;
        }
    }
    else if( side == LEFT )
    {
        if( old_node->l_node != NULL )
            return GSL_EFAILED;
        else
        {
            /* adding a new left node */
            old_node->l_node = new_node;
            old_node->l_leaf = NULL;

            return GSL_SUCCESS;
        }
    }
    else
        return GSL_EFAILED;
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_search
*
*   This function searchs for a near composition phi0 in the
*   binary search tree.
*
*   Input:
*   root     - binary tree root
*   phi      - composition
*
*   Output:
*   end_leaf - leaf with the near composition
*   end_node - node with the near composition
*   side     - near compositon leaf side
*
*   last update: Feb 3, 2009
*------------------------------------------------------------
*/

int bst_search(bst_node *root,gsl_vector *phi,
                        bst_node **end_node,bst_leaf **end_leaf)
{
    double dot;

    if( root == NULL )
    {
        *end_leaf = NULL;
        *end_node = NULL;

        return GSL_EFAILED;
    }

    /* dot := v^T*phi */
    gsl_blas_ddot(root->v,phi,&dot);

    /* if dot > a then right node else left node */
    if( dot > root->a )
    {
        /* extern node */
        if( root->r_node == NULL )
        {
            *end_leaf = root->r_leaf;
            *end_node = root;

            return RIGHT;
        }
        else
            return bst_search(root->r_node,phi,end_node,end_leaf);
    }
    else
    {
        /* extern node */
        if( root->l_node == NULL )
        {
            *end_leaf = root->l_leaf;
            *end_node = root;

            return LEFT;
        }
        else
            return bst_search(root->l_node,phi,end_node,end_leaf);
    }
}
/*------------------------------------------------------------*/

/*
*------------------------------------------------------------
*   bst_height
*
*   This function computes the binary search tree height.
*
*   Input:
*   root - binary tree root
*
*   Output:
*   height - binary search tree height
*
*   last update: Nov 2, 2009
*------------------------------------------------------------
*/

int bst_height(bst_node *root)
{
    int l_tree_height = 0;
    int r_tree_height = 0;

    if ( root != NULL )
    {
        l_tree_height = bst_height(root->l_node);
        r_tree_height = bst_height(root->r_node);

        if ( l_tree_height > r_tree_height )
            return l_tree_height + 1;
        else
            return r_tree_height + 1;
    }
    else
        return 0;

}
/*------------------------------------------------------------*/


// Copyright (c) 2005 - 2010 Marc de Kamps
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//    * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//      If you use this software in work leading to a scientific publication, you should cite
//      the 'currently valid reference', which can be found at http://miind.sourceforge.net
#ifndef _CODE_LIBS_NUMTOOLSLIB_NODE_EXSTATEDVINTEGRATOR_INCLUDE_GUARD
#define _CODE_LIBS_NUMTOOLSLIB_NODE_EXSTATEDVINTEGRATOR_INCLUDE_GUARD

#include <limits>
#include <vector>
#include <gsl/gsl_odeiv.h>
#include <gsl/gsl_errno.h>
#include "AbstractDVIntegratorCode.h"
#include "BasicDefinitions.h"
#include "DVIntegratorException.h"
#include "DVIntegratorStateParameter.h"

using std::vector;
using std::istream;
using std::ostream;
using std::string;

using std::numeric_limits;

namespace NumtoolsLib
{

	//! This is a wrapper class for the GSL numerical ODE solvers. Examples of its usage can be
	//! found in DynamicLib, for example in the Wilson-Cowan Algorithm. Unlike DVIntegrator it operates on a
	//! state vector that is maintained by another class.
	//!
	//! The ExStateDVIntegrator is typically member of a class which requires the solution of a system
	//! of ODEs. In the source file of that class a function must be defined whose return type is int
	//! and whose arguments are given in the typedef for Function. A pointer to this function, (i.e the
	//! function name must be given in the constructor. If the GSL
	//! solver requires a Jacobian, then Derivative must also be defined, but for simple solvers,
	//! such as 4-th order Runge-Kutta this is not required and the derivative argument can be left out.
	//! Often, the ODE system requires parameters that need to be updated during the evolution of the system.
	//! This parameter can be a single number, a vector or anything else. The type of the parameter must
	//! be provided using the template argument. The class of the parameter must have a default constructor.
	template <class ParameterObject=double>
	class ExStateDVIntegrator : public AbstractDVIntegrator<ParameterObject>
	{
	public:

		//! Constructor
		ExStateDVIntegrator
		(
			Number,						//<! maximum number of integrations
			double*,					//<! initial state
			Number,						//<! state size
			TimeStep,					//<! initial time step
			Time,						//<! initial time
			const Precision&,			//<! absolute and relative precision
			Function,					//<! dydt
			Derivative deravative = 0,  //<! Jacobian, if available
			const gsl_odeiv_step_type*	p_step_algorithm = gsl_odeiv_step_rkf45 //<! gsl integrator object
		);

		//! copy constructor must be defined, because the state of the integrator
		//! must be handled correctly
		ExStateDVIntegrator(const ExStateDVIntegrator&);

		//! Ditto for copy operator
		ExStateDVIntegrator& operator=(const ExStateDVIntegrator&);

		//! virtual destructor
		virtual ~ExStateDVIntegrator();

		//! Set a new state
		bool Reconfigure
		(
			const DVIntegratorStateParameter<ParameterObject>&
		);

		//! Current time
		Time CurrentTime() const;

		//! Only use if for efficiency reasons, acces to internal state is necessary
		const double* BeginState() const;

		//! Ditto
		const double* EndState  () const;

		//! streaming tag
		virtual string Tag () const;

		//! Direct access to the parameter object for performance reasons
		ParameterObject& Parameter();

	private:

	}; // end of NodeIntegrator

} // end of namespace

#endif // include guard


#include <stdlib.h>
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <cblas.h>
#include "LCP_Solver.h"
#include "debug.h"

void numericsError(char * functionName, char* message)
{
  char output[200] = "Numerics error - ";
  strcat(output, functionName);
  strcat(output, message);
  strcat(output, ".\n");
  fprintf(stderr, "%s", output);
  exit(EXIT_FAILURE);
}

void prodNumericsMatrix(int sizeX, int sizeY, double alpha, const NumericsMatrix* const A, const double* const x, double beta, double* y)
{
  assert(A);
  assert(x);
  assert(y);
  assert(A->size0 == sizeY);
  assert(A->size1 == sizeX);
  cblas_dgemv(CblasColMajor, CblasNoTrans, sizeY, sizeX, alpha, A->matrix0, sizeY, x, 1, beta, y, 1);
}

void deleteSolverOptions(SolverOptions* op)
{
  if(op)
  {
    if (op->iparam != NULL)
      free(op->iparam);
    op->iparam = NULL;
    if (op->dparam != NULL)
      free(op->dparam);
    op->dparam = NULL;
  }
}

void lcp_lexicolemke(LinearComplementarityProblem* problem, double *zlem , double *wlem , int *info , SolverOptions* options)
{
  /* matrix M of the lcp */
  double * M = problem->M->matrix0;
  assert(M);
  /* size of the LCP */
  int dim = problem->size;
  assert(dim>0);
  int dim2 = 2 * (dim + 1);

  int i, drive, block, Ifound;
  int ic, jc;
  int ITER;
  int nobasis;
  int itermax = options->iparam[0];

  i=0;
  int n = problem->size;
  double *q = problem->q;

  while ((i < (n - 1)) && (q[i] >= 0.))
    i++;

  if ((i == (n - 1)) && (q[n - 1] >= 0.))
  {
    /* TRIVIAL CASE : q >= 0
     * z = 0 and w = q is solution of LCP(q,M)
     */
    for (int j = 0 ; j < n; j++)
    {
      zlem[j] = 0.0;
      wlem[j] = q[j];
    }
    *info = 0;
    options->iparam[1] = 0;   /* Number of iterations done */
    options->dparam[1] = 0.0; /* Error */
    if (options->verboseMode > 0)
      printf("lcp_lexicolemke: found trivial solution for the LCP (positive vector q => z = 0 and w = q). \n");
    return ;
  }

  double z0, zb, dblock;
  double pivot, tovip;
  double tmp;
  int *basis;
  double** A;

  /*output*/
  options->iparam[1] = 0;

  /* Allocation */
  basis = (int *)malloc(dim * sizeof(int));
  A = (double **)malloc(dim * sizeof(double*));

  for (ic = 0 ; ic < dim; ++ic)
    A[ic] = (double *)malloc(dim2 * sizeof(double));

  /* construction of A matrix such that
   * A = [ q | Id | -d | -M ] with d = (1,...1)
   */
  /* We need to init only the part corresponding to Id */
  for (ic = 0 ; ic < dim; ++ic)
    for (jc = 1 ; jc <= dim; ++jc)
      A[ic][jc] = 0.0;

  for (ic = 0 ; ic < dim; ++ic)
    for (jc = 0 ; jc < dim; ++jc)
      A[ic][jc + dim + 2] = -M[dim * jc + ic];

  assert(problem->q);

  for (ic = 0 ; ic < dim; ++ic) A[ic][0] = problem->q[ic];

  for (ic = 0 ; ic < dim; ++ic) A[ic][ic + 1 ] =  1.0;
  for (ic = 0 ; ic < dim; ++ic) A[ic][dim + 1] = -1.0;

  DEBUG_PRINT("total matrix\n");
  DEBUG_EXPR_WE(for (unsigned int i = 0; i < dim; ++i)
      { for(unsigned int j = 0 ; j < dim2; ++j)
      { DEBUG_PRINTF("%1.2e ", A[i][j]) }
      DEBUG_PRINT("\n")});
  /* End of construction of A */

  Ifound = 0;

  for (ic = 0 ; ic < dim  ; ++ic) basis[ic] = ic + 1;

  drive = dim + 1;
  block = 0;
  z0 = A[block][0];
  ITER = 0;

  /* Start research of argmin lexico */
  /* With this first step the covering vector enter in the basis */
  for (ic = 1 ; ic < dim ; ++ic)
  {
    zb = A[ic][0];
    if (zb < z0)
    {
      z0    = zb;
      block = ic;
    }
    else if (zb == z0)
    {
      for (jc = 0 ; jc < dim ; ++jc)
      {
        dblock = A[block][1 + jc] - A[ic][1 + jc];
        if (dblock < 0)
        {
          break;
        }
        else if (dblock > 0)
        {
          block = ic;
          break;
        }
      }
    }
  }

  /* Stop research of argmin lexico */
  DEBUG_PRINTF("Pivoting %i and %i\n", block, drive);

  pivot = A[block][drive];
  tovip = 1.0 / pivot;

  /* Pivot < block , drive > */
  A[block][drive] = 1;
  for (ic = 0       ; ic < drive ; ++ic) A[block][ic] = A[block][ic] * tovip;
  for (ic = drive + 1 ; ic < dim2  ; ++ic) A[block][ic] = A[block][ic] * tovip;

  /* */

  for (ic = 0 ; ic < block ; ++ic)
  {
    tmp = A[ic][drive];
    for (jc = 0 ; jc < dim2 ; ++jc) A[ic][jc] -=  tmp * A[block][jc];
  }
  for (ic = block + 1 ; ic < dim ; ++ic)
  {
    tmp = A[ic][drive];
    for (jc = 0 ; jc < dim2 ; ++jc) A[ic][jc] -=  tmp * A[block][jc];
  }

   nobasis = basis[block];
  basis[block] = drive;

  DEBUG_EXPR_WE( DEBUG_PRINT("new basis: ")
      for (unsigned int i = 0; i < dim; ++i)
      { DEBUG_PRINTF("%i ", basis[i])}
      DEBUG_PRINT("\n"));
  DEBUG_PRINT("total matrix\n");
  DEBUG_EXPR_WE(for (unsigned int i = 0; i < dim; ++i)
      { for(unsigned int j = 0 ; j < dim2; ++j)
      { DEBUG_PRINTF("%1.2e ", A[i][j]) }
      DEBUG_PRINT("\n")});

  while (ITER < itermax && !Ifound)
  {

    ++ITER;

    if (nobasis < dim + 1)      drive = nobasis + (dim + 1);
    else if (nobasis > dim + 1) drive = nobasis - (dim + 1);

    DEBUG_PRINTF("driving variable %i \n", drive);

    /* Start research of argmin lexico for minimum ratio test */
    pivot = 1e20;
    block = -1;

    for (ic = 0 ; ic < dim ; ++ic)
    {
      zb = A[ic][drive];
      if (zb > 0.0)
      {
        z0 = A[ic][0] / zb;
        if (z0 > pivot) continue;
        if (z0 < pivot)
        {
          pivot = z0;
          block = ic;
        }
        else
        {
          for (jc = 1 ; jc < dim + 1 ; ++jc)
          {
            assert(block >=0 && "lcp_lexicolemke: block <0");
            dblock = A[block][jc] / pivot - A[ic][jc] / zb;
            if (dblock < 0.0) break;
            else if (dblock > 0.0)
            {
              block = ic;
              break;
            }
          }
        }
      }
    }
    if (block == -1)
    {
      Ifound = 1;
      DEBUG_PRINT("The pivot column is nonpositive !\n"
          "It either means that the algorithm failed or that the LCP is infeasible\n"
          "Check the class of the M matrix to find out the meaning of this\n");
      break;
    }

    if (basis[block] == dim + 1) Ifound = 1;

    /* Pivot < block , drive > */
    pivot = A[block][drive];
    tovip = 1.0 / pivot;
    A[block][drive] = 1;

    for (ic = 0       ; ic < drive ; ++ic) A[block][ic] = A[block][ic] * tovip;
    for (ic = drive + 1 ; ic < dim2  ; ++ic) A[block][ic] = A[block][ic] * tovip;

    /* */

    for (ic = 0 ; ic < block ; ++ic)
    {
      tmp = A[ic][drive];
      for (jc = 0 ; jc < dim2 ; ++jc) A[ic][jc] -=  tmp * A[block][jc];
    }
    for (ic = block + 1 ; ic < dim ; ++ic)
    {
      tmp = A[ic][drive];
      for (jc = 0 ; jc < dim2 ; ++jc) A[ic][jc] -=  tmp * A[block][jc];
    }

    nobasis = basis[block];
    basis[block] = drive;

    DEBUG_EXPR_WE( DEBUG_PRINT("new basis: ")
      for (unsigned int i = 0; i < dim; ++i)
      { DEBUG_PRINTF("%i ", basis[i])}
      DEBUG_PRINT("\n"));

    DEBUG_PRINT("total matrix\n");
    DEBUG_EXPR_WE(for (unsigned int i = 0; i < dim; ++i)
      { for(unsigned int j = 0 ; j < dim2; ++j)
      { DEBUG_PRINTF("%1.2e ", A[i][j]) }
      DEBUG_PRINT("\n")});

  } /* end while*/

  DEBUG_EXPR_WE( DEBUG_PRINT("new basis: ")
      for (unsigned int i = 0; i < dim; ++i)
      { DEBUG_PRINTF("%i ", basis[i])}
      DEBUG_PRINT("\n"));

  DEBUG_PRINT("total matrix\n");
  DEBUG_EXPR_WE(for (unsigned int i = 0; i < dim; ++i)
      { for(unsigned int j = 0 ; j < dim2; ++j)
      { DEBUG_PRINTF("%1.2e ", A[i][j]) }
      DEBUG_PRINT("\n")});

  for (ic = 0 ; ic < dim; ++ic)
  {
    drive = basis[ic];
    if (drive < dim + 1)
    {
      zlem[drive - 1] = 0.0;
      wlem[drive - 1] = A[ic][0];
    }
    else if (drive > dim + 1)
    {
      zlem[drive - dim - 2] = A[ic][0];
      wlem[drive - dim - 2] = 0.0;
    }
  }

  options->iparam[1] = ITER;

  if (Ifound) *info = 0;
  else *info = 1;

  free(basis);

  for (i = 0 ; i < dim ; ++i) free(A[i]);
  free(A);
}

int linearComplementarity_driver(LinearComplementarityProblem* problem, double *z , double *w, SolverOptions* options)
{
  /********************
   * 0 - Check inputs *
   ********************/

  if (options == NULL)
    numericsError("lcp_driver", "null input for solver options");
  if (problem == NULL || z == NULL || w == NULL)
    numericsError("lcp_driver", "null input for LinearComplementarityProblem and/or unknowns (z,w)");

  int NoDefaultOptions = options->isSet; /* true(1) if the SolverOptions structure has been filled in else false(0) */

  if (NoDefaultOptions == 0)
  {
    numericsError("lcp_driver_DenseMatrix", "options for solver have not been set");
  }

  if (options->verboseMode > 0)
    printSolverOptions(options);

  /* Output info. : 0: ok -  >0: problem (depends on solver) */
  int info = -1;

  /******************************************
   *  1 - Check for trivial solution
   ******************************************/

  int i = 0;
  int n = problem->size;
  double *q = problem->q;
/*  if (!((options->solverId == SICONOS_LCP_ENUM) && (options->iparam[0] == 1 )))*/
    {
      while ((i < (n - 1)) && (q[i] >= 0.)) i++;
      if ((i == (n - 1)) && (q[n - 1] >= 0.))
      {
        /* TRIVIAL CASE : q >= 0
         * z = 0 and w = q is solution of LCP(q,M)
         */
        for (int j = 0 ; j < n; j++)
        {
          z[j] = 0.0;
          w[j] = q[j];
        }
        info = 0;
        options->dparam[1] = 0.0; /* Error */
        if (options->verboseMode > 0)
          printf("LCP_driver_DenseMatrix: found trivial solution for the LCP (positive vector q => z = 0 and w = q). \n");
        return info;
      }
    }

  /*************************************************
   *  2 - Call Lemke solver (if no trivial sol.)
   *************************************************/

  if (options->verboseMode == 1)
    printf(" ========================== Call Lemke solver for Linear Complementarity problem ==========================\n");

  /****** Lemke algorithm ******/
  /* IN: itermax
     OUT: iter */
   lcp_lexicolemke(problem, z , w , &info , options);

  /*************************************************
   *  3 - Computes w = Mz + q and checks validity
   *************************************************/
  if (options->filterOn > 0)
  {
    int info_ = lcp_compute_error(problem, z, w, options->dparam[0], &(options->dparam[1]),
				  options->verboseMode);
    if (info <= 0) /* info was not setor the solver was happy */
      info = info_;
  }

  return info;
}

void lcp_compute_error_only(unsigned int n, double *z , double *w, double * error)
{
  /* Checks complementarity */

  *error = 0.;
  double zi, wi;
  for (unsigned int i = 0 ; i < n ; i++)
  {
    zi = z[i];
    wi = w[i];
    if (zi < 0.0)
    {
      *error += -zi;
      if (wi < 0.0) *error += zi * wi;
    }
    if (wi < 0.0) *error += -wi;
    if ((zi > 0.0) && (wi > 0.0)) *error += zi * wi;
  }
}

int lcp_compute_error(LinearComplementarityProblem* problem, double *z , double *w, double tolerance,
		      double * error, int verbose)
{
  /* Checks inputs */
  if (problem == NULL || z == NULL || w == NULL)
    numericsError("lcp_compute_error", "null input for problem and/or z and/or w");

  /* Computes w = Mz + q */
  int incx = 1, incy = 1;
  unsigned int n = problem->size;
  cblas_dcopy(n , problem->q , incx , w , incy);  // w <-q
  prodNumericsMatrix(n, n, 1.0, problem->M, z, 1.0, w);
  double normq = cblas_dnrm2(n , problem->q , incx);
  lcp_compute_error_only(n, z, w, error);
  *error = *error / (normq + 1.0); /* Need some comments on why this is needed */
  if (*error > tolerance)
  {
    if (verbose > 0)
	printf(" Numerics - lcp_compute_error : error = %g > tolerance = %g.\n", *error, tolerance);
    return 1;
  }
  else
    return 0;
}

int linearComplementarity_lexicolemke_setDefaultSolverOptions(SolverOptions* options)
{
  /* if (options->verboseMode > 0) */
  /* { */
  /*   printf("Set the Default SolverOptions for the Lemke Solver\n"); */
  /* } */

  options->isSet = 1;
  options->filterOn = 1;
  options->iSize = 5;
  options->dSize = 5;
  options->iparam = (int *)calloc(options->iSize, sizeof(int));
  options->dparam = (double *)calloc(options->dSize, sizeof(double));
  options->verboseMode = 0;
  options->dparam[0] = 1e-6;
  options->iparam[0] = 10000;
  return 0;
}

void printSolverOptions(SolverOptions* options)
{
  printf("\n ========== Numerics Non Smooth Solver parameters: \n");
  if (options->isSet == 0)
    printf("The solver parameters have not been set. \t options->isSet = %i \n", options->isSet);
  else
  {
    printf("The solver parameters below have  been set \t options->isSet = %i\n", options->isSet);
    printf("Name of the solver\t\t\t\t Lemke \n");
    if (options->iparam != NULL)
    {
      printf("int parameters \t\t\t\t\t options->iparam\n");
      printf("size of the int parameters\t\t\t options->iSize = %i\n", options->iSize);
      for (int i = 0; i < options->iSize; ++i)
        printf("\t\t\t\t\t\t options->iparam[%i] = %d\n", i, options->iparam[i]);
    }
    if (options->dparam != NULL)
    {
      printf("double parameters \t\t\t\t options->dparam\n");
      printf("size of the double parameters\t\t\t options->dSize = %i\n", options->dSize);
      for (int i = 0; i < options->iSize; ++i)
        printf("\t\t\t\t\t\t options->dparam[%i] = %.6le\n", i, options->dparam[i]);
    }
  }

  printf("See Lemke documentation for parameters definition)\n");
  printf("\n");
}


// File: nlopt_wrapper.c
// Author: Jannis Harder
// Description: Wrapper for nlopt using context switching

#include <stdlib.h>
#include <ucontext.h>
#include <string.h>
#include <stdio.h> // For debugging TODO: remove
#include <nlopt.h>

#define STACKSIZE (8 * 1024 * 1024)

enum status {
	ST_IDLE = 0,
	ST_RUNNING,
	ST_VALUE,
	ST_GRAD,
	ST_DONE
};

struct function {
	struct wrapper * w;
	struct function * next;
	int id;
};

struct wrapper {
	struct function f;
	nlopt_opt opt;
	int n;
	ucontext_t julia_ctx;
	ucontext_t nlopt_ctx;
	char *nlopt_stack;
	double final_f;
	double *opt_x;
	double *eval_x;
	double *eval_grad;
	double eval_f;
	int force_stop;
	int result;
	int function_id;
	enum status status;
};

double nlopt_wrapper_f(unsigned n, const double *x, double *grad, void *f_data);
void nlopt_wrapper_optimize_thread(struct wrapper* w);

void nlopt_wrapper_version(int *version)
{
	nlopt_version(&version[0], &version[1], &version[2]);
	version[3] = 2;
	version[4] = 2;
	version[5] = 4;
	version[6] = 0;
}

struct wrapper *nlopt_wrapper_create(int type_id, int dimensions)
{
	nlopt_opt opt = nlopt_create(type_id, dimensions);
	if (!opt)
		return NULL;
	struct wrapper *w = calloc(1, sizeof(struct wrapper));
	w->n = dimensions;
	w->opt = opt;
	w->f.w = w;
	w->f.id = 1;
	return w;
}

void nlopt_wrapper_free(struct wrapper *w)
{
	nlopt_destroy(w->opt);
	free(w->opt_x);
	struct function *f = &w->f;
	while (f) {
		struct function *next = f->next;
		free(f);
		f = next;
	}
}

int nlopt_wrapper_objective(struct wrapper *w, int max)
{
	if (max)
		return nlopt_set_max_objective(w->opt, &nlopt_wrapper_f, &w->f);
	else
		return nlopt_set_min_objective(w->opt, &nlopt_wrapper_f, &w->f);
}

double nlopt_wrapper_f(unsigned n, const double *x, double *grad, void *f_data)
{
	struct function *f = f_data;
	struct wrapper *w = f->w;

	w->function_id = f->id;

	w->status = grad ? ST_GRAD : ST_VALUE;
	memcpy(w->eval_x, x, n * sizeof(double));
	swapcontext(&w->nlopt_ctx, &w->julia_ctx);
	if (w->force_stop)
		nlopt_force_stop(w->opt);
	if (grad)
		memcpy(grad, w->eval_grad, n * sizeof(double));
	return w->eval_f;
}

void nlopt_wrapper_optimize_start(struct wrapper *w, double *x)
{
	int i;
	getcontext(&w->nlopt_ctx);
	w->nlopt_stack = calloc(1, STACKSIZE);
	w->nlopt_ctx.uc_stack.ss_sp = w->nlopt_stack;
	w->nlopt_ctx.uc_stack.ss_size = STACKSIZE;
	w->nlopt_ctx.uc_link = &w->julia_ctx;
	makecontext(&w->nlopt_ctx, (void(*)())&nlopt_wrapper_optimize_thread, 1, w);

	w->opt_x = calloc(w->n, sizeof(double));
	memcpy(w->opt_x, x, w->n * sizeof(double));
}

int nlopt_wrapper_optimize_callback(struct wrapper *w, double *x, double *grad, double f, int force_stop, int *function_id)
{
	w->eval_f = f;
	w->eval_x = x;
	w->eval_grad = grad;
	w->force_stop = force_stop;
	swapcontext(&w->julia_ctx, &w->nlopt_ctx);
	*function_id = w->function_id;
	return w->status;
}

int nlopt_wrapper_optimize_finalize(struct wrapper *w, double *x, double *f)
{
	memcpy(x, w->opt_x, w->n * sizeof(double));
	free(w->opt_x);
	w->opt_x = NULL;
	*f = w->final_f;
	free(w->nlopt_stack);
	w->nlopt_stack = NULL;
	return w->result;
}

void nlopt_wrapper_optimize_thread(struct wrapper *w)
{
	w->result = nlopt_optimize(w->opt, w->opt_x, &w->final_f);
	w->status = ST_DONE;
}

void nlopt_wrapper_dimopt(struct wrapper *w, double *x, int i)
{
	switch (i) {
	case 0: nlopt_set_lower_bounds(w->opt, x); break;
	case 1: nlopt_set_upper_bounds(w->opt, x); break;
	case 2: nlopt_set_xtol_abs(w->opt, x); break;
	}
}

void nlopt_wrapper_doubleopt(struct wrapper *w, double v, int i)
{
	switch (i) {
	case 0: nlopt_set_stopval(w->opt, v); break;
	case 1: nlopt_set_ftol_rel(w->opt, v); break;
	case 2: nlopt_set_ftol_abs(w->opt, v); break;
	case 3: nlopt_set_xtol_rel(w->opt, v); break;
	case 4: nlopt_set_maxtime(w->opt, v); break;
	}
}

void nlopt_wrapper_intopt(struct wrapper *w, long int v, int i)
{
	switch (i) {
	case 0: nlopt_set_maxeval(w->opt, v); break;
	case 1: nlopt_set_population(w->opt, v < 0 ? 0 : v); break;
	case 2: nlopt_srand(v); break;
	}
}

void nlopt_wrapper_add_constraint(struct wrapper *w, int id, double tolerance, int equality)
{
	struct function *f = calloc(1, sizeof(struct function));

	f->w = w;
	f->next = w->f.next;
	f->id = id;
	w->f.next = f;
	if (equality)
		nlopt_add_equality_constraint(w->opt, &nlopt_wrapper_f, f, tolerance);
	else
		nlopt_add_inequality_constraint(w->opt, &nlopt_wrapper_f, f, tolerance);
}

void nlopt_wrapper_local_optimizer(struct wrapper *w, struct wrapper *local_w)
{
	nlopt_set_local_optimizer(w->opt, local_w->opt);
}


#ifndef SAMPLER_H
#define SAMPLER_H
#include <gsl/gsl_rng.h>
#include <stdlib.h>

typedef struct sampler {
  gsl_rng *internal_rng_state;
  unsigned long int seed;
  double (*generate)(void *samplerp);
} Sampler;

Sampler *new_sampler(unsigned long int seed);
void free_sampler(Sampler *p);
double generate_method(void *samplerp);

#endif


#ifndef OPENMC_MATERIAL_H
#define OPENMC_MATERIAL_H

#include <memory> // for unique_ptr
#include <string>
#include <unordered_map>
#include <vector>

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

#include "openmc/constants.h"
#include "openmc/bremsstrahlung.h"
#include "openmc/particle.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

class Material;

namespace model {

extern std::unordered_map<int32_t, int32_t> material_map;
extern std::vector<std::unique_ptr<Material>> materials;

} // namespace model

//==============================================================================
//! A substance with constituent nuclides and thermal scattering data
//==============================================================================

class Material
{
public:
  //----------------------------------------------------------------------------
  // Types
  struct ThermalTable {
    int index_table; //!< Index of table in data::thermal_scatt
    int index_nuclide; //!< Index in nuclide_
    double fraction; //!< How often to use table
  };

  //----------------------------------------------------------------------------
  // Constructors, destructors, factory functions
  Material() {};
  explicit Material(pugi::xml_node material_node);
  ~Material();

  //----------------------------------------------------------------------------
  // Methods

  void calculate_xs(Particle& p) const;

  //! Assign thermal scattering tables to specific nuclides within the material
  //! so the code knows when to apply bound thermal scattering data
  void init_thermal();

  //! Set up mapping between global nuclides vector and indices in nuclide_
  void init_nuclide_index();

  //! Finalize the material, assigning tables, normalize density, etc.
  void finalize();

  //! Write material data to HDF5
  void to_hdf5(hid_t group) const;

  //! Add nuclide to the material
  //
  //! \param[in] nuclide Name of the nuclide
  //! \param[in] density Density of the nuclide in [atom/b-cm]
  void add_nuclide(const std::string& nuclide, double density);

  //! Set atom densities for the material
  //
  //! \param[in] name Name of each nuclide
  //! \param[in] density Density of each nuclide in [atom/b-cm]
  void set_densities(const std::vector<std::string>& name,
    const std::vector<double>& density);

  //----------------------------------------------------------------------------
  // Accessors

  //! Get density in [atom/b-cm]
  //! \return Density in [atom/b-cm]
  double density() const { return density_; }

  //! Get density in [g/cm^3]
  //! \return Density in [g/cm^3]
  double density_gpcc() const { return density_gpcc_; }

  //! Get name
  //! \return Material name
  const std::string& name() const { return name_; }

  //! Set name
  void set_name(const std::string& name) { name_ = name; }

  //! Set total density of the material
  //
  //! \param[in] density Density value
  //! \param[in] units Units of density
  void set_density(double density, gsl::cstring_span units);

  //! Get nuclides in material
  //! \return Indices into the global nuclides vector
  gsl::span<const int> nuclides() const { return {nuclide_.data(), nuclide_.size()}; }

  //! Get densities of each nuclide in material
  //! \return Densities in [atom/b-cm]
  gsl::span<const double> densities() const { return {atom_density_.data(), atom_density_.size()}; }

  //! Get ID of material
  //! \return ID of material
  int32_t id() const { return id_; }

  //! Assign a unique ID to the material
  //! \param[in] Unique ID to assign. A value of -1 indicates that an ID
  //!   should be automatically assigned.
  void set_id(int32_t id);

  //! Get whether material is fissionable
  //! \return Whether material is fissionable
  bool fissionable() const { return fissionable_; }

  //! Get volume of material
  //! \return Volume in [cm^3]
  double volume() const;

  //! Get temperature of material
  //! \return Temperature in [K]
  double temperature() const;

  //----------------------------------------------------------------------------
  // Data
  int32_t id_ {C_NONE}; //!< Unique ID
  std::string name_; //!< Name of material
  std::vector<int> nuclide_; //!< Indices in nuclides vector
  std::vector<int> element_; //!< Indices in elements vector
  xt::xtensor<double, 1> atom_density_; //!< Nuclide atom density in [atom/b-cm]
  double density_; //!< Total atom density in [atom/b-cm]
  double density_gpcc_; //!< Total atom density in [g/cm^3]
  double volume_ {-1.0}; //!< Volume in [cm^3]
  bool fissionable_ {false}; //!< Does this material contain fissionable nuclides
  bool depletable_ {false}; //!< Is the material depletable?
  std::vector<bool> p0_; //!< Indicate which nuclides are to be treated with iso-in-lab scattering

  // To improve performance of tallying, we store an array (direct address
  // table) that indicates for each nuclide in data::nuclides the index of the
  // corresponding nuclide in the nuclide_ vector. If it is not present in the
  // material, the entry is set to -1.
  std::vector<int> mat_nuclide_index_;

  // Thermal scattering tables
  std::vector<ThermalTable> thermal_tables_;

  std::unique_ptr<Bremsstrahlung> ttb_;

private:
  //----------------------------------------------------------------------------
  // Private methods

  //! Calculate the collision stopping power
  void collision_stopping_power(double* s_col, bool positron);

  //! Initialize bremsstrahlung data
  void init_bremsstrahlung();

  //! Normalize density
  void normalize_density();

  void calculate_neutron_xs(Particle& p) const;
  void calculate_photon_xs(Particle& p) const;

  //----------------------------------------------------------------------------
  // Private data members
  gsl::index index_;

  //! \brief Default temperature for cells containing this material.
  //!
  //! A negative value indicates no default temperature was specified.
  double temperature_ {-1};
};

//==============================================================================
// Non-member functions
//==============================================================================

//! Calculate Sternheimer adjustment factor
double sternheimer_adjustment(const std::vector<double>& f, const
  std::vector<double>& e_b_sq, double e_p_sq, double n_conduction, double
  log_I, double tol, int max_iter);

//! Calculate density effect correction
double density_effect(const std::vector<double>& f, const std::vector<double>&
  e_b_sq, double e_p_sq, double n_conduction, double rho, double E, double tol,
  int max_iter);

//! Read material data from materials.xml
void read_materials_xml();

void free_memory_material();

} // namespace openmc
#endif // OPENMC_MATERIAL_H


/*
 * Copyright (c) 2016-2021 lymastee, All rights reserved.
 * Contact: lymastee@hotmail.com
 *
 * This file is part of the gslib project.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#pragma once

#ifndef painterpath_d2d84280_c369_48f2_99f8_28652ad13baa_h
#define painterpath_d2d84280_c369_48f2_99f8_28652ad13baa_h

#include <ariel/config.h>
#include <gslib/std.h>

__ariel_begin__

class painter_path;
typedef list<painter_path> painter_paths;

class ariel_export painter_linestrip
{
public:
    typedef vector<vec2> points;
    typedef points::iterator ptiter;
    typedef points::const_iterator ptciter;

protected:
    bool                _closed;
    points              _pts;

public:
    painter_linestrip();
    ~painter_linestrip() {}
    int get_size() const { return (int)_pts.size(); }
    void get_bound_rect(rectf& rc) const;
    vec2& get_point(int i) { return _pts.at(i); }
    const vec2& get_point(int i) const { return _pts.at(i); }
    vec2& get_last_point() { return _pts.back(); }
    const vec2& get_last_point() const { return _pts.back(); }
    void add_point(const vec2& pt) { _pts.push_back(pt); }
    void set_point(int i, const vec2& pt) { _pts.at(i) = pt; }
    void reserve(int s) { _pts.reserve(s); }
    void clear() { _pts.clear(); }
    void swap(painter_linestrip& another);
    void finish();
    void transform(const mat3& m);
    vec2* expand(int size);
    void expand_to(int size) { _pts.resize(size); }
    void reverse();
    void offset(const painter_linestrip& org, float off);
    int point_inside(const vec2& pt) const;
    bool is_closed() const { return _closed; }
    void set_closed(bool c) { _closed = c; }
    bool is_clockwise() const;
    bool is_convex() const;
    bool is_convex(int i) const;
    void tracing() const;
    void trace_segments() const;
    void trace_mel(float z) const;

protected:
    enum
    {
        st_clockwise_mask = 1,
        st_convex_mask = 2,
    };
    mutable uint        _tst_table;
    mutable bool        _is_clock_wise;
    mutable bool        _is_convex;

protected:
    bool is_clockwise_inited() const { return (_tst_table & st_clockwise_mask) != 0; }
    void set_clockwise_inited() const { _tst_table |= st_clockwise_mask; }
    bool is_convex_inited() const { return (_tst_table & st_convex_mask) != 0; }
    void set_convex_inited() const { _tst_table |= st_convex_mask; }
};

typedef list<painter_linestrip> linestrips;
typedef vector<painter_linestrip*> linestripvec;
typedef linestrips painter_linestrips;

/* create a random access view for linestrips */
ariel_export extern void append_linestrips_rav(linestripvec& rav, linestrips& src);
ariel_export extern void create_linestrips_rav(linestripvec& rav, linestrips& src);

class ariel_export painter_path
{
public:
    enum tag
    {
        pt_moveto,
        pt_lineto,
        pt_quadto,
        pt_cubicto,
    };

    class __gs_novtable ariel_export node abstract
    {
    public:
        virtual ~node() {}
        virtual tag get_tag() const = 0;
        virtual const vec2& get_point() const = 0;
        virtual void set_point(const vec2&) = 0;
        virtual void interpolate(painter_linestrip& c, const node* last, float step_len) const = 0;

    public:
        template<class _c>
        _c* as_node() { return static_cast<_c*>(this); }
        template<class _c>
        const _c* as_const_node() const { return static_cast<const _c*>(this); }
    };

    template<tag _tag>
    class node_tpl:
        public node
    {
    public:
        node_tpl() {}
        node_tpl(float x, float y): _pt(x, y) {}
        node_tpl(const vec2& pt): _pt(pt) {}

    public:
        tag get_tag() const override { return _tag; }
        const vec2& get_point() const override { return _pt; }
        void set_point(const vec2& pt) override { _pt = pt; }
        void interpolate(painter_linestrip& c, const node*, float) const override { c.add_point(_pt); }

    protected:
        vec2            _pt;
    };

    typedef node_tpl<pt_moveto> move_to_node;
    typedef node_tpl<pt_lineto> line_to_node;

    class ariel_export quad_to_node:
        public node_tpl<pt_quadto>
    {
    public:
        quad_to_node() {}
        quad_to_node(const vec2& p1, const vec2& p2): node_tpl(p2) { _c = p1; }
        void set_control(const vec2& c) { _c = c; }
        const vec2& get_control() const { return _c; }
        void interpolate(painter_linestrip& c, const node* last, float step_len) const override;

    protected:
        vec2            _c;
    };

    class ariel_export cubic_to_node:
        public node_tpl<pt_cubicto>
    {
    public:
        cubic_to_node() {}
        cubic_to_node(const vec2& p1, const vec2& p2, const vec2 p3): node_tpl(p3) { _c[0] = p1, _c[1] = p2; }
        void set_control1(const vec2& c) { _c[0] = c; }
        void set_control2(const vec2& c) { _c[1] = c; }
        const vec2& get_control1() const { return _c[0]; }
        const vec2& get_control2() const { return _c[1]; }
        void interpolate(painter_linestrip& c, const node* last, float step_len) const override;

    protected:
        vec2            _c[2];
    };

    typedef vector<node*> node_list;
    typedef node_list::iterator iterator;
    typedef node_list::const_iterator const_iterator;
    typedef vector<int> indices;

protected:
    node_list           _nodelist;

public:
    painter_path() {}
    painter_path(const painter_path& path) { duplicate(path); }
    ~painter_path() { destroy(); }
    bool empty() const { return _nodelist.empty(); }
    int size() const { return (int)_nodelist.size(); }
    void resize(int len);
    void destroy();
    void duplicate(const painter_path& path);
    void add_path(const painter_path& path);
    void add_rect(const rectf& rc);
    void swap(painter_path& path);
    iterator begin() { return _nodelist.begin(); }
    iterator end() { return _nodelist.end(); }
    const_iterator begin() const { return _nodelist.begin(); }
    const_iterator end() const { return _nodelist.end(); }
    node* get_node(int i) { return _nodelist.at(i); }
    const node* get_node(int i) const { return _nodelist.at(i); }
    void close_path();
    void close_sub_path();
    void get_boundary_box(rectf& rc) const;
    void move_to(float x, float y) { move_to(vec2(x, y)); }
    void line_to(float x, float y) { line_to(vec2(x, y)); }
    void arc_to(float x, float y, float r) { arc_to(vec2(x, y), r); }
    void rarc_to(float x, float y, float r) { rarc_to(vec2(x, y), r); }
    void quad_to(float x1, float y1, float x2, float y2) { quad_to(vec2(x1, y1), vec2(x2, y2)); }
    void cubic_to(float x1, float y1, float x2, float y2, float x3, float y3) { cubic_to(vec2(x1, y1), vec2(x2, y2), vec2(x3, y3)); }
    void move_to(const vec2& pt) { _nodelist.push_back(new move_to_node(pt)); }
    void line_to(const vec2& pt) { _nodelist.push_back(new line_to_node(pt)); }
    void quad_to(const vec2& p1, const vec2& p2) { _nodelist.push_back(new quad_to_node(p1, p2)); }
    void cubic_to(const vec2& p1, const vec2& p2, const vec2& p3) { _nodelist.push_back(new cubic_to_node(p1, p2, p3)); }
    void arc_to(const vec2& p1, const vec2& p2, float r);
    void arc_to(const vec2& pt, float r);
    void rarc_to(const vec2& pt, float r);
    void transform(const mat3& m);
    void get_linestrips(linestrips& c, float step_len = -1.f) const;
    int get_control_contour(painter_linestrip& ls, int start) const;
    int get_sub_path(painter_path& sp, int start) const;
    void to_sub_paths(painter_paths& paths) const;
    bool is_clockwise() const;
    bool is_convex() const;
    void simplify(painter_path& path) const;
    void reverse();
    void tracing() const;
    void tracing_segments() const;
};

typedef painter_path::node painter_node;

struct ariel_export path_info
{
    const painter_node*     node[2];

    path_info() { node[0] = node[1] = 0; }
    path_info(const painter_node* n1, const painter_node* n2) { node[0] = n1, node[1] = n2; }
    int get_order() const;
    int get_point_count() const;
    bool get_points(vec2 pt[], int cnt) const;
    void tracing() const;
};

enum curve_type
{
    ct_quad,
    ct_cubic,
};

struct __gs_novtable ariel_export curve_splitter abstract
{
    vec2                fixedpt;
    float               ratio;
    curve_splitter*     child[2];
    curve_splitter*     parent;

public:
    curve_splitter();
    virtual ~curve_splitter();
    virtual curve_type get_type() const = 0;
    virtual int get_point_count() const = 0;
    virtual bool get_points(vec2 p[], int count) const = 0;
    virtual void split(float t) = 0;
    virtual void interpolate(vec2& p, float t) const = 0;
    virtual float reparameterize(const vec2& p) const = 0;
    virtual void tracing() const = 0;
    bool is_leaf() const;
};

struct ariel_export curve_splitter_quad:
    public curve_splitter
{
    vec2                cp[3];
    vec3                para[2];

public:
    curve_splitter_quad(const vec2 p[3]);
    curve_type get_type() const override { return ct_quad; }
    int get_point_count() const override { return 3; }
    bool get_points(vec2 p[], int count) const override;
    void split(float t) override;
    void interpolate(vec2& p, float t) const override;
    float reparameterize(const vec2& p) const override;
    void tracing() const override;
};

struct ariel_export curve_splitter_cubic:
    public curve_splitter
{
    vec2                cp[4];
    vec4                para[2];

public:
    curve_splitter_cubic(const vec2 p[4]);
    curve_type get_type() const override { return ct_cubic; }
    int get_point_count() const override { return 4; }
    bool get_points(vec2 p[], int count) const override;
    void split(float t) override;
    void interpolate(vec2& p, float t) const override;
    float reparameterize(const vec2& p) const override;
    void tracing() const override;
};

struct ariel_export curve_helper
{
    static curve_splitter* create_splitter(const path_info* pnf);
    static curve_splitter* create_next_splitter(vec2& p, curve_splitter* cs, float t);
    static curve_splitter* query_splitter(curve_splitter* cs, float t);
    static curve_splitter* query_splitter(curve_splitter* cs, const vec2& p);
    static curve_splitter* query_splitter(curve_splitter* cs, const vec2& p1, const vec2& p2);
};

struct ariel_export painter_helper
{
    enum
    {
        merge_straight_line = 0x01,
        fix_loop = 0x02,
        fix_inflection = 0x04,
        reduce_straight_curve = 0x08,
        reduce_short_line = 0x10,
    };

    static void transform(painter_path& output, const painter_path& path, uint mask);
    static void close_sub_paths(painter_path& output, const painter_path& path);
};

__ariel_end__

#endif