<commit_before>/*
* ECKCDSA (ISO/IEC 14888-3:2006/Cor.2:2009)
* (C) 2016 René Korthaus, Sirrix AG
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/eckcdsa.h>
#include <botan/internal/pk_ops_impl.h>
#include <botan/keypair.h>
#include <botan/reducer.h>
#include <botan/emsa.h>
#include <botan/hash.h>

namespace Botan {

bool ECKCDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
                                 bool strong) const
   {
   if(!public_point().on_the_curve())
      {
      return false;
      }

   if(!strong)
      {
      return true;
      }

   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
   }

namespace {

/**
* ECKCDSA signature operation
*/
class ECKCDSA_Signature_Operation : public PK_Ops::Signature_with_EMSA
   {
   public:
      typedef ECKCDSA_PrivateKey Key_Type;

      ECKCDSA_Signature_Operation(const ECKCDSA_PrivateKey& eckcdsa,
                                const std::string& emsa) :
         PK_Ops::Signature_with_EMSA(emsa),
         m_order(eckcdsa.domain().get_order()),
         m_base_point(eckcdsa.domain().get_base_point(), m_order),
         m_x(eckcdsa.private_value()),
         m_mod_order(m_order),
         m_prefix()
         {
         const BigInt public_point_x = eckcdsa.public_point().get_affine_x();
         const BigInt public_point_y = eckcdsa.public_point().get_affine_y();

         m_prefix.resize(public_point_x.bytes() + public_point_y.bytes());
         public_point_x.binary_encode(m_prefix.data());
         public_point_y.binary_encode(&m_prefix[public_point_x.bytes()]);
         m_prefix.resize(HashFunction::create(hash_for_signature())->hash_block_size()); // use only the "hash input block size" leftmost bits
         }

      secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
                                   RandomNumberGenerator& rng) override;

      size_t message_parts() const override { return 2; }
      size_t message_part_size() const override { return m_order.bytes(); }
      size_t max_input_bits() const override { return m_order.bits(); }

      bool has_prefix() override { return true; }
      secure_vector<byte> message_prefix() const override { return m_prefix; }

   private:
      const BigInt& m_order;
      Blinded_Point_Multiply m_base_point;
      const BigInt& m_x;
      Modular_Reducer m_mod_order;
      secure_vector<byte> m_prefix;
   };

secure_vector<byte>
ECKCDSA_Signature_Operation::raw_sign(const byte msg[], size_t,
                                     RandomNumberGenerator& rng)
   {
   const BigInt k = BigInt::random_integer(rng, 1, m_order);
   const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng);
   const BigInt k_times_P_x = k_times_P.get_affine_x();

   secure_vector<byte> to_be_hashed(k_times_P_x.bytes());
   k_times_P_x.binary_encode(to_be_hashed.data());

   std::unique_ptr<EMSA> emsa(m_emsa->clone());
   emsa->update(to_be_hashed.data(), to_be_hashed.size());
   secure_vector<byte> c = emsa->raw_data();
   c = emsa->encoding_of(c, max_input_bits(), rng);

   const BigInt r(c.data(), c.size());

   xor_buf(c, msg, c.size());
   BigInt w(c.data(), c.size());
   w = m_mod_order.reduce(w);

   const BigInt s = m_mod_order.multiply(m_x, k - w);
   BOTAN_ASSERT(s != 0, "invalid s");

   secure_vector<byte> output = BigInt::encode_1363(r, c.size());
   output += BigInt::encode_1363(s, m_mod_order.get_modulus().bytes());
   return output;
   }

/**
* ECKCDSA verification operation
*/
class ECKCDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
   {
   public:
      typedef ECKCDSA_PublicKey Key_Type;

      ECKCDSA_Verification_Operation(const ECKCDSA_PublicKey& eckcdsa,
                                   const std::string& emsa) :
         PK_Ops::Verification_with_EMSA(emsa),
         m_base_point(eckcdsa.domain().get_base_point()),
         m_public_point(eckcdsa.public_point()),
         m_order(eckcdsa.domain().get_order()),
         m_mod_order(m_order),
         m_prefix()
         {
         const BigInt public_point_x = m_public_point.get_affine_x();
         const BigInt public_point_y = m_public_point.get_affine_y();

         m_prefix.resize(public_point_x.bytes() + public_point_y.bytes());
         public_point_x.binary_encode(&m_prefix[0]);
         public_point_y.binary_encode(&m_prefix[public_point_x.bytes()]);
         m_prefix.resize(HashFunction::create(hash_for_signature())->hash_block_size()); // use only the "hash input block size" leftmost bits
         }

      bool has_prefix() override { return true; }
      secure_vector<byte> message_prefix() const override { return m_prefix; }

      size_t message_parts() const override { return 2; }
      size_t message_part_size() const override { return m_order.bytes(); }
      size_t max_input_bits() const override { return m_order.bits(); }

      bool with_recovery() const override { return false; }

      bool verify(const byte msg[], size_t msg_len,
                  const byte sig[], size_t sig_len) override;
   private:
      const PointGFp& m_base_point;
      const PointGFp& m_public_point;
      const BigInt& m_order;
      // FIXME: should be offered by curve
      Modular_Reducer m_mod_order;
      secure_vector<byte> m_prefix;
   };

bool ECKCDSA_Verification_Operation::verify(const byte msg[], size_t,
                                           const byte sig[], size_t sig_len)
   {
   // check that bit length of r is equal to output bit length of employed hash function h
   const std::unique_ptr<HashFunction> hash = HashFunction::create(hash_for_signature());

   // no way to know size of r in sig, so check that we have at least hash->output_length()+1
   // bytes in sig, enough for r and an arbitrary size s
   if(sig_len <= hash->output_length())
      {
      return false;
      }

   secure_vector<byte> r(sig, sig + hash->output_length());

   // check that 0 < s < q
   const BigInt s(sig + hash->output_length(), sig_len - hash->output_length());

   if(s <= 0 || s >= m_order)
      {
      return false;
      }

   secure_vector<byte> r_xor_e(r);
   xor_buf(r_xor_e, msg, r.size());
   BigInt w(r_xor_e.data(), r_xor_e.size());
   w = m_mod_order.reduce(w);

   const PointGFp q = (m_base_point * w) + (m_public_point * s);
   const BigInt q_x = q.get_affine_x();
   secure_vector<byte> c(q_x.bytes());
   q_x.binary_encode(c.data());
   std::unique_ptr<EMSA> emsa(m_emsa->clone());
   emsa->update(c.data(), c.size());
   secure_vector<byte> v = emsa->raw_data();
   Null_RNG rng;
   v = emsa->encoding_of(v, max_input_bits(), rng);

   return (v == r);
   }

}

std::unique_ptr<PK_Ops::Verification>
ECKCDSA_PublicKey::create_verification_op(const std::string& params,
                                         const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Verification>(new ECKCDSA_Verification_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

std::unique_ptr<PK_Ops::Signature>
ECKCDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
                                        const std::string& params,
                                        const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Signature>(new ECKCDSA_Signature_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

}
<commit_msg>Fix hardcoded SHA-1 in eckcdsa consistency check<commit_after>/*
* ECKCDSA (ISO/IEC 14888-3:2006/Cor.2:2009)
* (C) 2016 René Korthaus, Sirrix AG
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/eckcdsa.h>
#include <botan/internal/pk_ops_impl.h>
#include <botan/keypair.h>
#include <botan/reducer.h>
#include <botan/emsa.h>
#include <botan/hash.h>

namespace Botan {

bool ECKCDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
                                 bool strong) const
   {
   if(!public_point().on_the_curve())
      {
      return false;
      }

   if(!strong)
      {
      return true;
      }

   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
   }

namespace {

/**
* ECKCDSA signature operation
*/
class ECKCDSA_Signature_Operation : public PK_Ops::Signature_with_EMSA
   {
   public:
      typedef ECKCDSA_PrivateKey Key_Type;

      ECKCDSA_Signature_Operation(const ECKCDSA_PrivateKey& eckcdsa,
                                const std::string& emsa) :
         PK_Ops::Signature_with_EMSA(emsa),
         m_order(eckcdsa.domain().get_order()),
         m_base_point(eckcdsa.domain().get_base_point(), m_order),
         m_x(eckcdsa.private_value()),
         m_mod_order(m_order),
         m_prefix()
         {
         const BigInt public_point_x = eckcdsa.public_point().get_affine_x();
         const BigInt public_point_y = eckcdsa.public_point().get_affine_y();

         m_prefix.resize(public_point_x.bytes() + public_point_y.bytes());
         public_point_x.binary_encode(m_prefix.data());
         public_point_y.binary_encode(&m_prefix[public_point_x.bytes()]);
         m_prefix.resize(HashFunction::create(hash_for_signature())->hash_block_size()); // use only the "hash input block size" leftmost bits
         }

      secure_vector<byte> raw_sign(const byte msg[], size_t msg_len,
                                   RandomNumberGenerator& rng) override;

      size_t message_parts() const override { return 2; }
      size_t message_part_size() const override { return m_order.bytes(); }
      size_t max_input_bits() const override { return m_order.bits(); }

      bool has_prefix() override { return true; }
      secure_vector<byte> message_prefix() const override { return m_prefix; }

   private:
      const BigInt& m_order;
      Blinded_Point_Multiply m_base_point;
      const BigInt& m_x;
      Modular_Reducer m_mod_order;
      secure_vector<byte> m_prefix;
   };

secure_vector<byte>
ECKCDSA_Signature_Operation::raw_sign(const byte msg[], size_t,
                                     RandomNumberGenerator& rng)
   {
   const BigInt k = BigInt::random_integer(rng, 1, m_order);
   const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng);
   const BigInt k_times_P_x = k_times_P.get_affine_x();

   secure_vector<byte> to_be_hashed(k_times_P_x.bytes());
   k_times_P_x.binary_encode(to_be_hashed.data());

   std::unique_ptr<EMSA> emsa(m_emsa->clone());
   emsa->update(to_be_hashed.data(), to_be_hashed.size());
   secure_vector<byte> c = emsa->raw_data();
   c = emsa->encoding_of(c, max_input_bits(), rng);

   const BigInt r(c.data(), c.size());

   xor_buf(c, msg, c.size());
   BigInt w(c.data(), c.size());
   w = m_mod_order.reduce(w);

   const BigInt s = m_mod_order.multiply(m_x, k - w);
   BOTAN_ASSERT(s != 0, "invalid s");

   secure_vector<byte> output = BigInt::encode_1363(r, c.size());
   output += BigInt::encode_1363(s, m_mod_order.get_modulus().bytes());
   return output;
   }

/**
* ECKCDSA verification operation
*/
class ECKCDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA
   {
   public:
      typedef ECKCDSA_PublicKey Key_Type;

      ECKCDSA_Verification_Operation(const ECKCDSA_PublicKey& eckcdsa,
                                   const std::string& emsa) :
         PK_Ops::Verification_with_EMSA(emsa),
         m_base_point(eckcdsa.domain().get_base_point()),
         m_public_point(eckcdsa.public_point()),
         m_order(eckcdsa.domain().get_order()),
         m_mod_order(m_order),
         m_prefix()
         {
         const BigInt public_point_x = m_public_point.get_affine_x();
         const BigInt public_point_y = m_public_point.get_affine_y();

         m_prefix.resize(public_point_x.bytes() + public_point_y.bytes());
         public_point_x.binary_encode(&m_prefix[0]);
         public_point_y.binary_encode(&m_prefix[public_point_x.bytes()]);
         m_prefix.resize(HashFunction::create(hash_for_signature())->hash_block_size()); // use only the "hash input block size" leftmost bits
         }

      bool has_prefix() override { return true; }
      secure_vector<byte> message_prefix() const override { return m_prefix; }

      size_t message_parts() const override { return 2; }
      size_t message_part_size() const override { return m_order.bytes(); }
      size_t max_input_bits() const override { return m_order.bits(); }

      bool with_recovery() const override { return false; }

      bool verify(const byte msg[], size_t msg_len,
                  const byte sig[], size_t sig_len) override;
   private:
      const PointGFp& m_base_point;
      const PointGFp& m_public_point;
      const BigInt& m_order;
      // FIXME: should be offered by curve
      Modular_Reducer m_mod_order;
      secure_vector<byte> m_prefix;
   };

bool ECKCDSA_Verification_Operation::verify(const byte msg[], size_t,
                                           const byte sig[], size_t sig_len)
   {
   // check that bit length of r is equal to output bit length of employed hash function h
   const std::unique_ptr<HashFunction> hash = HashFunction::create(hash_for_signature());

   // no way to know size of r in sig, so check that we have at least hash->output_length()+1
   // bytes in sig, enough for r and an arbitrary size s
   if(sig_len <= hash->output_length())
      {
      return false;
      }

   secure_vector<byte> r(sig, sig + hash->output_length());

   // check that 0 < s < q
   const BigInt s(sig + hash->output_length(), sig_len - hash->output_length());

   if(s <= 0 || s >= m_order)
      {
      return false;
      }

   secure_vector<byte> r_xor_e(r);
   xor_buf(r_xor_e, msg, r.size());
   BigInt w(r_xor_e.data(), r_xor_e.size());
   w = m_mod_order.reduce(w);

   const PointGFp q = (m_base_point * w) + (m_public_point * s);
   const BigInt q_x = q.get_affine_x();
   secure_vector<byte> c(q_x.bytes());
   q_x.binary_encode(c.data());
   std::unique_ptr<EMSA> emsa(m_emsa->clone());
   emsa->update(c.data(), c.size());
   secure_vector<byte> v = emsa->raw_data();
   Null_RNG rng;
   v = emsa->encoding_of(v, max_input_bits(), rng);

   return (v == r);
   }

}

std::unique_ptr<PK_Ops::Verification>
ECKCDSA_PublicKey::create_verification_op(const std::string& params,
                                         const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Verification>(new ECKCDSA_Verification_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

std::unique_ptr<PK_Ops::Signature>
ECKCDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
                                        const std::string& params,
                                        const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Signature>(new ECKCDSA_Signature_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

}
<|endoftext|>


<commit_before>/**\file
 * \brief Generator of test data for fir.h regression.
 *
 * Will generate data set for regression test in MATLAB.
 *
 * \author Rick Lan
 * \copyright See LICENSE for license.
 */

#include "fir.h"
#include "fir_regression.h"

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <fstream>

void regress_fir(void)
{
	std::cout << __func__ << "..." << std::endl;

	regress_fir_double();
	regress_fir_complex_double();

	regress_fir_manual_phase(0);
	regress_fir_manual_phase(1);
	regress_fir_manual_phase(2);

	regress_fir_automatic_phase(4);
	regress_fir_automatic_phase(5);
	regress_fir_automatic_phase(6);
	regress_fir_automatic_phase(7);
}

void regress_fir_double(void)
{
	std::cout << __func__ << "..." << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	// going to use same coeff for filter(), decimate() and interp()
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size()/2; i++)
	{
		coeff[i] = urand();
		coeff[coeff.size()-1 - i] = coeff[i];
	}
	if (coeffLength % 2)
		coeff[coeffLength/2] = urand();
	std::cout << "coeffs are:" << std::endl;
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << i << " " << coeff[i] << std::endl;

	// going to use same input for filter(), decimate() and interp()
	std::vector<double> in(coeffLength*30);
	for (size_t i = 0; i < in.size(); i++)
		in[i] = urand();

	FIRBasic<double> firBasic(coeff);
	regress_fir_do(firBasic, coeff, in, "regress_fir_basic_");

	FIR<double,double,double,double> fir(coeff);
	regress_fir_do(fir, coeff, in, "regress_fir_");

	FIRSymmetric<double,double,double,double,double> firSymmetric(coeff);
	regress_fir_do(firSymmetric, coeff, in, "regress_fir_symmetric_");

}

template <class T>
void
regress_fir_do(
		FIRBasic<T> &firBasic,
		const std::vector<T> &coeff,
		const std::vector<T> &in,
		const std::string &fileNamePrefix
		)
{
	std::cout << "Main tap index: " << firBasic.main_tap_index() << std::endl;
	//Probe pCoeff(fileNamePrefix + "coeff.txt");
	//pCoeff.AddVector(coeff);
	write_to<T>(fileNamePrefix + "coeff.txt", coeff);
	//Probe pIn(fileNamePrefix + "in.txt");
	//pIn.AddVector(in);
	write_to<T>(fileNamePrefix + "in.txt", in);

	// Test filter()
	std::vector<T> out(in.size());
	for (size_t i = 0; i < out.size(); i++)
		out[i] = firBasic.filter(in[i]);
	//Probe pFilter(fileNamePrefix + "filter.txt");
	//pFilter.AddVector(out);
	write_to<T>(fileNamePrefix + "filter.txt", out);
	firBasic.init(); // clear delay line

	// Test decimate()
	out.clear();
	std::vector<T> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(firBasic.decimate(in3));
			break;
		default:
			throw std::exception();
		}
	}
	//Probe pDecimate(fileNamePrefix + "decimate.txt");
	//pDecimate.AddVector(out);
	write_to<T>(fileNamePrefix + "decimate.txt", out);
	firBasic.init(); // clear delay line

	// Test interp()
	/*
	Probe pInterp(fileNamePrefix + "interp.txt");
	for (size_t i = 0; i < in.size(); i++)
		pInterp.AddVector(firBasic.interp(in[i],3));
	*/
	const size_t rate = 3;
	std::vector<T> interpOut(rate);
	std::vector<T> allOut;
	for (size_t i = 0; i < in.size(); i++) {
		interpOut = firBasic.interp(in[i], rate);
		for (size_t r = 0; r < rate; r++)
			allOut.push_back(interpOut[r]);
	}
	write_to<T>(fileNamePrefix + "interp.txt", allOut);
	firBasic.init(); // clear delay line

}

void regress_fir_complex_double(void)
{
	std::cout << __func__ << "..." << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	// going to use same coeff for filter(), decimate() and interp()
	std::vector<cxdouble> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size()/2; i++)
	{
		coeff[i] = cxdouble(urand(), urand());
		coeff[coeff.size()-1 - i] = coeff[i];
	}
	if (coeffLength % 2)
		coeff[coeffLength/2] = cxdouble(urand(), urand());
	std::cout << "coeffs are:" << std::endl;
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << i << " " << coeff[i] << std::endl;

	// going to use same input for filter(), decimate() and interp()
	std::vector<cxdouble> in(coeffLength*30);
	for (size_t i = 0; i < in.size(); i++)
		in[i] = cxdouble(urand(), urand());

	FIRBasic<cxdouble> firBasic(coeff);
	regress_fir_do(firBasic, coeff, in, "regress_fir_basic_cx_");

	CxFIR<double,double,double,double> fir(coeff);
	regress_fir_do(fir, coeff, in, "regress_fir_cx_");

// Not implemented yet
//	CxFIRSymmetric<double,double,double,double,double> firSymmetric(coeff);
//	regress_fir_do(firSymmetric, coeff, in, "regress_fir_symmetric_cx_");

}

/** Test phase selection */
void regress_fir_manual_phase(const size_t phase)
{
	std::cout << __func__ << "..." << std::endl;
	std::cout << "going to test phase=" << phase << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size(); i++)
		coeff[i] = i+1;
	std::cout << "coeffs are:";
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << coeff[i] << " ";
	std::cout << std::endl;

	// create impulse
	std::cout << "Input is an impulse" << std::endl;
	std::vector<double> in(coeffLength, 0.0);
	in[0] = 1.0;

	FIRBasic<double> fir(coeff);

	std::vector<double> out;
	std::vector<double> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(fir.decimate(in3, phase)); // by 3
			break;
		default:
			throw std::exception();
		}
	}

	std::cout << "outputs are: ";
	for (size_t i = 0; i < out.size(); i++)
		std::cout << out[i] << " ";
	std::cout << std::endl;

}

/** Test automatic phase */
void regress_fir_automatic_phase(const size_t mainTapIndex)
{
	std::cout << __func__ << "..." << std::endl;
	std::cout << "going to test mainTapIndex=" << mainTapIndex << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size(); i++)
		coeff[i] = i+1;
	std::cout << "coeffs are:";
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << coeff[i] << " ";
	std::cout << std::endl;

	// create impulse
	std::cout << "Input is an impulse" << std::endl;
	std::vector<double> in(coeffLength, 0.0);
	in[0] = 1.0;

	FIRBasic<double> fir(coeff, mainTapIndex);

	std::vector<double> out;
	std::vector<double> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(fir.decimate(in3)); // by 3
			break;
		default:
			throw std::exception();
		}
	}

	std::cout << "outputs are: ";
	for (size_t i = 0; i < out.size(); i++)
		std::cout << out[i] << " ";
	std::cout << std::endl;

}

template <class T>
void write_to(const std::string &fileName, std::vector<T> data)
{
	std::ofstream fp;
	fp.open(fileName.c_str());
	if (!fp) {
		std::cerr << "Unable to open " << fileName << " for writing!" << std::endl;
		throw std::exception();
	}
	for (size_t i = 0; i < data.size(); i++)
		fp << data[i] << std::endl;
	fp.close();
}

double urand(void)
{
	return rand() / double (RAND_MAX);
}
<commit_msg>Remove legacy comments.<commit_after>/**\file
 * \brief Generator of test data for fir.h regression.
 *
 * Will generate data set for regression test in MATLAB.
 *
 * \author Rick Lan
 * \copyright See LICENSE for license.
 */

#include "fir.h"
#include "fir_regression.h"

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <fstream>

void regress_fir(void)
{
	std::cout << __func__ << "..." << std::endl;

	regress_fir_double();
	regress_fir_complex_double();

	regress_fir_manual_phase(0);
	regress_fir_manual_phase(1);
	regress_fir_manual_phase(2);

	regress_fir_automatic_phase(4);
	regress_fir_automatic_phase(5);
	regress_fir_automatic_phase(6);
	regress_fir_automatic_phase(7);
}

void regress_fir_double(void)
{
	std::cout << __func__ << "..." << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	// going to use same coeff for filter(), decimate() and interp()
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size()/2; i++)
	{
		coeff[i] = urand();
		coeff[coeff.size()-1 - i] = coeff[i];
	}
	if (coeffLength % 2)
		coeff[coeffLength/2] = urand();
	std::cout << "coeffs are:" << std::endl;
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << i << " " << coeff[i] << std::endl;

	// going to use same input for filter(), decimate() and interp()
	std::vector<double> in(coeffLength*30);
	for (size_t i = 0; i < in.size(); i++)
		in[i] = urand();

	FIRBasic<double> firBasic(coeff);
	regress_fir_do(firBasic, coeff, in, "regress_fir_basic_");

	FIR<double,double,double,double> fir(coeff);
	regress_fir_do(fir, coeff, in, "regress_fir_");

	FIRSymmetric<double,double,double,double,double> firSymmetric(coeff);
	regress_fir_do(firSymmetric, coeff, in, "regress_fir_symmetric_");

}

template <class T>
void
regress_fir_do(
		FIRBasic<T> &firBasic,
		const std::vector<T> &coeff,
		const std::vector<T> &in,
		const std::string &fileNamePrefix
		)
{
	std::cout << "Main tap index: " << firBasic.main_tap_index() << std::endl;
	write_to<T>(fileNamePrefix + "coeff.txt", coeff);
	write_to<T>(fileNamePrefix + "in.txt", in);

	// Test filter()
	std::vector<T> out(in.size());
	for (size_t i = 0; i < out.size(); i++)
		out[i] = firBasic.filter(in[i]);
	write_to<T>(fileNamePrefix + "filter.txt", out);
	firBasic.init(); // clear delay line

	// Test decimate()
	out.clear();
	std::vector<T> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(firBasic.decimate(in3));
			break;
		default:
			throw std::exception();
		}
	}
	write_to<T>(fileNamePrefix + "decimate.txt", out);
	firBasic.init(); // clear delay line

	// Test interp()
	const size_t rate = 3;
	std::vector<T> interpOut(rate);
	std::vector<T> allOut;
	for (size_t i = 0; i < in.size(); i++) {
		interpOut = firBasic.interp(in[i], rate);
		for (size_t r = 0; r < rate; r++)
			allOut.push_back(interpOut[r]);
	}
	write_to<T>(fileNamePrefix + "interp.txt", allOut);
	firBasic.init(); // clear delay line

}

void regress_fir_complex_double(void)
{
	std::cout << __func__ << "..." << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	// going to use same coeff for filter(), decimate() and interp()
	std::vector<cxdouble> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size()/2; i++)
	{
		coeff[i] = cxdouble(urand(), urand());
		coeff[coeff.size()-1 - i] = coeff[i];
	}
	if (coeffLength % 2)
		coeff[coeffLength/2] = cxdouble(urand(), urand());
	std::cout << "coeffs are:" << std::endl;
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << i << " " << coeff[i] << std::endl;

	// going to use same input for filter(), decimate() and interp()
	std::vector<cxdouble> in(coeffLength*30);
	for (size_t i = 0; i < in.size(); i++)
		in[i] = cxdouble(urand(), urand());

	FIRBasic<cxdouble> firBasic(coeff);
	regress_fir_do(firBasic, coeff, in, "regress_fir_basic_cx_");

	CxFIR<double,double,double,double> fir(coeff);
	regress_fir_do(fir, coeff, in, "regress_fir_cx_");

// Not implemented yet
//	CxFIRSymmetric<double,double,double,double,double> firSymmetric(coeff);
//	regress_fir_do(firSymmetric, coeff, in, "regress_fir_symmetric_cx_");

}

/** Test phase selection */
void regress_fir_manual_phase(const size_t phase)
{
	std::cout << __func__ << "..." << std::endl;
	std::cout << "going to test phase=" << phase << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size(); i++)
		coeff[i] = i+1;
	std::cout << "coeffs are:";
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << coeff[i] << " ";
	std::cout << std::endl;

	// create impulse
	std::cout << "Input is an impulse" << std::endl;
	std::vector<double> in(coeffLength, 0.0);
	in[0] = 1.0;

	FIRBasic<double> fir(coeff);

	std::vector<double> out;
	std::vector<double> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(fir.decimate(in3, phase)); // by 3
			break;
		default:
			throw std::exception();
		}
	}

	std::cout << "outputs are: ";
	for (size_t i = 0; i < out.size(); i++)
		std::cout << out[i] << " ";
	std::cout << std::endl;

}

/** Test automatic phase */
void regress_fir_automatic_phase(const size_t mainTapIndex)
{
	std::cout << __func__ << "..." << std::endl;
	std::cout << "going to test mainTapIndex=" << mainTapIndex << std::endl;

	const size_t coeffLength = 13; // center tap is the main tap when decimation by 3
	std::vector<double> coeff(coeffLength);
	// create a symmetric filter
	for (size_t i = 0; i < coeff.size(); i++)
		coeff[i] = i+1;
	std::cout << "coeffs are:";
	for (size_t i = 0; i < coeff.size(); i++)
		std::cout << coeff[i] << " ";
	std::cout << std::endl;

	// create impulse
	std::cout << "Input is an impulse" << std::endl;
	std::vector<double> in(coeffLength, 0.0);
	in[0] = 1.0;

	FIRBasic<double> fir(coeff, mainTapIndex);

	std::vector<double> out;
	std::vector<double> in3(3);
	for (size_t i = 0; i < in.size(); i++)
	{
		switch (i%3) {
		case 0:
			in3[0] = in[i];
			break;
		case 1:
			in3[1] = in[i];
			break;
		case 2:
			in3[2] = in[i];
			out.push_back(fir.decimate(in3)); // by 3
			break;
		default:
			throw std::exception();
		}
	}

	std::cout << "outputs are: ";
	for (size_t i = 0; i < out.size(); i++)
		std::cout << out[i] << " ";
	std::cout << std::endl;

}

template <class T>
void write_to(const std::string &fileName, std::vector<T> data)
{
	std::ofstream fp;
	fp.open(fileName.c_str());
	if (!fp) {
		std::cerr << "Unable to open " << fileName << " for writing!" << std::endl;
		throw std::exception();
	}
	for (size_t i = 0; i < data.size(); i++)
		fp << data[i] << std::endl;
	fp.close();
}

double urand(void)
{
	return std::rand() / double (RAND_MAX);
}
<|endoftext|>


<commit_before>#include "Name.h"

bool Name::init(String name) {
    size = name.length() + 1;

    data = (uint8_t *) malloc(size);

    if (data != NULL) {
        uint8_t lastDot = size;

        for (uint8_t i = size - 1; i > 0; i--) {
            uint8_t c = name.charAt(i - 1);

            if (c == '.') {
                data[i] = lastDot - i - 1;
                lastDot = i;
            } else {
                data[i] = c;
            }
        }

        data[0] = lastDot - 1;
    }

    return data != NULL;
}

uint8_t Name::getSize() {
    return size;
}

bool Name::match(uint8_t c) {
    matches = matches && matchOffset < size && data[matchOffset++] == c;

    return matches;
}

void Name::write(Buffer buffer) {
    if (writtenOffset == 0) {
        writtenOffset = buffer.getOffset();

        for (int i = 0; i < size; i++) {
            buffer.writeUInt8(data[i]);
        }
    } else {
        buffer.writeUInt16((BACK_REF << 8) | writtenOffset);
    }
}

void Name::reset() {
    matches = true;
    matchOffset = 0;
    writtenOffset = 0;
}
<commit_msg>Added init(Buffer) method and overloaded == and !=<commit_after>#include "Name.h"

bool Name::init(String name) {
    size = name.length() + 1;

    if (data) {
        free(data);
    }

    data = (uint8_t *) malloc(size);

    if (data != NULL) {
        uint8_t lastDot = size;

        for (uint8_t i = size - 1; i > 0; i--) {
            uint8_t c = name.charAt(i - 1);

            if (c == '.') {
                data[i] = lastDot - i - 1;
                lastDot = i;
            } else {
                data[i] = c;
            }
        }

        data[0] = lastDot - 1;
    }

    return data != NULL;
}

bool Name::init(Buffer buffer) {
    bool success = buffer.available();

    if (success) {
        if (data) {
            free(data);
        }

        data = (uint8_t *) malloc(255);

        success = data;
    }

    if (success) {
        uint8_t c = buffer.readUInt8();

        uint8_t idx = 0;

        while (c != END_OF_NAME) {
            while ((c & BACK_REF) == BACK_REF) {
                success = buffer.available() > 0;

                if (success) {
                    uint16_t backReferenceOffset = (c & ~BACK_REF) << 8 | buffer.readUInt8();

                    success = backReferenceOffset < buffer.getOffset();

                    if (success) {
                        buffer.mark();
                        buffer.setOffset(backReferenceOffset);
                        c = inBuffer.readUInt8();
                    }
                }
            }

            if (success && buffer.available() > c) {
                data[idx++] = c;

                for (int i = 0; i < c; i++) {
                    data[idx++] = buffer.readUInt8();
                }

                c = inBuffer.readUInt8();
            }
        }

        data[idx++] = c;

        inBuffer.reset();
    }

    if (!success && data) {
        free(data);
    }

    size = idx;
}

uint8_t Name::getSize() {
    return size;
}

bool Name::match(uint8_t c) {
    matches = matches && matchOffset < size && data[matchOffset++] == c;

    return matches;
}

void Name::write(Buffer buffer) {
    if (writtenOffset == 0) {
        writtenOffset = buffer.getOffset();

        for (int i = 0; i < size; i++) {
            buffer.writeUInt8(data[i]);
        }
    } else {
        buffer.writeUInt16((BACK_REF << 8) | writtenOffset);
    }
}

void Name::reset() {
    matches = true;
    matchOffset = 0;
    writtenOffset = 0;
}

bool Name::operator==(const Name &other) const {
    bool equal = size == other->size;

    if (equal) {
        int idx = 0;

        while (equal && idx < size) {
            equal &= data[idx] == other->data[idx];
        }
    }

    return equal;
}

bool Name::operator!=(const Name &other) const {
    return !(*this == other);
}
<|endoftext|>


<commit_before>#include "ctc.h"
#include "logger.h"

PrefixTree::Node::Node() :
  inTok (0),
  parent (NULL),
  nStates (0),
  outLen (0)
{ }

PrefixTree::Node::Node (const PrefixTree& tree, const Node* parent, InputToken inTok) :
  inTok (inTok),
  parent (parent),
  nStates (tree.nStates),
  outLen (tree.outLen)
{ }

void PrefixTree::Node::fill (const PrefixTree& tree)
{
  cellStorage = vector<double> (nCells(), -numeric_limits<double>::infinity());
  logPrefixProb = -numeric_limits<double>::infinity();

  if (!parent)
    seqCell (0, 0) = 0;

  for (OutputIndex outPos = 0; outPos <= outLen; ++outPos) {
    const OutputToken outTok = outPos ? tree.output[outPos-1] : OutputTokenizer::emptyToken();
    for (StateIndex d = 0; d < nStates; ++d) {
      LogThisAt(9,"d="<<d<<": ");
      const EvaluatedMachineState& state = tree.machine.state[d];
      double& ll = seqCell (outPos, d);
      if (parent && state.incoming.count (inTok)) {
	const auto& incoming = state.incoming.at (inTok);
	if (outPos)
	  accumulateSeqCell (ll, incoming, *parent, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *parent, OutputTokenizer::emptyToken(), outPos);
      }
      if (state.incoming.count (InputTokenizer::emptyToken())) {
	const auto& incoming = state.incoming.at (InputTokenizer::emptyToken());
	if (outPos)
	  accumulateSeqCell (ll, incoming, *this, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *this, OutputTokenizer::emptyToken(), outPos);
      }
      LogThisAt(8,"seqCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
    // looping over d AND prevState seems inefficient! Could precompute sumInTrans*outTrans for each outTok
    for (StateIndex d = 0; d < nStates; ++d) {
      double& ll = prefixCell (outPos, d);
      ll = seqCell (outPos, d);
      if (outPos) {
	const EvaluatedMachineState& state = tree.machine.state[d];
	for (const auto& i_ostm: state.incoming) {
	  const EvaluatedMachineState::OutStateTransMap& outStateTransMap = i_ostm.second;
	  if (outStateTransMap.count (outTok))
	    for (const auto& st: outStateTransMap.at (outTok)) {
	      const EvaluatedMachineState::Trans& trans = st.second;
	      for (StateIndex prevState = 0; prevState < nStates; ++prevState) {
		const double prevCell = prefixCell (outPos - 1, prevState);
		const double logEmitWeight = prevCell + tree.sumInTrans[prevState][st.first] + trans.logWeight;
		log_accum_exp (ll, logEmitWeight);
		LogThisAt(9,"prefixCell("<<outPos<<","<<d<<") logsum+= "<<prevCell<<" + "<<tree.sumInTrans[prevState][st.first]<<" + "<<trans.logWeight<<" ("<<prevState<<"->"<<st.first<<"->"<<d<<")"<<endl);
	      }
	    }
	}
      }
      LogThisAt(8,"prefixCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
  }

  for (StateIndex d = 0; d < nStates; ++d) {
    log_accum_exp (logPrefixProb, prefixCell(outLen,d) + tree.sumInTrans[d][tree.nStates - 1]);
    LogThisAt(9,"logPrefixProb logsum+= "<<prefixCell(outLen,d)<<" + "<<tree.sumInTrans[d][tree.nStates - 1]<<" ("<<d<<"->end)"<<endl);
  }

  if (parent && logPrefixProb > parent->logPrefixProb)
    Warn ("LogP(%s*)=%g rose from LogP(%s*)=%g",
	  to_string_join(tree.seqTraceback(this),"").c_str(), logPrefixProb,
	  to_string_join(tree.seqTraceback(parent),"").c_str(), parent->logPrefixProb);
}

double PrefixTree::Node::logSeqProb() const {
  return seqCell (outLen, nStates - 1);
}

PrefixTree::PrefixTree (const EvaluatedMachine& machine, const vguard<OutputSymbol>& outSym) :
  machine (machine),
  sumInTrans (machine.sumInTrans()),
  output (machine.outputTokenizer.tokenize (outSym)),
  outLen (output.size()),
  nStates (machine.nStates()),
  bestSeqNode (NULL),
  bestLogSeqProb (-numeric_limits<double>::infinity())
{
  addNode (NULL, machine.inputTokenizer.emptyToken());
  const InputToken inToks = machine.inputTokenizer.tok2sym.size() - 1;
  while (!nodeQueue.empty()) {
    Node* parent = bestPrefixNode();
    LogThisAt (5, "Nodes: " << nodeStore.size() << " Extending " << to_string_join(bestPrefix(),"") << "* (" << parent->logPrefixProb << ")" << endl);
    if (parent->logPrefixProb > bestLogSeqProb) {
      nodeQueue.pop();
      for (InputToken inTok = 1; inTok <= inToks; ++inTok)
	(void) addNode (parent, inTok);
    } else
      break;
  }
}

PrefixTree::Node* PrefixTree::addNode (const Node* parent, InputToken inTok) {
  nodeStore.push_back (Node (*this, parent, inTok));
  Node* nodePtr = &nodeStore.back();

  LogThisAt (6, "Adding node " << (parent ? to_string_join (seqTraceback (nodePtr), "") : string("<root>")) << endl);

  nodePtr->fill (*this);
  if (nodePtr->logPrefixProb > bestLogSeqProb)
    nodeQueue.push (nodePtr);

  const double logNodeSeqProb = nodePtr->logSeqProb();
  if (logNodeSeqProb > bestLogSeqProb) {
    bestSeqNode = nodePtr;
    bestLogSeqProb = logNodeSeqProb;
    LogThisAt (4, "Nodes: " << nodeStore.size() << " Best sequence so far: " << to_string_join (bestSeq(), "") << " (" << bestLogSeqProb << ")" << endl);
  }
  LogThisAt (7, "logP(seq)=" << logNodeSeqProb << " logP(seq*)=" << nodePtr->logPrefixProb << " seq: " << to_string_join (seqTraceback (nodePtr), "") << endl);

  return nodePtr;
}

vguard<InputSymbol> PrefixTree::seqTraceback (const Node* node) const {
  list<InputToken> inSeq;
  while (node && node->inTok) {
    inSeq.push_back (node->inTok);
    node = node->parent;
  }
  return machine.inputTokenizer.detokenize (vguard<InputToken> (inSeq.rbegin(), inSeq.rend()));
}
<commit_msg>added a debugging message further exposing prefix prob calculation bug<commit_after>#include "ctc.h"
#include "logger.h"

PrefixTree::Node::Node() :
  inTok (0),
  parent (NULL),
  nStates (0),
  outLen (0)
{ }

PrefixTree::Node::Node (const PrefixTree& tree, const Node* parent, InputToken inTok) :
  inTok (inTok),
  parent (parent),
  nStates (tree.nStates),
  outLen (tree.outLen)
{ }

void PrefixTree::Node::fill (const PrefixTree& tree)
{
  cellStorage = vector<double> (nCells(), -numeric_limits<double>::infinity());
  logPrefixProb = -numeric_limits<double>::infinity();

  if (!parent)
    seqCell (0, 0) = 0;

  for (OutputIndex outPos = 0; outPos <= outLen; ++outPos) {
    const OutputToken outTok = outPos ? tree.output[outPos-1] : OutputTokenizer::emptyToken();
    for (StateIndex d = 0; d < nStates; ++d) {
      LogThisAt(9,"d="<<d<<": ");
      const EvaluatedMachineState& state = tree.machine.state[d];
      double& ll = seqCell (outPos, d);
      if (parent && state.incoming.count (inTok)) {
	const auto& incoming = state.incoming.at (inTok);
	if (outPos)
	  accumulateSeqCell (ll, incoming, *parent, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *parent, OutputTokenizer::emptyToken(), outPos);
      }
      if (state.incoming.count (InputTokenizer::emptyToken())) {
	const auto& incoming = state.incoming.at (InputTokenizer::emptyToken());
	if (outPos)
	  accumulateSeqCell (ll, incoming, *this, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *this, OutputTokenizer::emptyToken(), outPos);
      }
      LogThisAt(8,"seqCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
    // looping over d AND prevState seems inefficient! Could precompute sumInTrans*outTrans for each outTok
    for (StateIndex d = 0; d < nStates; ++d) {
      double& ll = prefixCell (outPos, d);
      ll = seqCell (outPos, d);
      if (outPos) {
	const EvaluatedMachineState& state = tree.machine.state[d];
	for (const auto& i_ostm: state.incoming) {
	  const EvaluatedMachineState::OutStateTransMap& outStateTransMap = i_ostm.second;
	  if (outStateTransMap.count (outTok))
	    for (const auto& st: outStateTransMap.at (outTok)) {
	      const EvaluatedMachineState::Trans& trans = st.second;
	      for (StateIndex prevState = 0; prevState < nStates; ++prevState) {
		const double prevCell = prefixCell (outPos - 1, prevState);
		const double logEmitWeight = prevCell + tree.sumInTrans[prevState][st.first] + trans.logWeight;
		log_accum_exp (ll, logEmitWeight);
		LogThisAt(9,"prefixCell("<<outPos<<","<<d<<") logsum+= "<<prevCell<<" + "<<tree.sumInTrans[prevState][st.first]<<" + "<<trans.logWeight<<" ("<<prevState<<"->"<<st.first<<"->"<<d<<")"<<endl);
	      }
	    }
	}
      }
      LogThisAt(8,"prefixCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
  }

  for (StateIndex d = 0; d < nStates; ++d) {
    log_accum_exp (logPrefixProb, prefixCell(outLen,d) + tree.sumInTrans[d][tree.nStates - 1]);
    LogThisAt(9,"logPrefixProb logsum+= "<<prefixCell(outLen,d)<<" + "<<tree.sumInTrans[d][tree.nStates - 1]<<" ("<<d<<"->end)"<<endl);
  }

  if (parent && logPrefixProb > parent->logPrefixProb)
    Warn ("LogP(%s*)=%g rose from LogP(%s*)=%g",
	  to_string_join(tree.seqTraceback(this),"").c_str(), logPrefixProb,
	  to_string_join(tree.seqTraceback(parent),"").c_str(), parent->logPrefixProb);
}

double PrefixTree::Node::logSeqProb() const {
  return seqCell (outLen, nStates - 1);
}

PrefixTree::PrefixTree (const EvaluatedMachine& machine, const vguard<OutputSymbol>& outSym) :
  machine (machine),
  sumInTrans (machine.sumInTrans()),
  output (machine.outputTokenizer.tokenize (outSym)),
  outLen (output.size()),
  nStates (machine.nStates()),
  bestSeqNode (NULL),
  bestLogSeqProb (-numeric_limits<double>::infinity())
{
  addNode (NULL, machine.inputTokenizer.emptyToken());
  const InputToken inToks = machine.inputTokenizer.tok2sym.size() - 1;
  while (!nodeQueue.empty()) {
    Node* parent = bestPrefixNode();
    LogThisAt (5, "Nodes: " << nodeStore.size() << " Extending " << to_string_join(bestPrefix(),"") << "* (" << parent->logPrefixProb << ")" << endl);
    if (parent->logPrefixProb > bestLogSeqProb) {
      nodeQueue.pop();
      double norm = 0;
      for (InputToken inTok = 1; inTok <= inToks; ++inTok)
	norm += exp (addNode(parent,inTok)->logPrefixProb);
      LogThisAt (6, "log(Sum_x(P(Sx*)) / P(S*)) = " << (log(norm) - exp(parent->logPrefixProb)) << endl);
    } else
      break;
  }
}

PrefixTree::Node* PrefixTree::addNode (const Node* parent, InputToken inTok) {
  nodeStore.push_back (Node (*this, parent, inTok));
  Node* nodePtr = &nodeStore.back();

  LogThisAt (6, "Adding node " << (parent ? to_string_join (seqTraceback (nodePtr), "") : string("<root>")) << endl);

  nodePtr->fill (*this);
  if (nodePtr->logPrefixProb > bestLogSeqProb)
    nodeQueue.push (nodePtr);

  const double logNodeSeqProb = nodePtr->logSeqProb();
  if (logNodeSeqProb > bestLogSeqProb) {
    bestSeqNode = nodePtr;
    bestLogSeqProb = logNodeSeqProb;
    LogThisAt (4, "Nodes: " << nodeStore.size() << " Best sequence so far: " << to_string_join (bestSeq(), "") << " (" << bestLogSeqProb << ")" << endl);
  }
  LogThisAt (7, "logP(seq)=" << logNodeSeqProb << " logP(seq*)=" << nodePtr->logPrefixProb << " seq: " << to_string_join (seqTraceback (nodePtr), "") << endl);

  return nodePtr;
}

vguard<InputSymbol> PrefixTree::seqTraceback (const Node* node) const {
  list<InputToken> inSeq;
  while (node && node->inTok) {
    inSeq.push_back (node->inTok);
    node = node->parent;
  }
  return machine.inputTokenizer.detokenize (vguard<InputToken> (inSeq.rbegin(), inSeq.rend()));
}
<|endoftext|>


<commit_before>#include <mlpack/core.hpp>
#include <mlpack/methods/hmm/hmm.hpp>
#include <mlpack/methods/gmm/gmm.hpp>

using GMM = mlpack::gmm::GMM;

template<typename Distribution>
using HMM = mlpack::hmm::HMM<Distribution>;

using GaussianDistribution = mlpack::distribution::GaussianDistribution;

int main(){
    //Number of gaussians
    static constexpr const std::size_t n_gaussians = 2;

    //Number of states
    static constexpr const std::size_t n_states = 2;

    //Number of features
    static constexpr const std::size_t n_features = 2;

    std::vector<arma::mat> images;
    std::vector<arma::Row<size_t>> labels;

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 44;
        image.col(0)[1] = 11;
        image.col(1)[0] = 55;
        image.col(1)[1] = 10;
        image.col(2)[0] = 23;
        image.col(2)[1] = 12;
        image.col(3)[0] = 11; image.col(3)[1] = 9;
        image.col(4)[0] = 20;
        image.col(4)[1] = 8;
        image.col(5)[0] = 40;
        image.col(5)[1] = 5;

        label = {0, 1, 1, 0, 0, 1};
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 43;
        image.col(0)[1] = 10;
        image.col(1)[0] = 50;
        image.col(1)[1] = 11;
        image.col(2)[0] = 22;
        image.col(2)[1] = 11;
        image.col(3)[0] = 10;
        image.col(3)[1] = 8;
        image.col(4)[0] = 22;
        image.col(4)[1] = 9;
        image.col(5)[0] = 43;
        image.col(5)[1] = 4;

        label = {0, 1, 1, 0, 0, 1};
    }

    {
        images.emplace_back(n_features, 7);
        labels.emplace_back(7);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 43;
        image.col(0)[1] = 10;
        image.col(1)[0] = 50;
        image.col(1)[1] = 11;
        image.col(2)[0] = 22;
        image.col(2)[1] = 11;
        image.col(3)[0] = 10;
        image.col(3)[1] = 8;
        image.col(4)[0] = 22;
        image.col(4)[1] = 9;
        image.col(5)[0] = 43;
        image.col(5)[1] = 4;
        image.col(6)[0] = 22;
        image.col(6)[1] = 3;

        label = {0, 1, 1, 0, 0, 1, 1};
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);

        labels.back() = labels[0];
        images.back() = images[0] + 0.1;
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);

        labels.back() = labels[1];
        images.back() = images[1] - 0.1;
    }

    HMM<GMM> hmm(n_states, GMM(n_gaussians, n_features));

    // Train the HMM.
    hmm.Train(images, labels);

    for(auto& image : images){
        std::cout << "From training(hmm): " << hmm.LogLikelihood(image) << std::endl;
    }

    {
        arma::mat likely(n_features, 7);
        likely = images[2] + 1.0;
        std::cout << "Likely(hmm):" << hmm.LogLikelihood(likely) << std::endl;
    }

    {
        arma::mat likely(n_features, 7);
        likely = images[2] - 1.0;
        std::cout << "Likely(hmm):" << hmm.LogLikelihood(likely) << std::endl;
    }

    {
        arma::mat unlikely(n_features, 6);
        unlikely = images[0] * 2.0;
        std::cout << "Unlikely(hmm): " << hmm.LogLikelihood(unlikely) << std::endl;
    }

    //Test GMM directly (does not seem to be possible)

    GMM gmm(n_gaussians, n_features);

    gmm.Train(images[0]);

    for(std::size_t i = 1; i < images.size(); ++i){
        gmm.Train(images[i], 1, true);
    }

    auto likelihood = [&gmm](auto& image){
        double likelihood = std::log(gmm.Probability(image.col(0)));

        for(std::size_t f = 1; f < image.n_cols; ++f){
            likelihood += std::log(gmm.Probability(image.col(f)));
        }

        return likelihood;
    };

    for(auto& image : images){
        for(std::size_t f = 0; f < image.n_cols; ++f){
            std::cout << "From training(gmm): o(" << f << "): " << gmm.Probability(image.col(f)) << std::endl;
        }
        std::cout << "From training(gmm): : " << likelihood(image) << std::endl;
    }

    {
        arma::mat unlikely(n_features, 6);
        unlikely = images[0] * 2.0;

        for(std::size_t f = 0; f < unlikely.n_cols; ++f){
            std::cout << "Unlikely(gmm): o(" << f << "): " << gmm.Probability(unlikely.col(f)) << std::endl;
        }

        std::cout << "Unlikely(gmm): : " << likelihood(unlikely) << std::endl;
    }
}
<commit_msg>Cleanup<commit_after>#include <mlpack/core.hpp>
#include <mlpack/methods/hmm/hmm.hpp>
#include <mlpack/methods/gmm/gmm.hpp>

using GMM = mlpack::gmm::GMM;

template<typename Distribution>
using HMM = mlpack::hmm::HMM<Distribution>;

using GaussianDistribution = mlpack::distribution::GaussianDistribution;

int main(){
    //Number of gaussians
    static constexpr const std::size_t n_gaussians = 2;

    //Number of states
    static constexpr const std::size_t n_states = 2;

    //Number of features
    static constexpr const std::size_t n_features = 2;

    std::vector<arma::mat> images;
    std::vector<arma::Row<size_t>> labels;

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 44;
        image.col(0)[1] = 11;
        image.col(1)[0] = 55;
        image.col(1)[1] = 10;
        image.col(2)[0] = 23;
        image.col(2)[1] = 12;
        image.col(3)[0] = 11; image.col(3)[1] = 9;
        image.col(4)[0] = 20;
        image.col(4)[1] = 8;
        image.col(5)[0] = 40;
        image.col(5)[1] = 5;

        label = {0, 1, 1, 0, 0, 1};
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 43;
        image.col(0)[1] = 10;
        image.col(1)[0] = 50;
        image.col(1)[1] = 11;
        image.col(2)[0] = 22;
        image.col(2)[1] = 11;
        image.col(3)[0] = 10;
        image.col(3)[1] = 8;
        image.col(4)[0] = 22;
        image.col(4)[1] = 9;
        image.col(5)[0] = 43;
        image.col(5)[1] = 4;

        label = {0, 1, 1, 0, 0, 1};
    }

    {
        images.emplace_back(n_features, 7);
        labels.emplace_back(7);
        auto& image = images.back();
        auto& label = labels.back();

        image.col(0)[0] = 43;
        image.col(0)[1] = 10;
        image.col(1)[0] = 50;
        image.col(1)[1] = 11;
        image.col(2)[0] = 22;
        image.col(2)[1] = 11;
        image.col(3)[0] = 10;
        image.col(3)[1] = 8;
        image.col(4)[0] = 22;
        image.col(4)[1] = 9;
        image.col(5)[0] = 43;
        image.col(5)[1] = 4;
        image.col(6)[0] = 22;
        image.col(6)[1] = 3;

        label = {0, 1, 1, 0, 0, 1, 1};
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);

        labels.back() = labels[0];
        images.back() = images[0] + 0.1;
    }

    {
        images.emplace_back(n_features, 6);
        labels.emplace_back(6);

        labels.back() = labels[1];
        images.back() = images[1] - 0.1;
    }

    // Train a HMM.

    HMM<GMM> hmm(n_states, GMM(n_gaussians, n_features));

    hmm.Train(images, labels);

    //Train a GMM directly

    GMM gmm(n_gaussians, n_features);

    gmm.Train(images[0]);

    for(std::size_t i = 1; i < images.size(); ++i){
        gmm.Train(images[i], 1, true);
    }

    // Some tests

    auto likelihood = [&gmm](auto& image){
        double likelihood = std::log(gmm.Probability(image.col(0)));

        for(std::size_t f = 1; f < image.n_cols; ++f){
            likelihood += std::log(gmm.Probability(image.col(f)));
        }

        return likelihood;
    };

    for(auto& image : images){
        std::cout << "From training(hmm): " << hmm.LogLikelihood(image) << std::endl;
        std::cout << "From training(gmm): : " << likelihood(image) << std::endl;
    }

    {
        arma::mat likely(n_features, 7);
        likely = images[2] + 1.0;
        std::cout << "Likely(hmm):" << hmm.LogLikelihood(likely) << std::endl;
        std::cout << "Likely(gmm):" << likelihood(likely) << std::endl;
    }

    {
        arma::mat likely(n_features, 7);
        likely = images[2] - 1.0;
        std::cout << "Likely(hmm):" << hmm.LogLikelihood(likely) << std::endl;
        std::cout << "Likely(gmm):" << likelihood(likely) << std::endl;
    }

    {
        arma::mat unlikely(n_features, 6);
        unlikely = images[0] * 2.0;
        std::cout << "Unlikely(hmm):" << hmm.LogLikelihood(unlikely) << std::endl;
        std::cout << "Unlikely(gmm): : " << likelihood(unlikely) << std::endl;
    }
}
<|endoftext|>


<commit_before>/* -*- C++ -*-

This file implements the Job class.

$ Author: Mirko Boehm $
$ Copyright: (C) 2004-2013 Mirko Boehm $
$ Contact: mirko@kde.org
http://www.kde.org
http://creative-destruction.me $

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.

$Id: Job.cpp 20 2005-08-08 21:02:51Z mirko $
*/

#include "job.h"

#include <QtCore/QList>
#include <QtCore/QMutex>
#include "debuggingaids.h"
#include "thread.h"
#include <QAtomicPointer>
#include <QAtomicInt>

#include "queuepolicy.h"
#include "dependencypolicy.h"
#include "executor_p.h"
#include "executewrapper_p.h"
#include "managedjobpointer.h"
#include "exception.h"

namespace
{

class DefaultExecutor : public ThreadWeaver::Executor
{
public:
    void begin(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread)
    {
        defaultBegin(job, thread);
    }

    void execute(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE {
        run(job, thread);
    }

    void end(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread)
    {
        defaultEnd(job, thread);
    }
};

class DebugExecuteWrapper : public ThreadWeaver::ExecuteWrapper
{
public:
    void execute(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *th) Q_DECL_OVERRIDE {
        Q_ASSERT_X(job, Q_FUNC_INFO, "job may not be zero!");
        ThreadWeaver::debug(3, "DefaultExecuteWrapper::execute: executing job %p in thread %i.\n", job.data(), th ? th->id() : 0);
        executeWrapped(job, th);
        ThreadWeaver::debug(3, "Job::execute: finished execution of job in thread %i.\n", th ? th->id() : 0);
    }
};

static DefaultExecutor defaultExecutor;
}

namespace ThreadWeaver
{

class Job::Private
{
public:
    Private()
        : mutex(QMutex::NonRecursive)
        , status(Job::Status_NoStatus)
        , executor(&defaultExecutor)
    {}

    ~Private()
    {}

    /* The list of QueuePolicies assigned to this Job. */
    QList<QueuePolicy *> queuePolicies;

    mutable QMutex mutex;
    /* @brief The status of the Job. */
    QAtomicInt status;

    /** The Executor that will execute this Job. */
    QAtomicPointer<Executor> executor;

    //FIXME What is the correct KDE frameworks no debug switch?
#if not defined NDEBUG
    /** DebugExecuteWrapper for logging of Job execution. */
    DebugExecuteWrapper debugExecuteWrapper;
#endif
};

Job::Job()
    : d(new Private())
{
#if not defined NDEBUG
    d->debugExecuteWrapper.wrap(setExecutor(&d->debugExecuteWrapper));
#endif
    d->status.storeRelease(Status_New);
}

Job::~Job()
{
    for (int index = 0; index < d->queuePolicies.size(); ++index) {
        d->queuePolicies.at(index)->destructed(this);
    }
    delete d;
}

void Job::execute(JobPointer self, Thread *th)
{
    Executor *executor = d->executor.loadAcquire();
    Q_ASSERT(executor); //may never be unset!
    Q_ASSERT(self);
    executor->begin(self, th);
    self->setStatus(Status_Running);
    try {
        executor->execute(self, th);
        if (self->status() == Status_Running) {
            self->setStatus(Status_Success);
        }
    } catch (JobAborted &) {
        self->setStatus(Status_Aborted);
    } catch (JobFailed &) {
        self->setStatus(Status_Failed);
    } catch (...) {
        debug(0, "Uncaught exception in Job %p, aborting.", self.data());
        throw;
    }
    Q_ASSERT(self->status() > Status_Running);
    executor->end(self, th);
    executor->cleanup(self, th);
}

void Job::blockingExecute()
{
    execute(ManagedJobPointer<Job>(this), 0);
}
Executor *Job::setExecutor(Executor *executor)
{
    return d->executor.fetchAndStoreOrdered(executor == 0 ? &defaultExecutor : executor);
}

Executor *Job::executor() const
{
    return d->executor.fetchAndAddOrdered(0);
}

int Job::priority() const
{
    return 0;
}

void Job::setStatus(JobInterface::Status status)
{
    d->status.storeRelease(status);
}

JobInterface::Status Job::status() const
{
    // since status is set only through setStatus, this should be safe:
    return static_cast<Status>(d->status.loadAcquire());
}

bool Job::success() const
{
    return d->status.loadAcquire() == Status_Success;
}

void Job::freeQueuePolicyResources(JobPointer job)
{
    for (int index = 0; index < d->queuePolicies.size(); ++index) {
        d->queuePolicies.at(index)->free(job);
    }
}

void Job::defaultBegin(JobPointer, Thread *)
{
}

void Job::defaultEnd(JobPointer job, Thread *)
{
    freeQueuePolicyResources(job);
}

void Job::aboutToBeQueued(QueueAPI *api)
{
    QMutexLocker l(mutex()); Q_UNUSED(l);
    aboutToBeQueued_locked(api);
}

void Job::aboutToBeQueued_locked(QueueAPI *)
{
}

void Job::aboutToBeDequeued(QueueAPI *api)
{
    QMutexLocker l(mutex()); Q_UNUSED(l);
    aboutToBeDequeued_locked(api);
}

void Job::aboutToBeDequeued_locked(QueueAPI *)
{
}

void Job::assignQueuePolicy(QueuePolicy *policy)
{
    if (! d->queuePolicies.contains(policy)) {
        d->queuePolicies.append(policy);
    }
}

void Job::removeQueuePolicy(QueuePolicy *policy)
{
    int index = d->queuePolicies.indexOf(policy);
    if (index != -1) {
        d->queuePolicies.removeAt(index);
    }
}

QList<QueuePolicy *> Job::queuePolicies() const
{
    return d->queuePolicies;
}

bool Job::isFinished() const
{
    const Status s = status();
    return s == Status_Success || s == Status_Failed || s == Status_Aborted;
}

QMutex *Job::mutex() const
{
    return &d->mutex;
}

}

#include "managedjobpointer.h"
<commit_msg>use ! instead of not<commit_after>/* -*- C++ -*-

This file implements the Job class.

$ Author: Mirko Boehm $
$ Copyright: (C) 2004-2013 Mirko Boehm $
$ Contact: mirko@kde.org
http://www.kde.org
http://creative-destruction.me $

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.

$Id: Job.cpp 20 2005-08-08 21:02:51Z mirko $
*/

#include "job.h"

#include <QtCore/QList>
#include <QtCore/QMutex>
#include "debuggingaids.h"
#include "thread.h"
#include <QAtomicPointer>
#include <QAtomicInt>

#include "queuepolicy.h"
#include "dependencypolicy.h"
#include "executor_p.h"
#include "executewrapper_p.h"
#include "managedjobpointer.h"
#include "exception.h"

namespace
{

class DefaultExecutor : public ThreadWeaver::Executor
{
public:
    void begin(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread)
    {
        defaultBegin(job, thread);
    }

    void execute(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE {
        run(job, thread);
    }

    void end(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *thread)
    {
        defaultEnd(job, thread);
    }
};

class DebugExecuteWrapper : public ThreadWeaver::ExecuteWrapper
{
public:
    void execute(ThreadWeaver::JobPointer job, ThreadWeaver::Thread *th) Q_DECL_OVERRIDE {
        Q_ASSERT_X(job, Q_FUNC_INFO, "job may not be zero!");
        ThreadWeaver::debug(3, "DefaultExecuteWrapper::execute: executing job %p in thread %i.\n", job.data(), th ? th->id() : 0);
        executeWrapped(job, th);
        ThreadWeaver::debug(3, "Job::execute: finished execution of job in thread %i.\n", th ? th->id() : 0);
    }
};

static DefaultExecutor defaultExecutor;
}

namespace ThreadWeaver
{

class Job::Private
{
public:
    Private()
        : mutex(QMutex::NonRecursive)
        , status(Job::Status_NoStatus)
        , executor(&defaultExecutor)
    {}

    ~Private()
    {}

    /* The list of QueuePolicies assigned to this Job. */
    QList<QueuePolicy *> queuePolicies;

    mutable QMutex mutex;
    /* @brief The status of the Job. */
    QAtomicInt status;

    /** The Executor that will execute this Job. */
    QAtomicPointer<Executor> executor;

    //FIXME What is the correct KDE frameworks no debug switch?
#if !defined(NDEBUG)
    /** DebugExecuteWrapper for logging of Job execution. */
    DebugExecuteWrapper debugExecuteWrapper;
#endif
};

Job::Job()
    : d(new Private())
{
#if !defined(NDEBUG)
    d->debugExecuteWrapper.wrap(setExecutor(&d->debugExecuteWrapper));
#endif
    d->status.storeRelease(Status_New);
}

Job::~Job()
{
    for (int index = 0; index < d->queuePolicies.size(); ++index) {
        d->queuePolicies.at(index)->destructed(this);
    }
    delete d;
}

void Job::execute(JobPointer self, Thread *th)
{
    Executor *executor = d->executor.loadAcquire();
    Q_ASSERT(executor); //may never be unset!
    Q_ASSERT(self);
    executor->begin(self, th);
    self->setStatus(Status_Running);
    try {
        executor->execute(self, th);
        if (self->status() == Status_Running) {
            self->setStatus(Status_Success);
        }
    } catch (JobAborted &) {
        self->setStatus(Status_Aborted);
    } catch (JobFailed &) {
        self->setStatus(Status_Failed);
    } catch (...) {
        debug(0, "Uncaught exception in Job %p, aborting.", self.data());
        throw;
    }
    Q_ASSERT(self->status() > Status_Running);
    executor->end(self, th);
    executor->cleanup(self, th);
}

void Job::blockingExecute()
{
    execute(ManagedJobPointer<Job>(this), 0);
}
Executor *Job::setExecutor(Executor *executor)
{
    return d->executor.fetchAndStoreOrdered(executor == 0 ? &defaultExecutor : executor);
}

Executor *Job::executor() const
{
    return d->executor.fetchAndAddOrdered(0);
}

int Job::priority() const
{
    return 0;
}

void Job::setStatus(JobInterface::Status status)
{
    d->status.storeRelease(status);
}

JobInterface::Status Job::status() const
{
    // since status is set only through setStatus, this should be safe:
    return static_cast<Status>(d->status.loadAcquire());
}

bool Job::success() const
{
    return d->status.loadAcquire() == Status_Success;
}

void Job::freeQueuePolicyResources(JobPointer job)
{
    for (int index = 0; index < d->queuePolicies.size(); ++index) {
        d->queuePolicies.at(index)->free(job);
    }
}

void Job::defaultBegin(JobPointer, Thread *)
{
}

void Job::defaultEnd(JobPointer job, Thread *)
{
    freeQueuePolicyResources(job);
}

void Job::aboutToBeQueued(QueueAPI *api)
{
    QMutexLocker l(mutex()); Q_UNUSED(l);
    aboutToBeQueued_locked(api);
}

void Job::aboutToBeQueued_locked(QueueAPI *)
{
}

void Job::aboutToBeDequeued(QueueAPI *api)
{
    QMutexLocker l(mutex()); Q_UNUSED(l);
    aboutToBeDequeued_locked(api);
}

void Job::aboutToBeDequeued_locked(QueueAPI *)
{
}

void Job::assignQueuePolicy(QueuePolicy *policy)
{
    if (! d->queuePolicies.contains(policy)) {
        d->queuePolicies.append(policy);
    }
}

void Job::removeQueuePolicy(QueuePolicy *policy)
{
    int index = d->queuePolicies.indexOf(policy);
    if (index != -1) {
        d->queuePolicies.removeAt(index);
    }
}

QList<QueuePolicy *> Job::queuePolicies() const
{
    return d->queuePolicies;
}

bool Job::isFinished() const
{
    const Status s = status();
    return s == Status_Success || s == Status_Failed || s == Status_Aborted;
}

QMutex *Job::mutex() const
{
    return &d->mutex;
}

}

#include "managedjobpointer.h"
<|endoftext|>


<commit_before>#include "keys.hh"

#include <unordered_map>

namespace Kakoune
{

static std::unordered_map<std::string, Key> keynamemap = {
    { "ret", { Key::Modifiers::None, '\n' } }
};

KeyList parse_keys(const std::string& str)
{
    KeyList result;
    for (size_t pos = 0; pos < str.length(); ++pos)
    {
        if (str[pos] == '<')
        {
            size_t end_pos = pos;
            while (end_pos < str.length() and str[end_pos] != '>')
                ++end_pos;

            if (end_pos < str.length())
            {
                std::string keyname = str.substr(pos+1, end_pos - pos - 1);
                auto it = keynamemap.find(keyname);
                if (it != keynamemap.end())
                {
                    result.push_back(it->second);
                    pos = end_pos;
                    continue;
                }
            }
        }
        result.push_back({Key::Modifiers::None, str[pos]});
    }
    return result;
}

}
<commit_msg>make parse_keys handle <c-*> and <a-*> keys.<commit_after>#include "keys.hh"

#include <unordered_map>

namespace Kakoune
{

static std::unordered_map<std::string, char> keynamemap = {
    { "ret", '\n' },
    { "space", ' ' },
    { "esc", 27 }
};

KeyList parse_keys(const std::string& str)
{
    KeyList result;
    for (size_t pos = 0; pos < str.length(); ++pos)
    {
        if (str[pos] == '<')
        {
            size_t end_pos = pos;
            while (end_pos < str.length() and str[end_pos] != '>')
                ++end_pos;

            if (end_pos < str.length())
            {
                Key::Modifiers modifier = Key::Modifiers::None;

                std::string keyname = str.substr(pos+1, end_pos - pos - 1);
                if (keyname.length() > 2)
                {
                    if (tolower(keyname[0]) == 'c' and keyname[1] == '-')
                    {
                        modifier = Key::Modifiers::Control;
                        keyname = keyname.substr(2);
                    }
                    if (tolower(keyname[0]) == 'a' and keyname[1] == '-')
                    {
                        modifier = Key::Modifiers::Control;
                        keyname = keyname.substr(2);
                    }
                }
                if (keyname.length() == 1)
                {
                    result.push_back(Key{ modifier, keyname[0] });
                    pos = end_pos;
                    continue;
                }
                auto it = keynamemap.find(keyname);
                if (it != keynamemap.end())
                {
                    result.push_back(Key{ modifier, it->second });
                    pos = end_pos;
                    continue;
                }
            }
        }
        result.push_back({Key::Modifiers::None, str[pos]});
    }
    return result;
}

}
<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "dparse.h"
#include "helper.hh"
#include <getopt.h>

extern "C" {
extern D_ParserTables parser_tables_lang;
};

void print_usage()
{
  std::printf(
    "Usage: lang [options] inputfile\n"
    "Options:\n"
    "    -h     print usage\n"
    "    -o     output to a file (defaults to stdout)\n"
    );
}

extern std::string result;

int main(int argc,char** argv) {
  int c;
  FILE* outputfile=stdout;
  static struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "ho:", long_opts, NULL)) != -1) {
    switch (c)
      {
      case 'o':
	outputfile=fopen(optarg,"w");
	if (!outputfile) {
	  std::printf("Can't open output file \"%s\"\n",optarg);
	  return 1;
	}
	break;
      case 'h':
	print_usage();
	return 0;
      default:
	return 2;
      }
  }

  if (optind == argc) {
    print_usage();
    return -1;
  }

  char *s;
  D_Parser *p = new_D_Parser(&parser_tables_lang, 512);

  s=readfile(argv[optind]);
  dparse(p,s,std::strlen(s));

  fprintf(outputfile,"%s",result.c_str());

  free_D_Parser(p);
  free(s);
  return 0;
}
<commit_msg>Add -c to compile the .lang as dynamic library Add -b to let user to define the compile command<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "dparse.h"
#include "helper.hh"
#include <getopt.h>
#include <glib.h>
#include <errno.h>

extern "C" {
extern D_ParserTables parser_tables_lang;
};

void print_usage()
{
  std::printf(
    "Usage: lang [options] inputfile\n"
    "Options:\n"
    "    -h     print usage\n"
    "    -o     output to a file (defaults to stdout)\n"
    "    -c     compile (needs to have output file)\n"
    );
}

extern std::string result;

std::string compile_command("g++ -fPIC -shared -x c++  - -I /usr/include/fmbt -o ");

int main(int argc,char** argv) {
  int c;
  bool lib=false;
  FILE* outputfile=stdout;
  static struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "b:hco:", long_opts, NULL)) != -1) {
    switch (c)
      {
      case 'b':
	compile_command=optarg;
	compile_command+=" ";
	break;
      case 'c':
	lib=true;
	break;
      case 'o':
	outputfile=fopen(optarg,"w");
	compile_command=compile_command+optarg;
	if (!outputfile) {
	  std::printf("Can't open output file \"%s\"\n",optarg);
	  return 1;
	}
	break;
      case 'h':
	print_usage();
	return 0;
      default:
	return 2;
      }
  }

  if (optind == argc || outputfile==stdout) {
    print_usage();
    return -1;
  }

  char *s;
  D_Parser *p = new_D_Parser(&parser_tables_lang, 512);

  s=readfile(argv[optind]);
  dparse(p,s,std::strlen(s));
  if (lib) {
    int _stdin; //,_stdout,_stder;
    GPid pid;
    int argc;
    gchar **argv=(gchar**)malloc(42*sizeof(gchar*));
    GError *gerr=NULL;

    g_shell_parse_argv(compile_command.c_str(),
		       &argc,&argv,&gerr);

    g_spawn_async_with_pipes(NULL,argv,NULL,G_SPAWN_SEARCH_PATH,NULL,&pid,NULL,&_stdin,NULL,NULL,&gerr);

    int pos=0;
    int wrote=0;
    do {
      wrote=TEMP_FAILURE_RETRY(write(_stdin,result.c_str()+pos,result.length()-pos));
      pos+=wrote;
    } while (wrote>0 && pos<result.length());
  } else {
    fprintf(outputfile,"%s",result.c_str());
  }

  free_D_Parser(p);
  free(s);
  return 0;
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2017 Tuukka Norri
 This code is licensed under MIT license (see LICENSE for details).
 */

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <vcf2multialign/generate_haplotypes.hh>

#ifdef __linux__
#include <pthread_workqueue.h>
#endif

#include "cmdline.h"

namespace v2m	= vcf2multialign;

int main(int argc, char **argv)
{
	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		exit(EXIT_FAILURE);

	if (args_info.chunk_size_arg <= 0)
	{
		std::cerr << "Chunk size must be positive." << std::endl;
		exit(EXIT_FAILURE);
	}

	std::ios_base::sync_with_stdio(false);
	std::cin.tie(nullptr);

	// libdispatch on macOS does not need pthread_workqueue.
#ifdef __linux__
	pthread_workqueue_init_np();
#endif

	v2m::generate_haplotypes(
		args_info.reference_arg,
		args_info.variants_arg,
		args_info.output_reference_arg,
		args_info.report_file_arg,
		args_info.null_allele_seq_arg,
		args_info.chunk_size_arg,
		args_info.overwrite_flag,
		!args_info.no_check_ref_flag
	);

	// Not reached b.c. pthread_exit() is eventually called in generate_haplotypes().
	return EXIT_SUCCESS;
}
<commit_msg>Add comments<commit_after>/*
 Copyright (c) 2017 Tuukka Norri
 This code is licensed under MIT license (see LICENSE for details).
 */

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <vcf2multialign/generate_haplotypes.hh>

#ifdef __linux__
#include <pthread_workqueue.h>
#endif

#include "cmdline.h"

namespace v2m	= vcf2multialign;

int main(int argc, char **argv)
{
	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		exit(EXIT_FAILURE);

	if (args_info.chunk_size_arg <= 0)
	{
		std::cerr << "Chunk size must be positive." << std::endl;
		exit(EXIT_FAILURE);
	}

	std::ios_base::sync_with_stdio(false);	// Don't use C style IO after calling cmdline_parser.
	std::cin.tie(nullptr);					// We don't require any input from the user.

	// libdispatch on macOS does not need pthread_workqueue.
#ifdef __linux__
	pthread_workqueue_init_np();
#endif

	v2m::generate_haplotypes(
		args_info.reference_arg,
		args_info.variants_arg,
		args_info.output_reference_arg,
		args_info.report_file_arg,
		args_info.null_allele_seq_arg,
		args_info.chunk_size_arg,
		args_info.overwrite_flag,
		!args_info.no_check_ref_flag
	);

	// Not reached b.c. pthread_exit() is eventually called in generate_haplotypes().
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <locale>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>  // NOLINT
#include "config.h"
#include "cmdline.h"
#include "ast.h"
#include "ast-serializer.h"
#include "codegen.h"
#include "parser.h"

int main(int argc, char **argv) {
  std::locale::global(std::locale(""));

  iv::cmdline::Parser cmd("iv");

  cmd.Add("help",
          "help",
          'h', "print this message");
  cmd.Add("version",
          "version",
          'v', "print the version");
  cmd.Add("warning",
          "",
          'W', "set warning level 0 - 2", false, 0, iv::cmdline::range(0, 2));
  cmd.Add("ast",
          "ast",
          0, "print ast");
  cmd.Add("copyright",
          "copyright",
          0,   "print the copyright");
  cmd.set_footer("[program_file] [arguments]");

  bool cmd_parse_success = cmd.Parse(argc, argv);
  if (!cmd_parse_success) {
    std::cerr << cmd.error() << std::endl << cmd.usage();
    return EXIT_FAILURE;
  }

  if (argc == 1 || cmd.Exist("help")) {
    std::cout << cmd.usage();
    return EXIT_SUCCESS;
  }

  if (cmd.Exist("version")) {
    printf("iv %s (compiled %s %s)\n", IV_VERSION, __DATE__, __TIME__);
    return EXIT_SUCCESS;
  }

  if (cmd.Exist("copyright")) {
    printf("iv - Copyright (C) 2010 %s\n", IV_DEVELOPER);
    return EXIT_SUCCESS;
  }

  const std::vector<std::string>& rest = cmd.rest();
  if (!rest.empty()) {
    std::string str;
    const char* filename = rest[0].c_str();
    if (std::FILE* fp = std::fopen(filename, "r")) {
      char buf[1024];
      while (std::size_t len = std::fread(buf, 1, sizeof(buf), fp)) {
        str.append(buf, buf+len);
      }
      std::fclose(fp);
    } else {
      std::string err("iv can't open \"");
      err.append(filename);
      err.append("\"");
      std::perror(err.c_str());
      return EXIT_FAILURE;
    }

    iv::core::Source src(str);
    iv::core::Parser parser(src);
    iv::core::FunctionLiteral* global = parser.ParseProgram();

    if (!global) {
      std::perror(parser.error().c_str());
      return EXIT_FAILURE;
    }

    if (cmd.Exist("ast")) {
      iv::core::AstSerializer ser;
      global->Accept(&ser);
      std::cout << ser << std::endl;
    } else {
      iv::core::CodeGenerator gen;
      global->Accept(&gen);
      std::cout << gen << std::endl;
    }
  } else {
    std::cout << cmd.usage();
    return EXIT_FAILURE;
  }
  return 0;
}
<commit_msg>remove old main.cc<commit_after><|endoftext|>


<commit_before>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 *
 * WvDial configuration utility.  Generates a basic wvdial.conf file.
 */
#include "wvmodemscan.h"
#include "wvfile.h"
#include "wvconf.h"
#include <ctype.h>

void check_ppp_options()
{
    WvFile file("/etc/ppp/options", O_RDONLY);
    char *line;

    while ((line = file.getline(0)) != NULL)
    {
	line = trim_string(line);

	// comments and blank lines are ignored
	if (line[0] == '#'  ||  !line[0])
	    continue;

	// IP addresses are allowed
	if (strchr(line, '.') || strchr(line, ':'))
	    continue;

	// but baud rates and tty names are not!
	// a 'connect' line is usually bad too.
	if (isdigit(line[0])
	    || !strncmp(line, "/dev", 4)
	    || !strncmp(line, "tty",  3)
	    || !strncmp(line, "cua",  3)
	    || !strncmp(line, "connect", 7))
	{
	    wvcon->print("\n*** WARNING!  Line \"%s\"\n"
		"   in /etc/ppp/options may conflict with wvdial!\n\n", line);
	}
    }
}

int main(int argc, char **argv)
{
#if DEBUG
    free(malloc(1));    // for electric fence
#endif

    if (argc != 2 || argv[1][0]=='-')
    {
	wvcon->print("Usage: %s <configfile-name>\n"
		"\t(create/update a wvdial.conf file automatically)\n",
		argv[0]);
	return 1;
    }

    wvcon->print("Scanning your serial ports for a modem.\n\n");

    WvModemScanList l;
    while (!l.isdone())
	l.execute();

    if (l.count() < 1)
    {
	wvcon->print("\n\n"
	  "Sorry, no modem was detected!  "
	    "Is it in use by another program?\n"
	  "Did you configure it properly with setserial?\n\n"

	  "Please read the FAQ at http://open.nit.ca/wvdial/\n\n"

	  "If you still have problems, send mail to "
	    "wvdial-list@lists.nit.ca.\n");
	return 1;
    }

    WvModemScanList::Iter i(l);

    i.rewind(); i.next();
    WvModemScan &m = *i;
    WvString fn = m.filename(), init = m.initstr();

    wvcon->print("\nFound %s on %s",
        m.is_isdn() ? "an ISDN TA" :
        strncmp("/dev/ttyACM",fn,11) ? "a modem" : "an USB modem", (const char *)fn);
    if (m.use_modem_link) {
        wvcon->print(", using link /dev/modem in config.\n");
        fn = "/dev/modem";
    } else {
        wvcon->print(".\n");
    }
    WvConf cfg(argv[1],660); // Create it read/write owner and group only
    static char s[]="Dialer Defaults";
    cfg.set(s, "Modem", fn);
    cfg.setint(s, "Baud", m.maxbaud());
    cfg.set(s, "Init1", m.is_isdn() ? "AT&F" : "ATZ");
    cfg.set(s, "Init2", init);
    cfg.set(s, "ISDN",  m.use_default_asyncmap() ? "1" : "0");
    cfg.set(s, "Modem Name",  m.modem_name ? (const char *)m.modem_name : "");
    cfg.set(s, "Modem Type",  m.is_isdn() ? "ISDN Terminal Adapter" :
            strncmp("/dev/ttyACM",fn,11) ? "Analog Modem" : "USB Modem");

    if (m.modem_name)
        wvcon->print("Config for %s written to %s.\n", (const char *)m.modem_name, argv[1]);
    else
        wvcon->print("Modem configuration written to %s.\n", argv[1]);

    // insert some entries to let people know what they need to edit
    if (!cfg.get(s, "Phone"))
	cfg.set(s, "; Phone", "<Target Phone Number>");
    if (!cfg.get(s, "Username"))
	cfg.set(s, "; Username", "<Your Login Name>");
    if (!cfg.get(s, "Password"))
	cfg.set(s, "; Password", "<Your Password>");

    check_ppp_options();

    return 0;
}
<commit_msg>Fix a bug in wvdialconf that tried setting the mode to 660 decimal, instead of octal. How the HELL did this EVER work???<commit_after>/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 *
 * WvDial configuration utility.  Generates a basic wvdial.conf file.
 */
#include "wvmodemscan.h"
#include "wvfile.h"
#include "wvconf.h"
#include <ctype.h>

void check_ppp_options()
{
    WvFile file("/etc/ppp/options", O_RDONLY);
    char *line;

    while ((line = file.getline(0)) != NULL)
    {
	line = trim_string(line);

	// comments and blank lines are ignored
	if (line[0] == '#'  ||  !line[0])
	    continue;

	// IP addresses are allowed
	if (strchr(line, '.') || strchr(line, ':'))
	    continue;

	// but baud rates and tty names are not!
	// a 'connect' line is usually bad too.
	if (isdigit(line[0])
	    || !strncmp(line, "/dev", 4)
	    || !strncmp(line, "tty",  3)
	    || !strncmp(line, "cua",  3)
	    || !strncmp(line, "connect", 7))
	{
	    wvcon->print("\n*** WARNING!  Line \"%s\"\n"
		"   in /etc/ppp/options may conflict with wvdial!\n\n", line);
	}
    }
}

int main(int argc, char **argv)
{
#if DEBUG
    free(malloc(1));    // for electric fence
#endif

    if (argc != 2 || argv[1][0]=='-')
    {
	wvcon->print("Usage: %s <configfile-name>\n"
		"\t(create/update a wvdial.conf file automatically)\n",
		argv[0]);
	return 1;
    }

    wvcon->print("Scanning your serial ports for a modem.\n\n");

    WvModemScanList l;
    while (!l.isdone())
	l.execute();

    if (l.count() < 1)
    {
	wvcon->print("\n\n"
	  "Sorry, no modem was detected!  "
	    "Is it in use by another program?\n"
	  "Did you configure it properly with setserial?\n\n"

	  "Please read the FAQ at http://open.nit.ca/wvdial/\n\n"

	  "If you still have problems, send mail to "
	    "wvdial-list@lists.nit.ca.\n");
	return 1;
    }

    WvModemScanList::Iter i(l);

    i.rewind(); i.next();
    WvModemScan &m = *i;
    WvString fn = m.filename(), init = m.initstr();

    wvcon->print("\nFound %s on %s",
        m.is_isdn() ? "an ISDN TA" :
        strncmp("/dev/ttyACM",fn,11) ? "a modem" : "an USB modem", (const char *)fn);
    if (m.use_modem_link) {
        wvcon->print(", using link /dev/modem in config.\n");
        fn = "/dev/modem";
    } else {
        wvcon->print(".\n");
    }
    WvConf cfg(argv[1],0660); // Create it read/write owner and group only
    static char s[]="Dialer Defaults";
    cfg.set(s, "Modem", fn);
    cfg.setint(s, "Baud", m.maxbaud());
    cfg.set(s, "Init1", m.is_isdn() ? "AT&F" : "ATZ");
    cfg.set(s, "Init2", init);
    cfg.set(s, "ISDN",  m.use_default_asyncmap() ? "1" : "0");
    cfg.set(s, "Modem Name",  m.modem_name ? (const char *)m.modem_name : "");
    cfg.set(s, "Modem Type",  m.is_isdn() ? "ISDN Terminal Adapter" :
            strncmp("/dev/ttyACM",fn,11) ? "Analog Modem" : "USB Modem");

    if (m.modem_name)
        wvcon->print("Config for %s written to %s.\n", (const char *)m.modem_name, argv[1]);
    else
        wvcon->print("Modem configuration written to %s.\n", argv[1]);

    // insert some entries to let people know what they need to edit
    if (!cfg.get(s, "Phone"))
	cfg.set(s, "; Phone", "<Target Phone Number>");
    if (!cfg.get(s, "Username"))
	cfg.set(s, "; Username", "<Your Login Name>");
    if (!cfg.get(s, "Password"))
	cfg.set(s, "; Password", "<Your Password>");

    check_ppp_options();

    return 0;
}
<|endoftext|>


<commit_before>/**
 * studentCollection_class.cpp
 *
 * Author: Patrick Rummage <patrickbrummage@gmail.com>
 *
 * Objective:
 *
 */
#include <iostream>
using std::cin;
using std::cout;

struct studentRecord {
    int studentID;
    int grade;
    char[] Name;
};

class studentCollection {
    private:
        struct studentNode {
            studentRecord studentData;
            studentNode* next;
        };

    public:
        studentCollection();
        ~studentCollection();
        void addRecord(studentRecord newStudent);
        studentRecord recordWithNumber(int idNum);
        void removeRecord(int idNum);

    private:
        studentNode* _listHead;
        void deleteList(studentList &listPtr);
};

studentCollection::studentCollection() {
    _listHead = NULL;
}

void studentCollection::addrecord(studentRecord newStudent) {
    studentNode* newNode = new studentNode;
    newNode->studentData = newStudent;
    newNode->next = _listHead; // previous first item
    _listHead = newNode;
}

studentRecord studentCollection::recordWithNumber(int idNum) {
    studentNode* loopPtr = _listHead;
    while (loopPtr != NULL && loopPtr->studentData.student.studentID != idNum) {
        loopPtr = loopPtr->next;
    }
    if (loopPtr == NULL) {
        studentRecord dummyRecord(-1,-1,"");
        return dummyRecord;
    } else {
        return loopPtr->studentData;
    }
}

void studentCollection::removeRecord(int idNum) {
    studentNode* loopPtr = _listHead;
    studentNode* previous = NULL;
    while (loopPtr != NULL && loopPtr->studentData.studentID != idNum) {
        previous = loopPtr;
        loopPtr = loopPtr->next;
    }
    if (loopPtr == NULL) { // Not found
        return;
    }
    if (previous == NULL) { // Removing first node
        _listHead = _listHead->next;
    } else { // Join nodes before and after one to be deleted
        previous->next = loopPtr->next;
    }
    delete loopPtr;
}

void studentCollection::deleteList(studentList &listPtr) {
    while (listPtr != NULL) {
        studentNode* temp = listPtr;
        listPtr = listPtr->next;
        delete temp;
    }
}

studentCollection::~studentCollection() {
    deleteList(_listHead);
}
<commit_msg>added copy operator and main function<commit_after>/**
 * studentCollection_class.cpp
 *
 * Author: Patrick Rummage <patrickbrummage@gmail.com>
 *
 * Objective:
 *
 */
#include <iostream>
using std::cin;
using std::cout;

struct studentRecord {
    int studentID;
    int grade;
    char* name;
};

class studentCollection {
    private:
        struct studentNode {
            studentRecord studentData;
            studentNode* next;
        };

    public:
        studentCollection();
        ~studentCollection();
        void addRecord(studentRecord newStudent);
        studentRecord recordWithNumber(int idNum);
        void removeRecord(int idNum);
        studentNode* copiedList(const studentNode* original);
        studentCollection& operator=(const studentCollection& rhs);

    private:
        studentNode* _listHead;
        void deleteList(studentNode* &listPtr);
};

studentCollection::studentCollection() {
    _listHead = NULL;
}

void studentCollection::addRecord(studentRecord newStudent) {
    studentNode* newNode = new studentNode;
    newNode->studentData = newStudent;
    newNode->next = _listHead; // previous first item
    _listHead = newNode;
}

studentRecord studentCollection::recordWithNumber(int idNum) {
    studentNode* loopPtr = _listHead;
    while (loopPtr != NULL && loopPtr->studentData.studentID != idNum) {
        loopPtr = loopPtr->next;
    }
    if (loopPtr == NULL) {
        studentRecord dummyRecord{-1,-1,"VOID"};
        return dummyRecord;
    } else {
        return loopPtr->studentData;
    }
}

void studentCollection::removeRecord(int idNum) {
    studentNode* loopPtr = _listHead;
    studentNode* previous = NULL;
    while (loopPtr != NULL && loopPtr->studentData.studentID != idNum) {
        previous = loopPtr;
        loopPtr = loopPtr->next;
    }
    if (loopPtr == NULL) { // Not found
        return;
    }
    if (previous == NULL) { // Removing first node
        _listHead = _listHead->next;
    } else { // Join nodes before and after one to be deleted
        previous->next = loopPtr->next;
    }
    delete loopPtr;
}

void studentCollection::deleteList(studentNode* &listPtr) {
    while (listPtr != NULL) {
        studentNode* temp = listPtr;
        listPtr = listPtr->next;
        delete temp;
    }
}

studentCollection::studentNode*
studentCollection::copiedList(const studentNode* original) {
    if (original == NULL) {
        return NULL;
    }
    studentNode* newList = new studentNode;
    newList->studentData = original->studentData;
    studentNode* oldLoopPtr = original->next;
    studentNode* newLoopPtr = newList;
    while(oldLoopPtr != NULL) {
        newLoopPtr->next = new studentNode;
        newLoopPtr = newLoopPtr->next;
        newLoopPtr->studentData = oldLoopPtr->studentData;
        oldLoopPtr = oldLoopPtr->next;
    }
    newLoopPtr->next = NULL;
    return newList;
}

studentCollection::~studentCollection() {
    deleteList(_listHead);
}

studentCollection& studentCollection::operator=(const studentCollection& rhs) {
    if (this != &rhs) {
        deleteList(_listHead);
        _listHead = copiedList(rhs._listHead);
    }
    return *this;
}

int main (int argc, char* argv[]) {

    return 0;
}
<|endoftext|>