/* ISO C99 introduced support for complex numbers. This
   requires complex.h to be included. The value of i 
   (sqrt of -1) may be obtained as either _Complex_I or I 
   from complex.h 
*/

#include <stdio.h>
#include <complex.h>

/* Function prototypes to the C wrapper routines for
   accessing both the new hybrid and Kahan methods
*/

  float c_snrm2(int n, int incx, float x[]);
  double c_dnrm2(int n, int incx, double x[]);
  float c_scnrm2(int n, int incx, float complex x[]);
  double c_dznrm2(int n, int incx, double complex x[]);

  float c_snrm2Kahan(int n, int incx, float x[]);
  double c_dnrm2Kahan(int n, int incx, double x[]);
  float c_scnrm2Kahan(int n, int incx, float complex x[]);
  double c_dznrm2Kahan(int n, int incx, double complex x[]);

/* This short test program checks that the C interface
   routines work correctly. All four routines, snrm2,
   scnrm2, dnrm2 and dznrm2 are called and the result
   checked. An example with incx=2 is also run for snrm2
   and dnrm2.

   Results that don't agree with the expected are reported.
   A simple "All tests passed" message is output if not
   errors are detected.
*/

int main()
{
  float xf[2], xf2[4], fnorm, fcnorm, fTrueNorm;
  float complex xfc[2];
  double xd[2], xd2[4], dnorm, dcnorm, dTrueNorm;
  double complex xdc[2];
  int n, incx, failed;

  failed = 0;
  n = 2;
  incx = 1;
  xf[0] = (float)(5.0);
  xf[1] = (float)(12.0);
  fnorm = c_snrm2(n, incx, xf);
  fTrueNorm = (float)(13.0);
  
  if (fnorm != fTrueNorm) {
     failed++;
     printf("Hybrid Test 1 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via snrm2 using hybrid code: %f\n", fnorm);
  }

  fnorm = c_snrm2Kahan(n, incx, xf);
  
  if (fnorm != fTrueNorm) {
     failed++;
     printf("Kahan Test 1 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via snrm2 using Kahan code: %f\n", fnorm);
  }

  n = 2;
  incx = 1;
  xd[0] = (double)(5.0);
  xd[1] = (double)(12.0);
  dnorm = c_dnrm2(n, incx, xd);
  dTrueNorm = (double)(13.0);
  
  if (dnorm != dTrueNorm) {
     failed++;
     printf("Hybrid Test 2 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via snrm2 using hybrid code: %f\n", dnorm);
  }

  dnorm = c_dnrm2Kahan(n, incx, xd);
  
  if (dnorm != dTrueNorm) {
     failed++;
     printf("Kahan Test 2 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via snrm2 using Kahan code: %f\n", dnorm);
  }

  n = 2;
  incx = 1;
  xfc[0] = (float)(1.0) + I*(float)(-1.0);
  xfc[1] = (float)(3.0) + I*(float)(5.0);
  fcnorm = c_scnrm2Kahan(n, incx, xfc);
  fTrueNorm = (float)(6.0);
  
  if (fcnorm != fTrueNorm) {
     failed++;
     printf("Hybrid Test 3 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via scnrm2 using hybrid code: %f\n", fcnorm);
  }

  fcnorm = c_scnrm2Kahan(n, incx, xfc);
  
  if (fcnorm != fTrueNorm) {
     failed++;
     printf("Kahan Test 3 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via scnrm2 using Kahan code: %f\n", fcnorm);
  }

  n = 2;
  incx = 1;
  xdc[0] = (double)(1.0) + I*(double)(-1.0);
  xdc[1] = (double)(3.0) + I*(double)(5.0);
  dcnorm = c_dznrm2Kahan(n, incx, xdc);
  dTrueNorm = (double)(6.0);
  
  if (dcnorm != dTrueNorm) {
     failed++;
     printf("Hybrid Test 4 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via dznrm2 using hybrid code: %f\n", dcnorm);
  }

  dcnorm = c_dznrm2Kahan(n, incx, xdc);
  
  if (dcnorm != dTrueNorm) {
     failed++;
     printf("Kahan Test 4 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via dznrm2 using Kahan code: %f\n", dcnorm);
  }

  n = 2;
  incx = 2;
  xf2[0] = (float)(5.0);
  xf2[1] = (float)(0.0);
  xf2[2] = (float)(12.0);
  xf2[3] = (float)(0.0);
  fnorm = c_snrm2(n, incx, xf2);
  fTrueNorm = (float)(13.0);
  
  if (fnorm != fTrueNorm) {
     failed++;
     printf("Hybrid Test 5 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via snrm2 using hybrid code: %f\n", fnorm);
  }

  fnorm = c_snrm2Kahan(n, incx, xf2);
  
  if (fnorm != fTrueNorm) {
     failed++;
     printf("Kahan Test 5 Failed: ");
     printf("Expected result: %f\n", fTrueNorm);
     printf("Computed norm via snrm2 using Kahan code: %f\n", fnorm);
  }

  n = 2;
  incx = 2;
  xd2[0] = (double)(5.0);
  xd2[1] = (double)(0.0);
  xd2[2] = (double)(12.0);
  xd2[3] = (double)(0.0);
  dnorm = c_dnrm2(n, incx, xd2);
  dTrueNorm = (double)(13.0);
  
  if (dnorm != dTrueNorm) {
     failed++;
     printf("Hybrid Test 6 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via snrm2 using hybrid code: %f\n", dnorm);
  }

  dnorm = c_dnrm2Kahan(n, incx, xd2);
  
  if (dnorm != dTrueNorm) {
     failed++;
     printf("Kahan Test 6 Failed: ");
     printf("Expected result: %f\n", dTrueNorm);
     printf("Computed norm via snrm2 using Kahan code: %f\n", dnorm);
  }

  if (failed ==0) {
    printf("All tests passed\n");
    return(0);
  }
  else {
    return(1);
  }

}
