
/*
 * --- GSMP-COPYRIGHT-NOTE-BEGIN ---
 * 
 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
 * Please add additional copyright information _after_ the line containing
 * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
 * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
 * 
 * GSMP: pcm/tests/Verify.cc
 * General Sound Manipulation Program is Copyright (C) 2000 - 2004
 *   Valentin Ziegler and René Rebe
 * 
 * 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; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * --- GSMP-COPYRIGHT-NOTE-END ---
 */

#include <iostream>
#include <iomanip>
#include "Types.hh"

#include <limits.h>

using namespace std;
using namespace GSMP;

// the global error counter
int error_count;

// a class, since template function can not be specialized ... :-(

template <typename T>
class verify_text
{
 public:
  static void ok (const T& t_v2) {
    std::cout << " ok. (" << std::fixed << t_v2 << ")" << std::endl;
  }
  
  static void fail (const T& t_v2, const T& v2)
  {
    std::cout << " failed!"
	      << " was: " << std::fixed << t_v2
	      << " should be: " << std::fixed << v2 << std::endl; 
  }
};

// a int8_t specialization due to the ostream char output with real
// characters instead numbers ...

template <> class verify_text<int8_t>
{
 public:
  static void ok (const int8_t& t_v2) {
    std::cout << " ok. (" << std::fixed << (int)t_v2 << ")" << std::endl;
  }
  
  static void fail (const int8_t& t_v2, const int8_t& v2)
  {
    std::cout << " failed!"
	      << " was: " << std::fixed << (int)t_v2
	      << " should be: " << std::fixed << (int)v2 << std::endl; 
  }
};


template <typename T1, typename E1, typename T2, typename E2>
void verify (const std::string& info, T1 v1, T2 v2)
{
  T2 t_v2 = PcmConvert<T1, T2, E1, E2>::Convert (v1);
  
  std::cout << std::left << std::setw (26) << info
	    << std::hex;
  
  bool is_ok;
  if (PcmTraits<T2>::IsInteger)
    is_ok = t_v2 == v2 || t_v2 == v2 - 1 || t_v2 == v2 + 1;
  else
    is_ok = t_v2 == v2;
  
  if (!is_ok) {
    verify_text<T2>::fail (t_v2, v2);
    ++error_count;
  }
  else
    verify_text<T2>::ok (t_v2);
  
  cout << std::dec;
}

int main()
{
  error_count = 0;
  
  // int8 ->
  
  verify<int8_t, HostEndianessTraits,
    int8_t, HostEndianessTraits>("int8 -> int8", 120, 120);

  verify<int8_t, HostEndianessTraits,
	 int8_t, HostEndianessTraits>("int8 -> int8 (neg)", -120, -120);

  verify<int8_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int8 -> int16", 120, 120 * 0x100);

  verify<int8_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int8 -> int16 (neg)", -120, -120 * 0x100);
  
  verify<int8_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int8 -> int32", 120, 120 * 0x10000);

  verify<int8_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int8 -> int32 (neg)", -120, -120 * 0x10000);

  verify<int8_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int8 -> int64", 120,
				       120L * 0x10000000000LL);
  
  verify<int8_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int8 -> int64 (neg)", -120,
				       (int64_t) -120 * 0x10000000000LL);

  verify<int8_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int8 -> double", 120,
				      (double) 120 / 0x7f);

  verify<int8_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int8 -> double (neg)", -120,
				      (double) -120 / 0x7f);

  // int16 ->
  
  verify<int16_t, HostEndianessTraits,
         int8_t, HostEndianessTraits>("int16 -> int8", 1200, 1200 / 0x100);

  verify<int16_t, HostEndianessTraits,
	 int8_t, HostEndianessTraits>("int16 -> int8 (neg)", -1200, -1200 / 0x100);

  verify<int16_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int16 -> int16", 1200, 1200);

  verify<int16_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int16 -> int16 (neg)", -1200, -1200);
  
  verify<int16_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int16 -> int32", 1200, 1200 * 0x100);

  verify<int16_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int16 -> int32 (neg)", -1200, -1200 * 0x100);

  verify<int16_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int16 -> int64", 1200,
				       (int64_t) 1200 * 0x100000000LL);

  verify<int16_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int16 -> int64 (neg)", -1200,
				       (int64_t) -1200 * 0x100000000LL);

  verify<int16_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int16 -> double", 1200,
				      (double) 1200 / 0x7fff);

  verify<int16_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int16 -> double (neg)", -1200,
				      (double) -1200 / 0x7fff);

  // int32 ->

  verify<int32_t, HostEndianessTraits,
         int8_t, HostEndianessTraits>("int32 -> int8", 120000, 120000 / 0x10000);

  verify<int32_t, HostEndianessTraits,
	 int8_t, HostEndianessTraits>("int32 -> int8 (neg)", -120000, -120000 / 0x10000);

  verify<int32_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int32 -> int16", 120000, 120000 / 0x100);

  verify<int32_t, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("int32 -> int16 (neg)", -120000, -120000 / 0x100);
  
  verify<int32_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int32 -> int32", 1200, 1200);

  verify<int32_t, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("int32 -> int32 (neg)", -1200, -1200);

  verify<int32_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int32 -> int64", 1200,
				       (int64_t) 1200 * 0x1000000LL);

  verify<int32_t, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("int32 -> int64 (neg)", -1200,
				       (int64_t) -1200 * 0x1000000LL);

  verify<int32_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int32 -> double", 1200,
				      (double) 1200 / 0x7ffffff);

  verify<int32_t, HostEndianessTraits,
	 double, HostEndianessTraits>("int32 -> double (neg)", -1200,
				      (double) -1200 / 0x7ffffff);

  // double ->
  
  verify<double, HostEndianessTraits,
         int8_t, HostEndianessTraits>("double -> int8",
				      .8, (int8_t)(.8/1 * 0x80));

  verify<double, HostEndianessTraits,
	 int8_t, HostEndianessTraits>("double -> int8 (neg)",
				      -.8, (int8_t)(-.8/1 * 0x80));

  verify<double, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("double -> int16",
				       .8, (int16_t)(.8/1 * 0x8000));

  verify<double, HostEndianessTraits,
	 int16_t, HostEndianessTraits>("double -> int16 (neg)",
				       -.8,(int16_t)(-.8/1 * 0x8000));
  
  verify<double, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("double -> int32",
				       .8, (int32_t)(.8/1 * 0x8000000));

  verify<double, HostEndianessTraits,
	 int32_t, HostEndianessTraits>("double -> int32 (neg)",
				       -.8, (int32_t)(-.8/1 * 0x8000000));

  verify<double, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("double -> int64",
				       .8,
				       (int64_t)(.8/1 * 0x800000000000LL));

  verify<double, HostEndianessTraits,
	 int64_t, HostEndianessTraits>("double -> int64 (neg)",
				       -.8,
				       (int64_t)(-.8/1 * 0x800000000000LL));

  verify<double, HostEndianessTraits,
	 double, HostEndianessTraits>("double -> double",
				      .8, .8);

  verify<double, HostEndianessTraits,
	 double, HostEndianessTraits>("double -> double (neg)",
				      -.8, -.8);

  std::cout << "Total error count: " << error_count << std::endl;
  return error_count;
}
