<commit_before>#include <algorithm>
#include <sstream>
#include <string>

#include "Module/Extractor/Polar/Extractor_polar.hpp"
#include "Tools/Exception/exception.hpp"
#include "Tools/Noise/Sigma.hpp"
#include "Tools/Noise/Event_probability.hpp"
#include "Factory/Module/Encoder/Encoder.hpp"
#include "Factory/Module/Puncturer/Puncturer.hpp"
#include "Tools/Codec/Polar_MK/Codec_polar_MK.hpp"

using namespace aff3ct;
using namespace aff3ct::tools;

template <typename B, typename Q>
Codec_polar_MK<B,Q>
::Codec_polar_MK(const factory::Polar_code              &pc_params,
                 const factory::Frozenbits_generator_MK &fb_params,
                 const factory::Encoder_polar_MK        &enc_params,
                 const factory::Decoder_polar_MK        &dec_params,
                 const module::CRC<B>                   *crc)
: Codec_SIHO<B,Q>(enc_params.K, enc_params.N_cw, enc_params.N_cw, enc_params.n_frames),
  adaptive_fb(fb_params.noise == -1.f),
  frozen_bits(new std::vector<bool>(fb_params.N_cw, true)),
  fb_decoder(nullptr),
  fb_encoder(nullptr),
  fb_extractor(nullptr)
{
	// ----------------------------------------------------------------------------------------------------- exceptions
	if (enc_params.K != dec_params.K)
	{
		std::stringstream message;
		message << "'enc_params.K' has to be equal to 'dec_params.K' ('enc_params.K' = " << enc_params.K
		        << ", 'dec_params.K' = " << dec_params.K << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	if (enc_params.N_cw != dec_params.N_cw)
	{
		std::stringstream message;
		message << "'enc_params.N_cw' has to be equal to 'dec_params.N_cw' ('enc_params.N_cw' = " << enc_params.N_cw
		        << ", 'dec_params.N_cw' = " << dec_params.N_cw << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	if (enc_params.n_frames != dec_params.n_frames)
	{
		std::stringstream message;
		message << "'enc_params.n_frames' has to be equal to 'dec_params.n_frames' ('enc_params.n_frames' = "
		        << enc_params.n_frames << ", 'dec_params.n_frames' = " << dec_params.n_frames << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	// ---------------------------------------------------------------------------------------------------------- tools
	// build the polar code
	code.reset(pc_params.build());

	// build the frozen bits generator
	fb_generator.reset(fb_params.build(*code.get()));

	// ---------------------------------------------------------------------------------------------------- allocations
	factory::Puncturer pct_params;
	pct_params.type     = "NO";
	pct_params.K        = enc_params.K;
	pct_params.N        = enc_params.N_cw;
	pct_params.N_cw     = enc_params.N_cw;
	pct_params.n_frames = enc_params.n_frames;

	this->set_puncturer(pct_params.build<B,Q>());

	std::fill(frozen_bits->begin(), frozen_bits->begin() + this->K, false);

	try
	{
		this->set_encoder(enc_params.build<B>(*code.get(), *frozen_bits));
		fb_encoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_encoder());
	}
	catch (tools::cannot_allocate const&)
	{
		this->set_encoder(static_cast<const factory::Encoder*>(&enc_params)->build<B>());
	}

	this->set_decoder_siho(dec_params.build<B,Q>(*code.get(), *frozen_bits, crc, &this->get_encoder()));
	this->fb_decoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_decoder_siho());

	this->set_extractor(new module::Extractor_polar<B,Q>(enc_params.K,
	                                                     enc_params.N_cw,
	                                                     *frozen_bits,
	                                                     enc_params.n_frames));
	fb_extractor = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_extractor());

	// ------------------------------------------------------------------------------------------------- frozen bit gen
	if (!adaptive_fb)
	{
		if (fb_params.type == "BEC")
		{
			auto ep = tools::Event_probability<float>(fb_params.noise);
			fb_generator->set_noise(ep);
		}
		else /* type = GA, TV or FILE */
		{
			auto sigma = tools::Sigma<float>(fb_params.noise);
			fb_generator->set_noise(sigma);
		}

		fb_generator->generate(*frozen_bits);
		this->notify_frozenbits_update();
	}
}

template <typename B, typename Q>
Codec_polar_MK<B,Q>* Codec_polar_MK<B,Q>
::clone() const
{
	auto t = new Codec_polar_MK(*this);
	t->deep_copy(*this);
	return t;
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::deep_copy(const Codec_polar_MK<B,Q> &t)
{
	Codec_SIHO<B,Q>::deep_copy(t);
	if (t.fb_encoder != nullptr)
		this->fb_encoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_encoder());
	if (t.fb_decoder != nullptr)
		this->fb_decoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_decoder_siho());
	if (t.fb_extractor != nullptr)
		this->fb_extractor = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_extractor());
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::notify_frozenbits_update()
{
	if (this->fb_decoder)
		this->fb_decoder->notify_noise_update();
	if (this->fb_encoder)
		this->fb_encoder->notify_noise_update();
	if (this->fb_extractor)
		this->fb_extractor->notify_noise_update();
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::notify_noise_update()
{
	Codec<B,Q>::notify_noise_update();
	if (this->adaptive_fb)
	{
		this->fb_generator->set_noise(*this->noise);
		this->fb_generator->generate(*this->frozen_bits);
		this->notify_frozenbits_update();
	}
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::check_noise()
{
	Codec<B,Q>::check_noise();
	if (!this->noise->is_of_type(Noise_type::SIGMA) && !this->noise->is_of_type(Noise_type::EP))
	{
		std::stringstream message;
		message << "Incompatible noise type, expected noise types are SIGMA or EP ('noise->get_type()' = "
		        << Noise<>::type_to_str(this->noise->get_type()) << ").";
		throw invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}
}

template <typename B, typename Q>
const std::vector<bool>& Codec_polar_MK<B,Q>
::get_frozen_bits() const
{
	return *this->frozen_bits;
}

template <typename B, typename Q>
bool Codec_polar_MK<B,Q>
::is_adaptive_frozen_bits() const
{
	return this->adaptive_fb;
}

template <typename B, typename Q>
const Polar_code& Codec_polar_MK<B,Q>
::get_code() const
{
	return *this->code;
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef AFF3CT_MULTI_PREC
template class aff3ct::tools::Codec_polar_MK<B_8,Q_8>;
template class aff3ct::tools::Codec_polar_MK<B_16,Q_16>;
template class aff3ct::tools::Codec_polar_MK<B_32,Q_32>;
template class aff3ct::tools::Codec_polar_MK<B_64,Q_64>;
#else
template class aff3ct::tools::Codec_polar_MK<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<commit_msg>Add missing getter in MK Polar codec.<commit_after>#include <algorithm>
#include <sstream>
#include <string>

#include "Module/Extractor/Polar/Extractor_polar.hpp"
#include "Tools/Exception/exception.hpp"
#include "Tools/Noise/Sigma.hpp"
#include "Tools/Noise/Event_probability.hpp"
#include "Factory/Module/Encoder/Encoder.hpp"
#include "Factory/Module/Puncturer/Puncturer.hpp"
#include "Tools/Codec/Polar_MK/Codec_polar_MK.hpp"

using namespace aff3ct;
using namespace aff3ct::tools;

template <typename B, typename Q>
Codec_polar_MK<B,Q>
::Codec_polar_MK(const factory::Polar_code              &pc_params,
                 const factory::Frozenbits_generator_MK &fb_params,
                 const factory::Encoder_polar_MK        &enc_params,
                 const factory::Decoder_polar_MK        &dec_params,
                 const module::CRC<B>                   *crc)
: Codec_SIHO<B,Q>(enc_params.K, enc_params.N_cw, enc_params.N_cw, enc_params.n_frames),
  adaptive_fb(fb_params.noise == -1.f),
  frozen_bits(new std::vector<bool>(fb_params.N_cw, true)),
  fb_decoder(nullptr),
  fb_encoder(nullptr),
  fb_extractor(nullptr)
{
	// ----------------------------------------------------------------------------------------------------- exceptions
	if (enc_params.K != dec_params.K)
	{
		std::stringstream message;
		message << "'enc_params.K' has to be equal to 'dec_params.K' ('enc_params.K' = " << enc_params.K
		        << ", 'dec_params.K' = " << dec_params.K << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	if (enc_params.N_cw != dec_params.N_cw)
	{
		std::stringstream message;
		message << "'enc_params.N_cw' has to be equal to 'dec_params.N_cw' ('enc_params.N_cw' = " << enc_params.N_cw
		        << ", 'dec_params.N_cw' = " << dec_params.N_cw << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	if (enc_params.n_frames != dec_params.n_frames)
	{
		std::stringstream message;
		message << "'enc_params.n_frames' has to be equal to 'dec_params.n_frames' ('enc_params.n_frames' = "
		        << enc_params.n_frames << ", 'dec_params.n_frames' = " << dec_params.n_frames << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	// ---------------------------------------------------------------------------------------------------------- tools
	// build the polar code
	code.reset(pc_params.build());

	// build the frozen bits generator
	fb_generator.reset(fb_params.build(*code.get()));

	// ---------------------------------------------------------------------------------------------------- allocations
	factory::Puncturer pct_params;
	pct_params.type     = "NO";
	pct_params.K        = enc_params.K;
	pct_params.N        = enc_params.N_cw;
	pct_params.N_cw     = enc_params.N_cw;
	pct_params.n_frames = enc_params.n_frames;

	this->set_puncturer(pct_params.build<B,Q>());

	std::fill(frozen_bits->begin(), frozen_bits->begin() + this->K, false);

	try
	{
		this->set_encoder(enc_params.build<B>(*code.get(), *frozen_bits));
		fb_encoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_encoder());
	}
	catch (tools::cannot_allocate const&)
	{
		this->set_encoder(static_cast<const factory::Encoder*>(&enc_params)->build<B>());
	}

	this->set_decoder_siho(dec_params.build<B,Q>(*code.get(), *frozen_bits, crc, &this->get_encoder()));
	this->fb_decoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_decoder_siho());

	this->set_extractor(new module::Extractor_polar<B,Q>(enc_params.K,
	                                                     enc_params.N_cw,
	                                                     *frozen_bits,
	                                                     enc_params.n_frames));
	fb_extractor = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_extractor());

	// ------------------------------------------------------------------------------------------------- frozen bit gen
	if (!adaptive_fb)
	{
		if (fb_params.type == "BEC")
		{
			auto ep = tools::Event_probability<float>(fb_params.noise);
			fb_generator->set_noise(ep);
		}
		else /* type = GA, TV or FILE */
		{
			auto sigma = tools::Sigma<float>(fb_params.noise);
			fb_generator->set_noise(sigma);
		}

		fb_generator->generate(*frozen_bits);
		this->notify_frozenbits_update();
	}
}

template <typename B, typename Q>
Codec_polar_MK<B,Q>* Codec_polar_MK<B,Q>
::clone() const
{
	auto t = new Codec_polar_MK(*this);
	t->deep_copy(*this);
	return t;
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::deep_copy(const Codec_polar_MK<B,Q> &t)
{
	Codec_SIHO<B,Q>::deep_copy(t);
	if (t.fb_encoder != nullptr)
		this->fb_encoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_encoder());
	if (t.fb_decoder != nullptr)
		this->fb_decoder = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_decoder_siho());
	if (t.fb_extractor != nullptr)
		this->fb_extractor = dynamic_cast<Interface_notify_frozenbits_update*>(&this->get_extractor());
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::notify_frozenbits_update()
{
	if (this->fb_decoder)
		this->fb_decoder->notify_noise_update();
	if (this->fb_encoder)
		this->fb_encoder->notify_noise_update();
	if (this->fb_extractor)
		this->fb_extractor->notify_noise_update();
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::notify_noise_update()
{
	Codec<B,Q>::notify_noise_update();
	if (this->adaptive_fb)
	{
		this->fb_generator->set_noise(*this->noise);
		this->fb_generator->generate(*this->frozen_bits);
		this->notify_frozenbits_update();
	}
}

template <typename B, typename Q>
void Codec_polar_MK<B,Q>
::check_noise()
{
	Codec<B,Q>::check_noise();
	if (!this->noise->is_of_type(Noise_type::SIGMA) && !this->noise->is_of_type(Noise_type::EP))
	{
		std::stringstream message;
		message << "Incompatible noise type, expected noise types are SIGMA or EP ('noise->get_type()' = "
		        << Noise<>::type_to_str(this->noise->get_type()) << ").";
		throw invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}
}

template <typename B, typename Q>
const std::vector<bool>& Codec_polar_MK<B,Q>
::get_frozen_bits() const
{
	return *this->frozen_bits;
}

template <typename B, typename Q>
bool Codec_polar_MK<B,Q>
::is_adaptive_frozen_bits() const
{
	return this->adaptive_fb;
}

template <typename B, typename Q>
const Polar_code& Codec_polar_MK<B,Q>
::get_code() const
{
	return *this->code;
}

template <typename B, typename Q>
const Frozenbits_generator& Codec_polar_MK<B,Q>
::get_frozen_bits_generator() const
{
	if (this->fb_generator == nullptr)
	{
		std::stringstream message;
		message << "'fb_generator' can't be nullptr.";
		throw runtime_error(__FILE__, __LINE__, __func__, message.str());
	}

	return *this->fb_generator.get();
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef AFF3CT_MULTI_PREC
template class aff3ct::tools::Codec_polar_MK<B_8,Q_8>;
template class aff3ct::tools::Codec_polar_MK<B_16,Q_16>;
template class aff3ct::tools::Codec_polar_MK<B_32,Q_32>;
template class aff3ct::tools::Codec_polar_MK<B_64,Q_64>;
#else
template class aff3ct::tools::Codec_polar_MK<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<|endoftext|>


<commit_before>#ifndef __FACTOR_MASTER_H__
#define __FACTOR_MASTER_H__

#ifndef _THREAD_SAFE
#define _THREAD_SAFE
#endif

#ifndef _REENTRANT
#define _REENTRANT
#endif

#include <errno.h>

// C headers
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <stdint.h>

// C++ headers
#include <algorithm>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>

#define FACTOR_STRINGIZE_I(x) #x
#define FACTOR_STRINGIZE(x) FACTOR_STRINGIZE_I(x)

// Record compiler version
#if defined(__clang__)
#define FACTOR_COMPILER_VERSION "Clang (GCC " __VERSION__ ")"
#elif defined(__INTEL_COMPILER)
#define FACTOR_COMPILER_VERSION \
  "Intel C Compiler " FACTOR_STRINGIZE(__INTEL_COMPILER)
#elif defined(__GNUC__)
#define FACTOR_COMPILER_VERSION "GCC " __VERSION__
#elif defined(_MSC_FULL_VER)
#define FACTOR_COMPILER_VERSION \
  "Microsoft Visual C++ " FACTOR_STRINGIZE(_MSC_FULL_VER)
#else
#define FACTOR_COMPILER_VERSION "unknown"
#endif

// Record compilation time
#define FACTOR_COMPILE_TIME __TIMESTAMP__

// Detect target CPU type
#if defined(__arm__)
#define FACTOR_ARM
#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
#define FACTOR_AMD64
#define FACTOR_64
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define FACTOR_X86
#elif(defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)) && \
    (defined(__PPC64__) || defined(__64BIT__))
#define FACTOR_PPC64
#define FACTOR_PPC
#define FACTOR_64
#elif defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)
#define FACTOR_PPC32
#define FACTOR_PPC
#else
#error "Unsupported architecture"
#endif

#if defined(_MSC_VER)
#define WINDOWS
#define WINNT
#elif defined(WIN32)
#define WINDOWS
#endif

// Forward-declare this since it comes up in function prototypes
namespace factor { struct factor_vm; }

// Factor headers
#include "assert.hpp"
#include "debug.hpp"
#include "layouts.hpp"
#include "platform.hpp"
#include "utilities.hpp"
#include "primitives.hpp"
#include "errors.hpp"
#include "segments.hpp"
#include "gc_info.hpp"
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
#include "sampling_profiler.hpp"
#include "bignumint.hpp"
#include "bignum.hpp"
#include "booleans.hpp"
#include "instruction_operands.hpp"
#include "tagged.hpp"
#include "code_blocks.hpp"
#include "bump_allocator.hpp"
#include "bitwise_hacks.hpp"
#include "mark_bits.hpp"
#include "fixup.hpp"
#include "free_list.hpp"
#include "write_barrier.hpp"
#include "object_start_map.hpp"
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"
#include "code_heap.hpp"
#include "gc.hpp"
#include "float_bits.hpp"
#include "io.hpp"
#include "image.hpp"
#include "callbacks.hpp"
#include "dispatch.hpp"
#include "vm.hpp"
#include "allot.hpp"
#include "data_roots.hpp"
#include "code_roots.hpp"
#include "generic_arrays.hpp"
#include "callstack.hpp"
#include "slot_visitor.hpp"
#include "to_tenured_collector.hpp"
#include "arrays.hpp"
#include "math.hpp"
#include "byte_arrays.hpp"
#include "jit.hpp"
#include "quotations.hpp"
#include "inline_cache.hpp"
#include "mvm.hpp"
#include "factor.hpp"

#endif // __FACTOR_MASTER_H__
<commit_msg>vm: fix COMPILE-TIME to use __DATE__ and __TIME__<commit_after>#ifndef __FACTOR_MASTER_H__
#define __FACTOR_MASTER_H__

#ifndef _THREAD_SAFE
#define _THREAD_SAFE
#endif

#ifndef _REENTRANT
#define _REENTRANT
#endif

#include <errno.h>

// C headers
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <stdint.h>

// C++ headers
#include <algorithm>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>

#define FACTOR_STRINGIZE_I(x) #x
#define FACTOR_STRINGIZE(x) FACTOR_STRINGIZE_I(x)

// Record compiler version
#if defined(__clang__)
#define FACTOR_COMPILER_VERSION "Clang (GCC " __VERSION__ ")"
#elif defined(__INTEL_COMPILER)
#define FACTOR_COMPILER_VERSION \
  "Intel C Compiler " FACTOR_STRINGIZE(__INTEL_COMPILER)
#elif defined(__GNUC__)
#define FACTOR_COMPILER_VERSION "GCC " __VERSION__
#elif defined(_MSC_FULL_VER)
#define FACTOR_COMPILER_VERSION \
  "Microsoft Visual C++ " FACTOR_STRINGIZE(_MSC_FULL_VER)
#else
#define FACTOR_COMPILER_VERSION "unknown"
#endif

// Record compilation time
#define FACTOR_COMPILE_TIME __DATE__ " " __TIME__

// Detect target CPU type
#if defined(__arm__)
#define FACTOR_ARM
#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
#define FACTOR_AMD64
#define FACTOR_64
#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define FACTOR_X86
#elif(defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)) && \
    (defined(__PPC64__) || defined(__64BIT__))
#define FACTOR_PPC64
#define FACTOR_PPC
#define FACTOR_64
#elif defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC)
#define FACTOR_PPC32
#define FACTOR_PPC
#else
#error "Unsupported architecture"
#endif

#if defined(_MSC_VER)
#define WINDOWS
#define WINNT
#elif defined(WIN32)
#define WINDOWS
#endif

// Forward-declare this since it comes up in function prototypes
namespace factor { struct factor_vm; }

// Factor headers
#include "assert.hpp"
#include "debug.hpp"
#include "layouts.hpp"
#include "platform.hpp"
#include "utilities.hpp"
#include "primitives.hpp"
#include "errors.hpp"
#include "segments.hpp"
#include "gc_info.hpp"
#include "contexts.hpp"
#include "run.hpp"
#include "objects.hpp"
#include "sampling_profiler.hpp"
#include "bignumint.hpp"
#include "bignum.hpp"
#include "booleans.hpp"
#include "instruction_operands.hpp"
#include "tagged.hpp"
#include "code_blocks.hpp"
#include "bump_allocator.hpp"
#include "bitwise_hacks.hpp"
#include "mark_bits.hpp"
#include "fixup.hpp"
#include "free_list.hpp"
#include "write_barrier.hpp"
#include "object_start_map.hpp"
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"
#include "code_heap.hpp"
#include "gc.hpp"
#include "float_bits.hpp"
#include "io.hpp"
#include "image.hpp"
#include "callbacks.hpp"
#include "dispatch.hpp"
#include "vm.hpp"
#include "allot.hpp"
#include "data_roots.hpp"
#include "code_roots.hpp"
#include "generic_arrays.hpp"
#include "callstack.hpp"
#include "slot_visitor.hpp"
#include "to_tenured_collector.hpp"
#include "arrays.hpp"
#include "math.hpp"
#include "byte_arrays.hpp"
#include "jit.hpp"
#include "quotations.hpp"
#include "inline_cache.hpp"
#include "mvm.hpp"
#include "factor.hpp"

#endif // __FACTOR_MASTER_H__
<|endoftext|>


<commit_before>#include "../../include/dkm.hpp"
#include <iostream>
#include <sstream>
#include <iomanip>

int main() {
	std::vector<std::array<float, 2>> data{{1.f, 1.f}, {2.f, 2.f}, {1200.f, 1200.f}, {2.f, 2.f}};
	auto cluster_data = dkm::kmeans_lloyd(data, 2);

	std::cout << "Means:" << std::endl;
	for (const auto& mean : std::get<0>(cluster_data)) {
		std::cout << "\t(" << mean[0] << "," << mean[1] << ")" << std::endl;
	}
	std::cout << "\nCluster labels:" << std::endl;
	std::cout << "\tPoint:";
	for (const auto& point : data) {
		std::stringstream value;
		value << "(" << point[0] << "," << point[1] << ")";
		std::cout << std::setw(14) << value.str();
	}
	std::cout << std::endl;
	std::cout << "\tLabel:";
	for (const auto& label : std::get<1>(cluster_data)) {
		std::cout << std::setw(14) << label;
	}
	std::cout << std::endl;
}
<commit_msg>Fixed missing braces warning on clang.<commit_after>#include "../../include/dkm.hpp"
#include <iostream>
#include <sstream>
#include <iomanip>

#ifdef __clang__
#pragma clang diagnostic ignored "-Wmissing-braces"
#endif

int main() {
	std::vector<std::array<float, 2>> data{{1.f, 1.f}, {2.f, 2.f}, {1200.f, 1200.f}, {2.f, 2.f}};
	auto cluster_data = dkm::kmeans_lloyd(data, 2);

	std::cout << "Means:" << std::endl;
	for (const auto& mean : std::get<0>(cluster_data)) {
		std::cout << "\t(" << mean[0] << "," << mean[1] << ")" << std::endl;
	}
	std::cout << "\nCluster labels:" << std::endl;
	std::cout << "\tPoint:";
	for (const auto& point : data) {
		std::stringstream value;
		value << "(" << point[0] << "," << point[1] << ")";
		std::cout << std::setw(14) << value.str();
	}
	std::cout << std::endl;
	std::cout << "\tLabel:";
	for (const auto& label : std::get<1>(cluster_data)) {
		std::cout << std::setw(14) << label;
	}
	std::cout << std::endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Request.hxx"
#include "Stock.hxx"
#include "Client.hxx"
#include "http/ResponseHandler.hxx"
#include "lease.hxx"
#include "access_log/ChildErrorLog.hxx"
#include "stock/Item.hxx"
#include "istream/UnusedPtr.hxx"
#include "pool/pool.hxx"
#include "pool/LeakDetector.hxx"
#include "net/SocketDescriptor.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Cancellable.hxx"
#include "stopwatch.hxx"

#include <sys/socket.h>

class FcgiRequest final : Lease, Cancellable, PoolLeakDetector {
	struct pool &pool;

	StockItem *stock_item;

	ChildErrorLog log;

	CancellablePointer cancel_ptr;

public:
	FcgiRequest(struct pool &_pool, StockItem &_stock_item) noexcept
		:PoolLeakDetector(_pool),
		 pool(_pool), stock_item(&_stock_item)
	{
	}

	void Start(EventLoop &event_loop, StopwatchPtr &&stopwatch,
		   const char *site_name,
		   const char *path,
		   http_method_t method, const char *uri,
		   const char *script_name, const char *path_info,
		   const char *query_string,
		   const char *document_root,
		   const char *remote_addr,
		   StringMap &&headers, UnusedIstreamPtr body,
		   ConstBuffer<const char *> params,
		   UniqueFileDescriptor &&stderr_fd,
		   SocketDescriptor log_socket,
		   const ChildErrorLogOptions &log_options,
		   HttpResponseHandler &handler,
		   CancellablePointer &caller_cancel_ptr) {
		caller_cancel_ptr = *this;

		fcgi_stock_item_set_site(*stock_item, site_name);
		fcgi_stock_item_set_uri(*stock_item, uri);

		if (!stderr_fd.IsDefined())
			stderr_fd = fcgi_stock_item_get_stderr(*stock_item);

		if (log_socket.IsDefined() && !stderr_fd.IsDefined())
			stderr_fd = log.EnableClient(event_loop, log_socket,
						     log_options,
						     /* TODO? */ true);

		log.SetSite(site_name);

		const char *script_filename = path;

		fcgi_client_request(&pool, event_loop, std::move(stopwatch),
				    fcgi_stock_item_get(*stock_item),
				    fcgi_stock_item_get_domain(*stock_item) == AF_LOCAL
				    ? FdType::FD_SOCKET : FdType::FD_TCP,
				    *this,
				    method, uri,
				    script_filename,
				    script_name, path_info,
				    query_string,
				    document_root,
				    remote_addr,
				    std::move(headers), std::move(body),
				    params,
				    std::move(stderr_fd),
				    handler, cancel_ptr);
	}

private:
	void Destroy() noexcept {
		DeleteFromPool(pool, this);
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override {
		fcgi_stock_aborted(*stock_item);

		cancel_ptr.Cancel();
	}

	/* virtual methods from class Lease */
	void ReleaseLease(bool reuse) noexcept override {
		stock_item->Put(!reuse);
		stock_item = nullptr;

		Destroy();
	}
};

void
fcgi_request(struct pool *pool, EventLoop &event_loop,
	     FcgiStock *fcgi_stock,
	     const StopwatchPtr &parent_stopwatch,
	     const char *site_name,
	     const ChildOptions &options,
	     const char *action,
	     const char *path,
	     ConstBuffer<const char *> args,
	     unsigned parallelism,
	     http_method_t method, const char *uri,
	     const char *script_name, const char *path_info,
	     const char *query_string,
	     const char *document_root,
	     const char *remote_addr,
	     StringMap &&headers, UnusedIstreamPtr body,
	     ConstBuffer<const char *> params,
	     UniqueFileDescriptor &&stderr_fd,
	     HttpResponseHandler &handler,
	     CancellablePointer &cancel_ptr) noexcept
{
	if (action == nullptr)
		action = path;

	StopwatchPtr stopwatch(parent_stopwatch, "fcgi", action);

	StockItem *stock_item;
	try {
		stock_item = fcgi_stock_get(fcgi_stock, options,
					    action, args, parallelism);
	} catch (...) {
		stopwatch.RecordEvent("launch_error");
		body.Clear();
		handler.InvokeError(std::current_exception());
		return;
	}

	stopwatch.RecordEvent("fork");

	auto request = NewFromPool<FcgiRequest>(*pool, *pool, *stock_item);

	request->Start(event_loop, std::move(stopwatch),
		       site_name, path, method, uri,
		       script_name, path_info,
		       query_string, document_root, remote_addr,
		       std::move(headers), std::move(body),
		       params, std::move(stderr_fd),
		       fcgi_stock_get_log_socket(*fcgi_stock),
		       fcgi_stock_get_log_options(*fcgi_stock),
		       handler, cancel_ptr);
}
<commit_msg>fcgi/Request: add `noexcept`<commit_after>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Request.hxx"
#include "Stock.hxx"
#include "Client.hxx"
#include "http/ResponseHandler.hxx"
#include "lease.hxx"
#include "access_log/ChildErrorLog.hxx"
#include "stock/Item.hxx"
#include "istream/UnusedPtr.hxx"
#include "pool/pool.hxx"
#include "pool/LeakDetector.hxx"
#include "net/SocketDescriptor.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Cancellable.hxx"
#include "stopwatch.hxx"

#include <sys/socket.h>

class FcgiRequest final : Lease, Cancellable, PoolLeakDetector {
	struct pool &pool;

	StockItem *stock_item;

	ChildErrorLog log;

	CancellablePointer cancel_ptr;

public:
	FcgiRequest(struct pool &_pool, StockItem &_stock_item) noexcept
		:PoolLeakDetector(_pool),
		 pool(_pool), stock_item(&_stock_item)
	{
	}

	void Start(EventLoop &event_loop, StopwatchPtr &&stopwatch,
		   const char *site_name,
		   const char *path,
		   http_method_t method, const char *uri,
		   const char *script_name, const char *path_info,
		   const char *query_string,
		   const char *document_root,
		   const char *remote_addr,
		   StringMap &&headers, UnusedIstreamPtr body,
		   ConstBuffer<const char *> params,
		   UniqueFileDescriptor &&stderr_fd,
		   SocketDescriptor log_socket,
		   const ChildErrorLogOptions &log_options,
		   HttpResponseHandler &handler,
		   CancellablePointer &caller_cancel_ptr) noexcept {
		caller_cancel_ptr = *this;

		fcgi_stock_item_set_site(*stock_item, site_name);
		fcgi_stock_item_set_uri(*stock_item, uri);

		if (!stderr_fd.IsDefined())
			stderr_fd = fcgi_stock_item_get_stderr(*stock_item);

		if (log_socket.IsDefined() && !stderr_fd.IsDefined())
			stderr_fd = log.EnableClient(event_loop, log_socket,
						     log_options,
						     /* TODO? */ true);

		log.SetSite(site_name);

		const char *script_filename = path;

		fcgi_client_request(&pool, event_loop, std::move(stopwatch),
				    fcgi_stock_item_get(*stock_item),
				    fcgi_stock_item_get_domain(*stock_item) == AF_LOCAL
				    ? FdType::FD_SOCKET : FdType::FD_TCP,
				    *this,
				    method, uri,
				    script_filename,
				    script_name, path_info,
				    query_string,
				    document_root,
				    remote_addr,
				    std::move(headers), std::move(body),
				    params,
				    std::move(stderr_fd),
				    handler, cancel_ptr);
	}

private:
	void Destroy() noexcept {
		DeleteFromPool(pool, this);
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override {
		fcgi_stock_aborted(*stock_item);

		cancel_ptr.Cancel();
	}

	/* virtual methods from class Lease */
	void ReleaseLease(bool reuse) noexcept override {
		stock_item->Put(!reuse);
		stock_item = nullptr;

		Destroy();
	}
};

void
fcgi_request(struct pool *pool, EventLoop &event_loop,
	     FcgiStock *fcgi_stock,
	     const StopwatchPtr &parent_stopwatch,
	     const char *site_name,
	     const ChildOptions &options,
	     const char *action,
	     const char *path,
	     ConstBuffer<const char *> args,
	     unsigned parallelism,
	     http_method_t method, const char *uri,
	     const char *script_name, const char *path_info,
	     const char *query_string,
	     const char *document_root,
	     const char *remote_addr,
	     StringMap &&headers, UnusedIstreamPtr body,
	     ConstBuffer<const char *> params,
	     UniqueFileDescriptor &&stderr_fd,
	     HttpResponseHandler &handler,
	     CancellablePointer &cancel_ptr) noexcept
{
	if (action == nullptr)
		action = path;

	StopwatchPtr stopwatch(parent_stopwatch, "fcgi", action);

	StockItem *stock_item;
	try {
		stock_item = fcgi_stock_get(fcgi_stock, options,
					    action, args, parallelism);
	} catch (...) {
		stopwatch.RecordEvent("launch_error");
		body.Clear();
		handler.InvokeError(std::current_exception());
		return;
	}

	stopwatch.RecordEvent("fork");

	auto request = NewFromPool<FcgiRequest>(*pool, *pool, *stock_item);

	request->Start(event_loop, std::move(stopwatch),
		       site_name, path, method, uri,
		       script_name, path_info,
		       query_string, document_root, remote_addr,
		       std::move(headers), std::move(body),
		       params, std::move(stderr_fd),
		       fcgi_stock_get_log_socket(*fcgi_stock),
		       fcgi_stock_get_log_options(*fcgi_stock),
		       handler, cancel_ptr);
}
<|endoftext|>


<commit_before>#include <fffuncparser.h>

#ifdef FF_DEBUG
#   include <cstdio>
#endif

using namespace ff;

FuncParser::FuncParser(int argc, const char ** argv)
    :m_index(clang_createIndex(0, 0))
    ,m_tunit()
    ,m_argc(argc)
    ,m_argv(argv)
    ,m_func_list()
    ,m_file()
{

}

FuncParser::~FuncParser()
{
    clang_disposeIndex(this->m_index);
    clang_disposeTranslationUnit(this->m_tunit);
}

bool
FuncParser::parse(const std::string &file)
{
    if (file.empty()) {
        return false;
    }

    this->m_file = file;

    return this->startParse();
}

void FuncParser::unregisterKind(CXCursorKind kind)
{
    for (std::vector<CXCursorKind>::iterator it = this->m_kind.begin();
            it != this->m_kind.end();it ++) {
        if (*it == kind) {
            this->m_kind.erase(it);
            break;
        }
    }
}

bool
FuncParser::startParse()
{
    this->m_tunit = clang_parseTranslationUnit(this->m_index,
                                               this->m_file.c_str(),
                                               this->m_argv,
                                               this->m_argc,
                                               nullptr,
                                               0,
                                               CXTranslationUnit_None);

    CXCursor cursor = clang_getTranslationUnitCursor(this->m_tunit);

    int ret = clang_visitChildren(cursor, FuncParser::FP_vistor, CXClientData(this));

    return bool(ret == 0);
}

void
FuncParser::visitCursor(CXCursor cursor)
{
    CXCursorKind kind = clang_getCursorKind(cursor);

#ifndef FF_DEBUG
    if (this->filterKind(kind)) {
        return ;
    }
#endif

    CXString str = clang_getCursorKindSpelling(kind);

    FF_AVOID_WARNING(str);
    //add parser cpp or header file

#ifdef FF_DEBUG
    std::fprintf(stderr, "CursorKind:%s\n", clang_getCString(str));
#endif
}

CXChildVisitResult
FuncParser::FP_vistor(CXCursor cursor, CXCursor parent, CXClientData data)
{
    FF_AVOID_WARNING(parent);

    FuncParser* fp = static_cast<FuncParser*>(data);

    fp->visitCursor(cursor);

    return CXChildVisit_Continue;
}

bool
FuncParser::filterKind(CXCursorKind kind)
{
    for (std::vector<CXCursorKind>::iterator it = this->m_kind.begin();
            it != this->m_kind.end();it ++) {
        if (*it == kind) {
            return false;
        }
    }

    return true;
}

<commit_msg>add parse CursorKind switch..<commit_after>#include <fffuncparser.h>

#ifdef FF_DEBUG
#   include <cstdio>
#endif

using namespace ff;

FuncParser::FuncParser(int argc, const char ** argv)
    :m_index(clang_createIndex(0, 0))
    ,m_tu()
    ,m_argc(argc)
    ,m_argv(argv)
    ,m_func_list()
    ,m_file()
{
    this->registerKind(CXCursor_FunctionDecl);
    this->registerKind(CXCursor_FunctionTemplate);
    this->registerKind(CXCursor_CXXMethod);
    this->registerKind(CXCursor_Constructor);
    this->registerKind(CXCursor_Destructor);
    this->registerKind(CXCursor_ConversionFunction);
    this->registerKind(CXCursor_ClassDecl);
    this->registerKind(CXCursor_StructDecl);
}

FuncParser::~FuncParser()
{

}

bool
FuncParser::parse(const std::string &file)
{
    if (file.empty()) {
        return false;
    }

    m_file = file;

    return this->startParse();
}

void FuncParser::unregisterKind(CXCursorKind kind)
{
    m_kind.erase(kind);
}

bool
FuncParser::startParse()
{
    m_tu = clang_parseTranslationUnit(
            m_index,
            m_file.c_str(),
            m_argv,
            m_argc,
            nullptr,
            0,
            CXTranslationUnit_None
    );

    CXCursor cursor = clang_getTranslationUnitCursor(m_tu);

    int ret = clang_visitChildren(cursor, FuncParser::FP_vistor, CXClientData(this));

    return bool(ret == 0);
}

CXChildVisitResult
FuncParser::visitCursor(CXCursor cursor)
{
    CXCursorKind kind = clang_getCursorKind(cursor);

    if (this->filterKind(kind)) {
        return CXChildVisit_Continue;
    }

    switch(kind) {
        case CXCursor_FunctionDecl: { }
        case CXCursor_FunctionTemplate: { }
        case CXCursor_CXXMethod: { }
        case CXCursor_Constructor: { }
        case CXCursor_Destructor: { }
        case CXCursor_ConversionFunction: { }
        case CXCursor_ClassDecl: { }
        case CXCursor_StructDecl: { }
        default: {   }
    }

    return CXChildVisit_Continue;
}

CXChildVisitResult
FuncParser::FP_vistor(CXCursor cursor, CXCursor parent, CXClientData data)
{
    FF_AVOID_WARNING(parent);

    FuncParser* fp = static_cast<FuncParser*>(data);

    return fp->visitCursor(cursor);
}

bool
FuncParser::filterKind(CXCursorKind kind)
{
    return m_kind.count(kind) > 0;
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2003-2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/file_storage.hpp"
#include "libtorrent/utf8.hpp"
#include <boost/bind.hpp>

namespace libtorrent
{
	file_storage::file_storage()
		: m_piece_length(0)
		, m_total_size(0)
		, m_num_pieces(0)
	{}

	int file_storage::piece_size(int index) const
	{
		TORRENT_ASSERT(index >= 0 && index < num_pieces());
		if (index == num_pieces()-1)
		{
			int size = int(total_size()
				- size_type(num_pieces() - 1) * piece_length());
			TORRENT_ASSERT(size > 0);
			TORRENT_ASSERT(size <= piece_length());
			return int(size);
		}
		else
			return piece_length();
	}

	void file_storage::set_name(std::wstring const& n)
	{
		std::string utf8;
		wchar_utf8(n, utf8);
		m_name = utf8;
	}

	void file_storage::rename_file(int index, std::string const& new_filename)
	{
		TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
		m_files[index].path = new_filename;
	}

	void file_storage::rename_file(int index, std::wstring const& new_filename)
	{
		TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
		std::string utf8;
		wchar_utf8(new_filename, utf8);
		m_files[index].path = utf8;
	}

	file_storage::iterator file_storage::file_at_offset(size_type offset) const
	{
		// TODO: do a binary search
		std::vector<file_entry>::const_iterator i;
		for (i = begin(); i != end(); ++i)
		{
			if (i->offset <= offset && i->offset + i->size > offset)
				return i;
		}
		return i;
	}

	std::vector<file_slice> file_storage::map_block(int piece, size_type offset
		, int size_) const
	{
		TORRENT_ASSERT(num_files() > 0);
		std::vector<file_slice> ret;

		size_type start = piece * (size_type)m_piece_length + offset;
		size_type size = size_;
		TORRENT_ASSERT(start + size <= m_total_size);

		// find the file iterator and file offset
		// TODO: do a binary search on the file offsets
		size_type file_offset = start;
		std::vector<file_entry>::const_iterator file_iter;

		int counter = 0;
		for (file_iter = begin();; ++counter, ++file_iter)
		{
			TORRENT_ASSERT(file_iter != end());
			if (file_offset < file_iter->size)
			{
				file_slice f;
				f.file_index = counter;
				f.offset = file_offset + file_iter->file_base;
				f.size = (std::min)(file_iter->size - file_offset, (size_type)size);
				size -= f.size;
				file_offset += f.size;
				ret.push_back(f);
			}

			TORRENT_ASSERT(size >= 0);
			if (size <= 0) break;

			file_offset -= file_iter->size;
		}
		return ret;
	}

	peer_request file_storage::map_file(int file_index, size_type file_offset
		, int size) const
	{
		TORRENT_ASSERT(file_index < num_files());
		TORRENT_ASSERT(file_index >= 0);
		size_type offset = file_offset + at(file_index).offset;

		peer_request ret;
		ret.piece = int(offset / piece_length());
		ret.start = int(offset - ret.piece * piece_length());
		ret.length = size;
		return ret;
	}

	void file_storage::add_file(fs::wpath const& file, size_type size, int flags)
	{
		std::string utf8;
		wchar_utf8(file.string(), utf8);
		add_file(utf8, size, flags);
	}

	void file_storage::add_file(fs::path const& file, size_type size, int flags)
	{
		TORRENT_ASSERT(size >= 0);
#if BOOST_VERSION < 103600
		if (!file.has_branch_path())
#else
		if (!file.has_parent_path())
#endif
		{
			// you have already added at least one file with a
			// path to the file (branch_path), which means that
			// all the other files need to be in the same top
			// directory as the first file.
			TORRENT_ASSERT(m_files.empty());
			m_name = file.string();
		}
		else
		{
			if (m_files.empty())
				m_name = *file.begin();
		}
		TORRENT_ASSERT(m_name == *file.begin());
		m_files.push_back(file_entry());
		file_entry& e = m_files.back();
		e.size = size;
		e.path = file;
		e.offset = m_total_size;
		e.pad_file = bool(flags & pad_file);
		e.hidden_attribute = bool(flags & attribute_hidden);
		e.executable_attribute = bool(flags & attribute_executable);
		m_total_size += size;
	}

	void file_storage::add_file(file_entry const& ent)
	{
#if BOOST_VERSION < 103600
		if (!ent.path.has_branch_path())
#else
		if (!ent.path.has_parent_path())
#endif
		{
			// you have already added at least one file with a
			// path to the file (branch_path), which means that
			// all the other files need to be in the same top
			// directory as the first file.
			TORRENT_ASSERT(m_files.empty());
			m_name = ent.path.string();
		}
		else
		{
			if (m_files.empty())
				m_name = *ent.path.begin();
		}
		m_files.push_back(ent);
		file_entry& e = m_files.back();
		e.offset = m_total_size;
		m_total_size += ent.size;
	}

	void file_storage::optimize(int pad_file_limit)
	{
		// the main purpuse of padding is to optimize disk
		// I/O. This is a conservative memory page size assumption
		int alignment = 8*1024;

		// it doesn't make any sense to pad files that
		// are smaller than one piece
		if (pad_file_limit >= 0 && pad_file_limit < alignment)
			pad_file_limit = alignment;

		// put the largest file at the front, to make sure
		// it's aligned
		std::vector<file_entry>::iterator i = std::max_element(m_files.begin(), m_files.end()
			, boost::bind(&file_entry::size, _1) < boost::bind(&file_entry::size, _2));

		using std::iter_swap;
		iter_swap(i, m_files.begin());

		size_type off = 0;
		int padding_file = 0;
		for (std::vector<file_entry>::iterator i = m_files.begin();
			i != m_files.end(); ++i)
		{
			if (pad_file_limit >= 0
				&& (off & (alignment-1)) != 0
				&& i->size > pad_file_limit
				&& i->pad_file == false)
			{
				// if we have pad files enabled, and this file is
				// not piece-aligned and the file size exceeds the
				// limit, and it's not a padding file itself.
				// so add a padding file in front of it
				int pad_size = alignment - (off & (alignment-1));

				// find the largest file that fits in pad_size
				std::vector<file_entry>::iterator best_match = m_files.end();
				for (std::vector<file_entry>::iterator j = i+1; j < m_files.end(); ++j)
				{
					if (j->size > pad_size) continue;
					if (best_match == m_files.end() || j->size > best_match->size)
						best_match = j;
				}

				if (best_match != m_files.end())
				{
					// we found one
					file_entry e = *best_match;
					m_files.erase(best_match);
					i = m_files.insert(i, e);
					i->offset = off;
					off += i->size;
					continue;
				}

				// we could not find a file that fits in pad_size
				// add a padding file

				file_entry e;
				i = m_files.insert(i, e);
				i->size = pad_size;
				i->offset = off;
				i->file_base = 0;
				char name[10];
				sprintf(name, "%d", padding_file);
				i->path = *(i+1)->path.begin();
				i->path /= "_____padding_file_";
				i->path /= name;
				i->pad_file = true;
				off += pad_size;
				++padding_file;
				++i;
			}
			i->offset = off;
			off += i->size;
		}
		m_total_size = off;
	}
}

<commit_msg>optimized file_storage::map_block to use lower_bound instead of linear search<commit_after>/*

Copyright (c) 2003-2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include "libtorrent/file_storage.hpp"
#include "libtorrent/utf8.hpp"
#include <boost/bind.hpp>

namespace libtorrent
{
	file_storage::file_storage()
		: m_piece_length(0)
		, m_total_size(0)
		, m_num_pieces(0)
	{}

	int file_storage::piece_size(int index) const
	{
		TORRENT_ASSERT(index >= 0 && index < num_pieces());
		if (index == num_pieces()-1)
		{
			int size = int(total_size()
				- size_type(num_pieces() - 1) * piece_length());
			TORRENT_ASSERT(size > 0);
			TORRENT_ASSERT(size <= piece_length());
			return int(size);
		}
		else
			return piece_length();
	}

	void file_storage::set_name(std::wstring const& n)
	{
		std::string utf8;
		wchar_utf8(n, utf8);
		m_name = utf8;
	}

	void file_storage::rename_file(int index, std::string const& new_filename)
	{
		TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
		m_files[index].path = new_filename;
	}

	void file_storage::rename_file(int index, std::wstring const& new_filename)
	{
		TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
		std::string utf8;
		wchar_utf8(new_filename, utf8);
		m_files[index].path = utf8;
	}

	file_storage::iterator file_storage::file_at_offset(size_type offset) const
	{
		// TODO: do a binary search
		std::vector<file_entry>::const_iterator i;
		for (i = begin(); i != end(); ++i)
		{
			if (i->offset <= offset && i->offset + i->size > offset)
				return i;
		}
		return i;
	}

	namespace
	{
		bool compare_file_offset(file_entry const& lhs, file_entry const& rhs)
		{
			return lhs.offset + lhs.size < rhs.offset + rhs.size;
		}
	}

	std::vector<file_slice> file_storage::map_block(int piece, size_type offset
		, int size) const
	{
		TORRENT_ASSERT(num_files() > 0);
		std::vector<file_slice> ret;

		// find the file iterator and file offset
		file_entry target;
		target.offset = piece * (size_type)m_piece_length + offset;
		target.size = 0;
		TORRENT_ASSERT(target.offset + size <= m_total_size);

		std::vector<file_entry>::const_iterator file_iter = std::upper_bound(
			begin(), end(), target, compare_file_offset);

		if (file_iter == end()) return ret;

		size_type file_offset = file_iter->offset;
		for (; size > 0; file_offset -= file_iter->size, ++file_iter)
		{
			TORRENT_ASSERT(file_iter != end());
			if (file_offset < file_iter->size)
			{
				file_slice f;
				f.file_index = file_iter - begin();
				f.offset = file_offset + file_iter->file_base;
				f.size = (std::min)(file_iter->size - file_offset, (size_type)size);
				size -= f.size;
				file_offset += f.size;
				ret.push_back(f);
			}

			TORRENT_ASSERT(size >= 0);
		}
		return ret;
	}

	peer_request file_storage::map_file(int file_index, size_type file_offset
		, int size) const
	{
		TORRENT_ASSERT(file_index < num_files());
		TORRENT_ASSERT(file_index >= 0);
		size_type offset = file_offset + at(file_index).offset;

		peer_request ret;
		ret.piece = int(offset / piece_length());
		ret.start = int(offset - ret.piece * piece_length());
		ret.length = size;
		return ret;
	}

	void file_storage::add_file(fs::wpath const& file, size_type size, int flags)
	{
		std::string utf8;
		wchar_utf8(file.string(), utf8);
		add_file(utf8, size, flags);
	}

	void file_storage::add_file(fs::path const& file, size_type size, int flags)
	{
		TORRENT_ASSERT(size >= 0);
#if BOOST_VERSION < 103600
		if (!file.has_branch_path())
#else
		if (!file.has_parent_path())
#endif
		{
			// you have already added at least one file with a
			// path to the file (branch_path), which means that
			// all the other files need to be in the same top
			// directory as the first file.
			TORRENT_ASSERT(m_files.empty());
			m_name = file.string();
		}
		else
		{
			if (m_files.empty())
				m_name = *file.begin();
		}
		TORRENT_ASSERT(m_name == *file.begin());
		m_files.push_back(file_entry());
		file_entry& e = m_files.back();
		e.size = size;
		e.path = file;
		e.offset = m_total_size;
		e.pad_file = bool(flags & pad_file);
		e.hidden_attribute = bool(flags & attribute_hidden);
		e.executable_attribute = bool(flags & attribute_executable);
		m_total_size += size;
	}

	void file_storage::add_file(file_entry const& ent)
	{
#if BOOST_VERSION < 103600
		if (!ent.path.has_branch_path())
#else
		if (!ent.path.has_parent_path())
#endif
		{
			// you have already added at least one file with a
			// path to the file (branch_path), which means that
			// all the other files need to be in the same top
			// directory as the first file.
			TORRENT_ASSERT(m_files.empty());
			m_name = ent.path.string();
		}
		else
		{
			if (m_files.empty())
				m_name = *ent.path.begin();
		}
		m_files.push_back(ent);
		file_entry& e = m_files.back();
		e.offset = m_total_size;
		m_total_size += ent.size;
	}

	void file_storage::optimize(int pad_file_limit)
	{
		// the main purpuse of padding is to optimize disk
		// I/O. This is a conservative memory page size assumption
		int alignment = 8*1024;

		// it doesn't make any sense to pad files that
		// are smaller than one piece
		if (pad_file_limit >= 0 && pad_file_limit < alignment)
			pad_file_limit = alignment;

		// put the largest file at the front, to make sure
		// it's aligned
		std::vector<file_entry>::iterator i = std::max_element(m_files.begin(), m_files.end()
			, boost::bind(&file_entry::size, _1) < boost::bind(&file_entry::size, _2));

		using std::iter_swap;
		iter_swap(i, m_files.begin());

		size_type off = 0;
		int padding_file = 0;
		for (std::vector<file_entry>::iterator i = m_files.begin();
			i != m_files.end(); ++i)
		{
			if (pad_file_limit >= 0
				&& (off & (alignment-1)) != 0
				&& i->size > pad_file_limit
				&& i->pad_file == false)
			{
				// if we have pad files enabled, and this file is
				// not piece-aligned and the file size exceeds the
				// limit, and it's not a padding file itself.
				// so add a padding file in front of it
				int pad_size = alignment - (off & (alignment-1));

				// find the largest file that fits in pad_size
				std::vector<file_entry>::iterator best_match = m_files.end();
				for (std::vector<file_entry>::iterator j = i+1; j < m_files.end(); ++j)
				{
					if (j->size > pad_size) continue;
					if (best_match == m_files.end() || j->size > best_match->size)
						best_match = j;
				}

				if (best_match != m_files.end())
				{
					// we found one
					file_entry e = *best_match;
					m_files.erase(best_match);
					i = m_files.insert(i, e);
					i->offset = off;
					off += i->size;
					continue;
				}

				// we could not find a file that fits in pad_size
				// add a padding file

				file_entry e;
				i = m_files.insert(i, e);
				i->size = pad_size;
				i->offset = off;
				i->file_base = 0;
				char name[10];
				sprintf(name, "%d", padding_file);
				i->path = *(i+1)->path.begin();
				i->path /= "_____padding_file_";
				i->path /= name;
				i->pad_file = true;
				off += pad_size;
				++padding_file;
				++i;
			}
			i->offset = off;
			off += i->size;
		}
		m_total_size = off;
	}
}

<|endoftext|>


<commit_before>#include "build.h"

#include <stdio.h>

#include "build_log.h"
#include "graph.h"
#include "ninja.h"
#include "subprocess.h"

struct BuildStatus {
  BuildStatus();
  virtual void PlanHasTotalEdges(int total);
  virtual void BuildEdgeStarted(Edge* edge);
  virtual void BuildEdgeFinished(Edge* edge);

  time_t last_update_;
  int finished_edges_, total_edges_;

  BuildConfig::Verbosity verbosity_;
};

BuildStatus::BuildStatus()
    : last_update_(time(NULL)), finished_edges_(0), total_edges_(0),
      verbosity_(BuildConfig::NORMAL) {}

void BuildStatus::PlanHasTotalEdges(int total) {
  total_edges_ = total;
}

void BuildStatus::BuildEdgeStarted(Edge* edge) {
  string desc = edge->GetDescription();
  if (verbosity_ != BuildConfig::QUIET) {
    if (verbosity_ != BuildConfig::VERBOSE && !desc.empty())
      printf("%s\n", desc.c_str());
    else
      printf("%s\n", edge->EvaluateCommand().c_str());
  }
}

void BuildStatus::BuildEdgeFinished(Edge* edge) {
  ++finished_edges_;
  time_t now = time(NULL);
  if (now - last_update_ > 5) {
    printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
           finished_edges_, total_edges_);
    last_update_ = now;
  }
}

bool Plan::AddTarget(Node* node, string* err) {
  vector<Node*> stack;
  return AddSubTarget(node, &stack, err);
}

bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
  Edge* edge = node->in_edge_;
  if (!edge) {  // Leaf node.
    if (node->dirty_) {
      string referenced;
      if (!stack->empty())
        referenced = ", needed by '" + stack->back()->file_->path_ + "',";
      *err = "'" + node->file_->path_ + "'" + referenced + " missing "
             "and no known rule to make it";
    }
    return false;
  }
  assert(edge);

  if (CheckDependencyCycle(node, stack, err))
    return false;

  if (!node->dirty())
    return false;  // Don't need to do anything.
  if (want_.find(edge) != want_.end())
    return true;  // We've already enqueued it.
  want_.insert(edge);

  stack->push_back(node);
  bool awaiting_inputs = false;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if (!edge->is_implicit(i - edge->inputs_.begin()) &&
        AddSubTarget(*i, stack, err)) {
      awaiting_inputs = true;
    } else if (!err->empty()) {
      return false;
    }
  }
  assert(stack->back() == node);
  stack->pop_back();

  if (!awaiting_inputs)
    ready_.insert(edge);

  return true;
}

bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
  vector<Node*>::reverse_iterator ri =
      find(stack->rbegin(), stack->rend(), node);
  if (ri == stack->rend())
    return false;

  // Add this node onto the stack to make it clearer where the loop
  // is.
  stack->push_back(node);

  vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
  *err = "dependency cycle: ";
  for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
    if (i != start)
      err->append(" -> ");
    err->append((*i)->file_->path_);
  }
  return true;
}

Edge* Plan::FindWork() {
  if (ready_.empty())
    return NULL;
  set<Edge*>::iterator i = ready_.begin();
  Edge* edge = *i;
  ready_.erase(i);
  return edge;
}

void Plan::EdgeFinished(Edge* edge) {
  want_.erase(edge);

  // Check off any nodes we were waiting for with this edge.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    NodeFinished(*i);
  }
}

void Plan::NodeFinished(Node* node) {
  // See if we we want any edges from this node.
  for (vector<Edge*>::iterator i = node->out_edges_.begin();
       i != node->out_edges_.end(); ++i) {
    if (want_.find(*i) != want_.end()) {
      // See if the edge is now ready.
      bool ready = true;
      for (vector<Node*>::iterator j = (*i)->inputs_.begin();
           j != (*i)->inputs_.end(); ++j) {
        if ((*j)->dirty()) {
          ready = false;
          break;
        }
      }
      if (ready)
        ready_.insert(*i);
    }
  }
}

void Plan::Dump() {
  printf("pending: %d\n", (int)want_.size());
  for (set<Edge*>::iterator i = want_.begin(); i != want_.end(); ++i) {
    (*i)->Dump();
  }
  printf("ready: %d\n", (int)ready_.size());
}

struct RealCommandRunner : public CommandRunner {
  virtual ~RealCommandRunner() {}
  virtual bool CanRunMore();
  virtual bool StartCommand(Edge* edge);
  virtual bool WaitForCommands();
  virtual Edge* NextFinishedCommand(bool* success);

  SubprocessSet subprocs_;
  map<Subprocess*, Edge*> subproc_to_edge_;
};

bool RealCommandRunner::CanRunMore() {
  const size_t kConcurrency = 8;  // XXX make configurable etc.
  return subprocs_.running_.size() < kConcurrency;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
  string command = edge->EvaluateCommand();
  Subprocess* subproc = new Subprocess;
  subproc_to_edge_.insert(make_pair(subproc, edge));
  if (!subproc->Start(command))
    return false;

  subprocs_.Add(subproc);
  return true;
}

bool RealCommandRunner::WaitForCommands() {
  if (subprocs_.running_.empty())
    return false;

  while (subprocs_.finished_.empty()) {
    subprocs_.DoWork();
  }
  return true;
}

Edge* RealCommandRunner::NextFinishedCommand(bool* success) {
  Subprocess* subproc = subprocs_.NextFinished();
  if (!subproc)
    return NULL;

  *success = subproc->Finish();

  map<Subprocess*, Edge*>::iterator i = subproc_to_edge_.find(subproc);
  Edge* edge = i->second;
  subproc_to_edge_.erase(i);

  if (!*success)
    printf("FAILED: %s\n", edge->EvaluateCommand().c_str());
  if (!subproc->stdout_.buf_.empty())
    printf("%s\n", subproc->stdout_.buf_.c_str());
  if (!subproc->stderr_.buf_.empty())
    printf("%s\n", subproc->stderr_.buf_.c_str());

  delete subproc;
  return edge;
}

struct DryRunCommandRunner : public CommandRunner {
  virtual ~DryRunCommandRunner() {}
  virtual bool CanRunMore() {
    return true;
  }
  virtual bool StartCommand(Edge* edge) {
    finished_.push(edge);
    return true;
  }
  virtual bool WaitForCommands() {
    return true;
  }
  virtual Edge* NextFinishedCommand(bool* success) {
    if (finished_.empty())
      return NULL;
    *success = true;
    Edge* edge = finished_.front();
    finished_.pop();
    return edge;
  }

  queue<Edge*> finished_;
};

Builder::Builder(State* state, const BuildConfig& config)
    : state_(state) {
  disk_interface_ = new RealDiskInterface;
  if (config.dry_run)
    command_runner_ = new DryRunCommandRunner;
  else
    command_runner_ = new RealCommandRunner;
  status_ = new BuildStatus;
  status_->verbosity_ = config.verbosity;
  log_ = state->build_log_;
}

Node* Builder::AddTarget(const string& name, string* err) {
  Node* node = state_->LookupNode(name);
  if (!node) {
    *err = "unknown target: '" + name + "'";
    return NULL;
  }
  node->file_->StatIfNecessary(disk_interface_);
  if (node->in_edge_) {
    if (!node->in_edge_->RecomputeDirty(state_, disk_interface_, err))
      return NULL;
  }
  if (!node->dirty_)
    return NULL;  // Intentionally no error.

  if (!plan_.AddTarget(node, err))
    return NULL;
  return node;
}

bool Builder::Build(string* err) {
  if (!plan_.more_to_do()) {
    *err = "no work to do";
    return true;
  }

  status_->PlanHasTotalEdges(plan_.edge_count());
  while (plan_.more_to_do()) {
    while (command_runner_->CanRunMore()) {
      Edge* edge = plan_.FindWork();
      if (!edge)
        break;

      if (edge->rule_ == &State::kPhonyRule) {
        FinishEdge(edge);
        continue;
      }

      if (!StartEdge(edge, err))
        return false;
    }

    bool success;
    if (Edge* edge = command_runner_->NextFinishedCommand(&success)) {
      if (!success) {
        *err = "subcommand failed";
        return false;
      }
      FinishEdge(edge);
    } else {
      if (!command_runner_->WaitForCommands()) {
        *err = "stuck [this is a bug]";
        return false;
      }
    }
  }

  return true;
}

bool Builder::StartEdge(Edge* edge, string* err) {
  status_->BuildEdgeStarted(edge);

  // Create directories necessary for outputs.
  // XXX: this will block; do we care?
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    if (!disk_interface_->MakeDirs((*i)->file_->path_))
      return false;
  }

  // Compute command and start it.
  string command = edge->EvaluateCommand();
  if (!command_runner_->StartCommand(edge)) {
    err->assign("command '" + command + "' failed.");
    return false;
  }

  return true;
}

void Builder::FinishEdge(Edge* edge) {
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    // XXX check that the output actually changed
    // XXX just notify node and have it propagate?
    (*i)->dirty_ = false;
  }
  plan_.EdgeFinished(edge);
  status_->BuildEdgeFinished(edge);
  log_->RecordCommand(edge, 0);  // XXX get edge timing.
}
<commit_msg>compute edge timing<commit_after>#include "build.h"

#include <stdio.h>
#include <sys/time.h>

#include "build_log.h"
#include "graph.h"
#include "ninja.h"
#include "subprocess.h"

struct BuildStatus {
  BuildStatus();
  virtual void PlanHasTotalEdges(int total);
  virtual void BuildEdgeStarted(Edge* edge);
  virtual void BuildEdgeFinished(Edge* edge);

  time_t last_update_;
  int finished_edges_, total_edges_;

  typedef map<Edge*, timeval> RunningEdgeMap;
  RunningEdgeMap running_edges_;

  BuildConfig::Verbosity verbosity_;
};

BuildStatus::BuildStatus()
    : last_update_(time(NULL)), finished_edges_(0), total_edges_(0),
      verbosity_(BuildConfig::NORMAL) {}

void BuildStatus::PlanHasTotalEdges(int total) {
  total_edges_ = total;
}

void BuildStatus::BuildEdgeStarted(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  running_edges_.insert(make_pair(edge, now));

  if (edge->rule_ == &State::kPhonyRule)
    return;

  string desc = edge->GetDescription();
  if (verbosity_ != BuildConfig::QUIET) {
    if (verbosity_ != BuildConfig::VERBOSE && !desc.empty())
      printf("%s\n", desc.c_str());
    else
      printf("%s\n", edge->EvaluateCommand().c_str());
  }
}

void BuildStatus::BuildEdgeFinished(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  ++finished_edges_;

  if (now.tv_sec - last_update_ > 5) {
    printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
           finished_edges_, total_edges_);
    last_update_ = now.tv_sec;
  }

  RunningEdgeMap::iterator i = running_edges_.find(edge);
  timeval delta;
  timersub(&now, &i->second, &delta);
  printf("%dms\n", (int)((delta.tv_sec * 1000) + (delta.tv_usec / 1000)));
  running_edges_.erase(i);
}

bool Plan::AddTarget(Node* node, string* err) {
  vector<Node*> stack;
  return AddSubTarget(node, &stack, err);
}

bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
  Edge* edge = node->in_edge_;
  if (!edge) {  // Leaf node.
    if (node->dirty_) {
      string referenced;
      if (!stack->empty())
        referenced = ", needed by '" + stack->back()->file_->path_ + "',";
      *err = "'" + node->file_->path_ + "'" + referenced + " missing "
             "and no known rule to make it";
    }
    return false;
  }
  assert(edge);

  if (CheckDependencyCycle(node, stack, err))
    return false;

  if (!node->dirty())
    return false;  // Don't need to do anything.
  if (want_.find(edge) != want_.end())
    return true;  // We've already enqueued it.
  want_.insert(edge);

  stack->push_back(node);
  bool awaiting_inputs = false;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if (!edge->is_implicit(i - edge->inputs_.begin()) &&
        AddSubTarget(*i, stack, err)) {
      awaiting_inputs = true;
    } else if (!err->empty()) {
      return false;
    }
  }
  assert(stack->back() == node);
  stack->pop_back();

  if (!awaiting_inputs)
    ready_.insert(edge);

  return true;
}

bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
  vector<Node*>::reverse_iterator ri =
      find(stack->rbegin(), stack->rend(), node);
  if (ri == stack->rend())
    return false;

  // Add this node onto the stack to make it clearer where the loop
  // is.
  stack->push_back(node);

  vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
  *err = "dependency cycle: ";
  for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
    if (i != start)
      err->append(" -> ");
    err->append((*i)->file_->path_);
  }
  return true;
}

Edge* Plan::FindWork() {
  if (ready_.empty())
    return NULL;
  set<Edge*>::iterator i = ready_.begin();
  Edge* edge = *i;
  ready_.erase(i);
  return edge;
}

void Plan::EdgeFinished(Edge* edge) {
  want_.erase(edge);

  // Check off any nodes we were waiting for with this edge.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    NodeFinished(*i);
  }
}

void Plan::NodeFinished(Node* node) {
  // See if we we want any edges from this node.
  for (vector<Edge*>::iterator i = node->out_edges_.begin();
       i != node->out_edges_.end(); ++i) {
    if (want_.find(*i) != want_.end()) {
      // See if the edge is now ready.
      bool ready = true;
      for (vector<Node*>::iterator j = (*i)->inputs_.begin();
           j != (*i)->inputs_.end(); ++j) {
        if ((*j)->dirty()) {
          ready = false;
          break;
        }
      }
      if (ready)
        ready_.insert(*i);
    }
  }
}

void Plan::Dump() {
  printf("pending: %d\n", (int)want_.size());
  for (set<Edge*>::iterator i = want_.begin(); i != want_.end(); ++i) {
    (*i)->Dump();
  }
  printf("ready: %d\n", (int)ready_.size());
}

struct RealCommandRunner : public CommandRunner {
  virtual ~RealCommandRunner() {}
  virtual bool CanRunMore();
  virtual bool StartCommand(Edge* edge);
  virtual bool WaitForCommands();
  virtual Edge* NextFinishedCommand(bool* success);

  SubprocessSet subprocs_;
  map<Subprocess*, Edge*> subproc_to_edge_;
};

bool RealCommandRunner::CanRunMore() {
  const size_t kConcurrency = 8;  // XXX make configurable etc.
  return subprocs_.running_.size() < kConcurrency;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
  string command = edge->EvaluateCommand();
  Subprocess* subproc = new Subprocess;
  subproc_to_edge_.insert(make_pair(subproc, edge));
  if (!subproc->Start(command))
    return false;

  subprocs_.Add(subproc);
  return true;
}

bool RealCommandRunner::WaitForCommands() {
  if (subprocs_.running_.empty())
    return false;

  while (subprocs_.finished_.empty()) {
    subprocs_.DoWork();
  }
  return true;
}

Edge* RealCommandRunner::NextFinishedCommand(bool* success) {
  Subprocess* subproc = subprocs_.NextFinished();
  if (!subproc)
    return NULL;

  *success = subproc->Finish();

  map<Subprocess*, Edge*>::iterator i = subproc_to_edge_.find(subproc);
  Edge* edge = i->second;
  subproc_to_edge_.erase(i);

  if (!*success)
    printf("FAILED: %s\n", edge->EvaluateCommand().c_str());
  if (!subproc->stdout_.buf_.empty())
    printf("%s\n", subproc->stdout_.buf_.c_str());
  if (!subproc->stderr_.buf_.empty())
    printf("%s\n", subproc->stderr_.buf_.c_str());

  delete subproc;
  return edge;
}

struct DryRunCommandRunner : public CommandRunner {
  virtual ~DryRunCommandRunner() {}
  virtual bool CanRunMore() {
    return true;
  }
  virtual bool StartCommand(Edge* edge) {
    finished_.push(edge);
    return true;
  }
  virtual bool WaitForCommands() {
    return true;
  }
  virtual Edge* NextFinishedCommand(bool* success) {
    if (finished_.empty())
      return NULL;
    *success = true;
    Edge* edge = finished_.front();
    finished_.pop();
    return edge;
  }

  queue<Edge*> finished_;
};

Builder::Builder(State* state, const BuildConfig& config)
    : state_(state) {
  disk_interface_ = new RealDiskInterface;
  if (config.dry_run)
    command_runner_ = new DryRunCommandRunner;
  else
    command_runner_ = new RealCommandRunner;
  status_ = new BuildStatus;
  status_->verbosity_ = config.verbosity;
  log_ = state->build_log_;
}

Node* Builder::AddTarget(const string& name, string* err) {
  Node* node = state_->LookupNode(name);
  if (!node) {
    *err = "unknown target: '" + name + "'";
    return NULL;
  }
  node->file_->StatIfNecessary(disk_interface_);
  if (node->in_edge_) {
    if (!node->in_edge_->RecomputeDirty(state_, disk_interface_, err))
      return NULL;
  }
  if (!node->dirty_)
    return NULL;  // Intentionally no error.

  if (!plan_.AddTarget(node, err))
    return NULL;
  return node;
}

bool Builder::Build(string* err) {
  if (!plan_.more_to_do()) {
    *err = "no work to do";
    return true;
  }

  status_->PlanHasTotalEdges(plan_.edge_count());
  while (plan_.more_to_do()) {
    while (command_runner_->CanRunMore()) {
      Edge* edge = plan_.FindWork();
      if (!edge)
        break;

      if (!StartEdge(edge, err))
        return false;

      if (edge->rule_ == &State::kPhonyRule)
        FinishEdge(edge);
    }

    bool success;
    if (Edge* edge = command_runner_->NextFinishedCommand(&success)) {
      if (!success) {
        *err = "subcommand failed";
        return false;
      }
      FinishEdge(edge);
    } else {
      if (!command_runner_->WaitForCommands()) {
        *err = "stuck [this is a bug]";
        return false;
      }
    }
  }

  return true;
}

bool Builder::StartEdge(Edge* edge, string* err) {
  status_->BuildEdgeStarted(edge);

  if (edge->rule_ == &State::kPhonyRule)
    return true;

  // Create directories necessary for outputs.
  // XXX: this will block; do we care?
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    if (!disk_interface_->MakeDirs((*i)->file_->path_))
      return false;
  }

  // Compute command and start it.
  string command = edge->EvaluateCommand();
  if (!command_runner_->StartCommand(edge)) {
    err->assign("command '" + command + "' failed.");
    return false;
  }

  return true;
}

void Builder::FinishEdge(Edge* edge) {
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    // XXX check that the output actually changed
    // XXX just notify node and have it propagate?
    (*i)->dirty_ = false;
  }
  plan_.EdgeFinished(edge);
  status_->BuildEdgeFinished(edge);
  log_->RecordCommand(edge, 0);  // XXX get edge timing.
}
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2015, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file DccDebugFlow.hxx
 *
 * Component useful for debugging DCC packet reception/decoding code.
 *
 * @author Balazs Racz
 * @date 13 Dec 2015
 */

#ifndef _NMRANET_DCCDEBUGFLOW_HXX_
#define _NMRANET_DCCDEBUGFLOW_HXX_

namespace nmranet {

class DccPacketDebugFlow : public StateFlow<Buffer<dcc::Packet>, QList<1>> {
 public:
  DccPacketDebugFlow(nmranet::Node* node)
      : StateFlow<Buffer<dcc::Packet>, QList<1>>(
            node->iface()->dispatcher()->service()),
        node_(node) {}

 private:
  Action entry() override {
    Debug::DccPacketDelay::set(false);
    return allocate_and_call(node_->iface()->global_message_write_flow(),
                             STATE(msg_allocated));
  }

  Action msg_allocated() {
    auto* b =
        get_allocation_result(node_->iface()->global_message_write_flow());

    b->data()->reset(
        static_cast<nmranet::Defs::MTI>(nmranet::Defs::MTI_XPRESSNET + 1),
        node_->node_id(),
        string((char*)message()->data()->payload, message()->data()->dlc));
    node_->iface()->global_message_write_flow()->send(b);
    return release_and_exit();
  }

  nmranet::Node* node_;
};

class DccDecodeFlow : public dcc::DccDecodeFlow {
 public:
  DccDecodeFlow() : dcc::DccDecodeFlow(&g_service, "/dev/nrz0") {}

 private:
  void dcc_packet_finished(const uint8_t* payload, size_t len) override {
    auto* b = g_packet_debug_flow.alloc();
    b->data()->dlc = len;
    memcpy(b->data()->payload, payload, len);
    g_packet_debug_flow.send(b);
  }

  void mm_packet_finished(const uint8_t* payload, size_t len) override {
    auto* b = g_packet_debug_flow.alloc();
    b->data()->dlc = len;
    memcpy(b->data()->payload, payload, len);
    b->data()->payload[0] |= 0xFC;
    g_packet_debug_flow.send(b);
  }

  void debug_data(uint32_t value) override {
    value /= (configCPU_CLOCK_HZ / 1000000);
    log(decoder_.state());
    log(value);
  }

  void log(uint8_t value) {
    dbuffer[ptr] = value;
    ++ptr;
    if (ptr >= sizeof(dbuffer)) ptr = 0;
  }
  uint8_t dbuffer[1024];
  uint16_t ptr = 0;
};

} // namespace

#endif // _NMRANET_DCCDEBUGFLOW_HXX_
<commit_msg>make flow name more clear.<commit_after>/** \copyright
 * Copyright (c) 2015, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file DccDebugFlow.hxx
 *
 * Component useful for debugging DCC packet reception/decoding code.
 *
 * @author Balazs Racz
 * @date 13 Dec 2015
 */

#ifndef _NMRANET_DCCDEBUGFLOW_HXX_
#define _NMRANET_DCCDEBUGFLOW_HXX_

namespace nmranet {

class DccPacketDebugFlow : public StateFlow<Buffer<dcc::Packet>, QList<1>> {
 public:
  DccPacketDebugFlow(nmranet::Node* node)
      : StateFlow<Buffer<dcc::Packet>, QList<1>>(
            node->iface()->dispatcher()->service()),
        node_(node) {}

 private:
  Action entry() override {
    Debug::DccPacketDelay::set(false);
    return allocate_and_call(node_->iface()->global_message_write_flow(),
                             STATE(msg_allocated));
  }

  Action msg_allocated() {
    auto* b =
        get_allocation_result(node_->iface()->global_message_write_flow());

    b->data()->reset(
        static_cast<nmranet::Defs::MTI>(nmranet::Defs::MTI_XPRESSNET + 1),
        node_->node_id(),
        string((char*)message()->data()->payload, message()->data()->dlc));
    node_->iface()->global_message_write_flow()->send(b);
    return release_and_exit();
  }

  nmranet::Node* node_;
};

class DccDebugDecodeFlow : public dcc::DccDecodeFlow {
 public:
  DccDebugDecodeFlow(Service* service, const char* path) : dcc::DccDecodeFlow(service, path) {}

 private:
  void dcc_packet_finished(const uint8_t* payload, size_t len) override {
    auto* b = g_packet_debug_flow.alloc();
    b->data()->dlc = len;
    memcpy(b->data()->payload, payload, len);
    g_packet_debug_flow.send(b);
  }

  void mm_packet_finished(const uint8_t* payload, size_t len) override {
    auto* b = g_packet_debug_flow.alloc();
    b->data()->dlc = len;
    memcpy(b->data()->payload, payload, len);
    b->data()->payload[0] |= 0xFC;
    g_packet_debug_flow.send(b);
  }

  void debug_data(uint32_t value) override {
    value /= (configCPU_CLOCK_HZ / 1000000);
    log(decoder_.state());
    log(value);
  }

  void log(uint8_t value) {
    dbuffer[ptr] = value;
    ++ptr;
    if (ptr >= sizeof(dbuffer)) ptr = 0;
  }
  uint8_t dbuffer[1024];
  uint16_t ptr = 0;
};

} // namespace

#endif // _NMRANET_DCCDEBUGFLOW_HXX_
<|endoftext|>


<commit_before>/********************************************************************
 * Author:  Carlos Moreno
 * Created: 2015-06-04
 *
 * Description:
 *
 *      This is a sample code to connect to a server through TCP.
 *      You are allowed to use this as a sample / starting point
 *      for the assignment (both problems require a program that
 *      connects to something)
 *
 * Copytight and permissions:
 *      This file is for the exclusive purpose of our ECE-458
 *      assignment 2, and you are not allowed to use it for any
 *      other purpose.
 *
 ********************************************************************/

#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cerrno>

#include <inttypes.h>
#include <math.h>
using namespace std;

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <wait.h>
#include <unistd.h>

static __inline__ uint64_t rdtsc();
bool password_ok (const string &pwd);

int main(int argc, char *argv[])
{
	string possiblePwd = "";
	if(argc == 2){
		possiblePwd = argv[1];
	}
	srand(time(NULL));
	bool finished = false;
	int letters = 0;
	if((finished = password_ok (possiblePwd)) == true) cout<<"password correct: " <<possiblePwd <<endl;
	//static const char alphabet[] = "ghijnoptuvwabcxyzdefqrsklm";
	static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
	while(!finished){
		uint64_t timevalues [26] = {};
		uint64_t squarevalues [26] = {};
		int times_picked [26] = {};
		//destroy possible caching
		for(int i = 0; i < 1000000; i++){
			int chosen_char = rand()%(sizeof(alphabet)-1);
			const char &current = alphabet[chosen_char];
			const string &pwd_attempt = possiblePwd + current;
            password_ok (pwd_attempt);

		}
		for(int i = 0; i < 10000000; i++){
            int chosen_char = rand()%(sizeof(alphabet)-1);
            if(i%10 == 0 || i%10 == 9) continue;
			char current = alphabet[chosen_char];

			const string &pwd_attempt = possiblePwd + current;
			uint64_t start = rdtsc();
			finished = password_ok (pwd_attempt);
			uint64_t end = rdtsc();
			if(finished){
				cout<<"password guessed correct: " <<pwd_attempt <<endl;
				return 0;
			}
			uint64_t difference = end - start;
			//cout<< alphabet[chosen_char]<< ": time of " <<difference <<endl;
			timevalues[chosen_char] += difference;
			squarevalues[chosen_char] += (difference*difference);
			times_picked[chosen_char] = times_picked[chosen_char] + 1;

		}
		//initialize to "a"
		double highest_mean = 0.0;
		double highest_var = 0.0;
		char highest_char = 'a';
		double nexthighest_mean = 0.0;
		int highest_picktime = 0;
		for(int i = 0; i < 26; i++){
			double current_mean = (double)timevalues[i] / times_picked[i];
			double current_var = ((double)1/ (double)(times_picked[i] - 1)) * (double)(squarevalues[i] - times_picked[i] * (current_mean * current_mean));
			if(current_mean > nexthighest_mean && current_mean < highest_mean){
				nexthighest_mean = current_mean;
			}
			if(current_mean > highest_mean){
				nexthighest_mean = highest_mean;
				highest_mean = current_mean;
				highest_var = current_var;
				highest_picktime = times_picked[i];
				highest_char = alphabet[i];
			}
			cout<< alphabet[i] <<" mean: " <<current_mean << " ms, \tvariance: " <<current_var << " \tpicked " << times_picked[i] <<" times" <<endl;
		}
		double confidence95 = 1.96*sqrt(highest_var) / sqrt(highest_picktime);
		double confidence99 = 2.58*sqrt(highest_var) / sqrt(highest_picktime);
		cout<< "\nBEST GUESS: " << possiblePwd+highest_char << ", with time: " << highest_mean << " variance: " << highest_var <<endl;
		cout<<"\n95\% confidence interval: " <<highest_mean << " +- " <<confidence95 <<"\n99\% confidence interval: " <<highest_mean << " +- " <<confidence99<< endl;
		cout<<"next longest time: " << nexthighest_mean <<endl;

		if(highest_mean/nexthighest_mean < 1.01 ||confidence99/highest_mean > 0.02 || (highest_mean - confidence99) < nexthighest_mean){
			cout<< "Not confident about attempted password, try a shorter guess?" <<endl;
		}
		return 0;

	}

    return 0;
}

static __inline__ uint64_t rdtsc()
{
	uint32_t hi, lo;
	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
	return ((uint64_t)lo) | (((uint64_t)hi) << 32);
}

bool password_ok (const string &pwd)
{
	return pwd == "mypassword";
    //return strcmp(pwd.c_str(), "mypassword") == 0;
}

<commit_msg>small change in part 2<commit_after>/********************************************************************
 * Author:  Carlos Moreno
 * Created: 2015-06-04
 *
 * Description:
 *
 *      This is a sample code to connect to a server through TCP.
 *      You are allowed to use this as a sample / starting point
 *      for the assignment (both problems require a program that
 *      connects to something)
 *
 * Copytight and permissions:
 *      This file is for the exclusive purpose of our ECE-458
 *      assignment 2, and you are not allowed to use it for any
 *      other purpose.
 *
 ********************************************************************/

#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cerrno>

#include <inttypes.h>
#include <math.h>
using namespace std;

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <wait.h>
#include <unistd.h>

static __inline__ uint64_t rdtsc();
bool password_ok (const string &pwd);

int main(int argc, char *argv[])
{
	string possiblePwd = "";
	if(argc == 2){
		possiblePwd = argv[1];
	}
	srand(time(NULL));
	bool finished = false;
	int letters = 0;
	if((finished = password_ok (possiblePwd)) == true) cout<<"password correct: " <<possiblePwd <<endl;
	//static const char alphabet[] = "ghijnoptuvwabcxyzdefqrsklm";
	static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
	while(!finished){
		uint64_t timevalues [26] = {};
		uint64_t squarevalues [26] = {};
		int times_picked [26] = {};
		//destroy possible caching
		for(int i = 0; i < 100000; i++){
			int chosen_char = rand()%(sizeof(alphabet)-1);
			const char &current = alphabet[chosen_char];
			const string &pwd_attempt = possiblePwd + current;
            password_ok (pwd_attempt);

		}
		srand(time(NULL));
		for(int i = 0; i < 10000000; i++){
            int chosen_char = rand()%(sizeof(alphabet)-1);
			char current = alphabet[chosen_char];

			const string &pwd_attempt = possiblePwd + current;
			uint64_t start = rdtsc();
			finished = password_ok (pwd_attempt);
			uint64_t end = rdtsc();
			if(finished){
				cout<<"password guessed correct: " <<pwd_attempt <<endl;
				return 0;
			}
			uint64_t difference = end - start;
			//cout<< alphabet[chosen_char]<< ": time of " <<difference <<endl;
			timevalues[chosen_char] += difference;
			squarevalues[chosen_char] += (difference*difference);
			times_picked[chosen_char] = times_picked[chosen_char] + 1;

		}
		//initialize to "a"
		double highest_mean = 0.0;
		double highest_var = 0.0;
		char highest_char = 'a';
		double nexthighest_mean = 0.0;
		int highest_picktime = 0;
		for(int i = 0; i < 26; i++){
			double current_mean = (double)timevalues[i] / times_picked[i];
			double current_var = ((double)1/ (double)(times_picked[i] - 1)) * (double)(squarevalues[i] - times_picked[i] * (current_mean * current_mean));
			if(current_mean > nexthighest_mean && current_mean < highest_mean){
				nexthighest_mean = current_mean;
			}
			if(current_mean > highest_mean){
				nexthighest_mean = highest_mean;
				highest_mean = current_mean;
				highest_var = current_var;
				highest_picktime = times_picked[i];
				highest_char = alphabet[i];
			}
			cout<< alphabet[i] <<" mean: " <<current_mean << " ms, \tvariance: " <<current_var << " \tpicked " << times_picked[i] <<" times" <<endl;
		}
		double confidence95 = 1.96*sqrt(highest_var) / sqrt(highest_picktime);
		double confidence99 = 2.58*sqrt(highest_var) / sqrt(highest_picktime);
		cout<< "\nBEST GUESS: " << possiblePwd+highest_char << ", with time: " << highest_mean << " variance: " << highest_var <<endl;
		cout<<"\n95\% confidence interval: " <<highest_mean << " +- " <<confidence95 <<"\n99\% confidence interval: " <<highest_mean << " +- " <<confidence99<< endl;
		cout<<"next longest time: " << nexthighest_mean <<endl;

		if(highest_mean/nexthighest_mean < 1.01 ||confidence99/highest_mean > 0.02 || (highest_mean - confidence99) < nexthighest_mean){
			cout<< "Not confident about attempted password, try a shorter guess?" <<endl;
		}
		return 0;

	}

    return 0;
}

static __inline__ uint64_t rdtsc()
{
	uint32_t hi, lo;
	__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
	return ((uint64_t)lo) | (((uint64_t)hi) << 32);
}

bool password_ok (const string &pwd)
{
	return pwd == "mypassword";
    //return strcmp(pwd.c_str(), "mypassword") == 0;
}

<|endoftext|>


<commit_before>/*
 *  Copyright 2007-2018 by the individuals mentioned in the source code history
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "omxExpectation.h"
#include "omxFitFunction.h"
#include "omxDefines.h"
#include "EnableWarnings.h"

struct omxNormalExpectation : public omxExpectation {

	omxMatrix *cov, *means; // observed covariance and means
	omxMatrix *thresholds; // same as thresholdsMat? TODO

	double logDetObserved;
	double n;

	virtual void init();
	virtual void compute(FitContext *fc, const char *what, const char *how);
	virtual void populateAttr(SEXP expectation);
	virtual omxMatrix *getComponent(const char*);
};

void omxNormalExpectation::compute(FitContext *fc, const char *, const char *) {
	omxNormalExpectation* one = this;

	omxRecompute(one->cov, fc);
	if(one->means != NULL)
	    omxRecompute(one->means, fc);
	if (one->thresholds) omxRecompute(one->thresholds, fc);
}

void omxNormalExpectation::populateAttr(SEXP algebra) {
    if(OMX_DEBUG) { mxLog("Populating Normal Attributes."); }

	omxRecompute(cov, NULL);
	if(means != NULL) omxRecompute(means, NULL);

	{
		SEXP expCovExt;
	ScopedProtect p1(expCovExt, Rf_allocMatrix(REALSXP, cov->rows, cov->cols));
	for(int row = 0; row < cov->rows; row++)
		for(int col = 0; col < cov->cols; col++)
			REAL(expCovExt)[col * cov->rows + row] =
				omxMatrixElement(cov, row, col);
	Rf_setAttrib(algebra, Rf_install("ExpCov"), expCovExt);
	}

	if (means != NULL) {
		SEXP expMeanExt;
		ScopedProtect p1(expMeanExt, Rf_allocMatrix(REALSXP, means->rows, means->cols));
		for(int row = 0; row < means->rows; row++)
			for(int col = 0; col < means->cols; col++)
				REAL(expMeanExt)[col * means->rows + row] =
					omxMatrixElement(means, row, col);
		Rf_setAttrib(algebra, Rf_install("ExpMean"), expMeanExt);
	} else {
		SEXP expMeanExt;
		ScopedProtect p1(expMeanExt, Rf_allocMatrix(REALSXP, 0, 0));
		Rf_setAttrib(algebra, Rf_install("ExpMean"), expMeanExt);
	}

	ProtectedSEXP RnumStats(Rf_ScalarReal(omxDataDF(data)));
	Rf_setAttrib(algebra, Rf_install("numStats"), RnumStats);
}

omxExpectation *omxInitNormalExpectation() { return new omxNormalExpectation; }

void omxNormalExpectation::init()
{
    if(OMX_DEBUG) { mxLog("Initializing Normal expectation."); }

    omxNormalExpectation *one = this;

	/* Set up expectation structures */
	if(OMX_DEBUG) { mxLog("Processing cov."); }
	one->cov = omxNewMatrixFromSlot(rObj, currentState, "covariance");

	if(OMX_DEBUG) { mxLog("Processing Means."); }
	one->means = omxNewMatrixFromSlot(rObj, currentState, "means");

	one->thresholds = omxNewMatrixFromSlot(rObj, currentState, "thresholds");
}

omxMatrix* omxNormalExpectation::getComponent(const char* component){
/* Return appropriate parts of Expectation to the Fit Function */
	if(OMX_DEBUG) { mxLog("Normal expectation: %s requested--", component); }

	omxNormalExpectation* one = this;
	omxMatrix* retval = NULL;

	if(strEQ("cov", component)) {
		retval = one->cov;
	} else if(strEQ("means", component)) {
		retval = one->means;
	} else if(strEQ("pvec", component)) {
		// Once implemented, change compute function and return pvec
	}
	if (retval) omxRecompute(retval, NULL);

	return retval;
}
<commit_msg>Remove redundent copy of thresholds<commit_after>/*
 *  Copyright 2007-2018 by the individuals mentioned in the source code history
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "omxExpectation.h"
#include "omxFitFunction.h"
#include "omxDefines.h"
#include "EnableWarnings.h"

struct omxNormalExpectation : public omxExpectation {

	omxMatrix *cov, *means; // observed covariance and means

	double logDetObserved;
	double n;

	virtual void init();
	virtual void compute(FitContext *fc, const char *what, const char *how);
	virtual void populateAttr(SEXP expectation);
	virtual omxMatrix *getComponent(const char*);
};

void omxNormalExpectation::compute(FitContext *fc, const char *, const char *) {
	omxNormalExpectation* one = this;

	omxRecompute(one->cov, fc);
	if(one->means != NULL)
	    omxRecompute(one->means, fc);
	if (one->thresholdsMat) omxRecompute(one->thresholdsMat, fc);
}

void omxNormalExpectation::populateAttr(SEXP algebra) {
    if(OMX_DEBUG) { mxLog("Populating Normal Attributes."); }

	omxRecompute(cov, NULL);
	if(means != NULL) omxRecompute(means, NULL);

	{
		SEXP expCovExt;
	ScopedProtect p1(expCovExt, Rf_allocMatrix(REALSXP, cov->rows, cov->cols));
	for(int row = 0; row < cov->rows; row++)
		for(int col = 0; col < cov->cols; col++)
			REAL(expCovExt)[col * cov->rows + row] =
				omxMatrixElement(cov, row, col);
	Rf_setAttrib(algebra, Rf_install("ExpCov"), expCovExt);
	}

	if (means != NULL) {
		SEXP expMeanExt;
		ScopedProtect p1(expMeanExt, Rf_allocMatrix(REALSXP, means->rows, means->cols));
		for(int row = 0; row < means->rows; row++)
			for(int col = 0; col < means->cols; col++)
				REAL(expMeanExt)[col * means->rows + row] =
					omxMatrixElement(means, row, col);
		Rf_setAttrib(algebra, Rf_install("ExpMean"), expMeanExt);
	} else {
		SEXP expMeanExt;
		ScopedProtect p1(expMeanExt, Rf_allocMatrix(REALSXP, 0, 0));
		Rf_setAttrib(algebra, Rf_install("ExpMean"), expMeanExt);
	}

	ProtectedSEXP RnumStats(Rf_ScalarReal(omxDataDF(data)));
	Rf_setAttrib(algebra, Rf_install("numStats"), RnumStats);
}

omxExpectation *omxInitNormalExpectation() { return new omxNormalExpectation; }

void omxNormalExpectation::init()
{
    if(OMX_DEBUG) { mxLog("Initializing Normal expectation."); }

    omxNormalExpectation *one = this;

	/* Set up expectation structures */
	if(OMX_DEBUG) { mxLog("Processing cov."); }
	one->cov = omxNewMatrixFromSlot(rObj, currentState, "covariance");

	if(OMX_DEBUG) { mxLog("Processing Means."); }
	one->means = omxNewMatrixFromSlot(rObj, currentState, "means");
}

omxMatrix* omxNormalExpectation::getComponent(const char* component){
/* Return appropriate parts of Expectation to the Fit Function */
	if(OMX_DEBUG) { mxLog("Normal expectation: %s requested--", component); }

	omxNormalExpectation* one = this;
	omxMatrix* retval = NULL;

	if(strEQ("cov", component)) {
		retval = one->cov;
	} else if(strEQ("means", component)) {
		retval = one->means;
	} else if(strEQ("pvec", component)) {
		// Once implemented, change compute function and return pvec
	}
	if (retval) omxRecompute(retval, NULL);

	return retval;
}
<|endoftext|>